7""" Gather the build_id, prefix_dir, and exec_name given the path to executable
8 also copies to the specified destination.
10 The structure of debug symbols is as follows:
11 .build-id/<prefix>/<exec_name>[.debug]
26def HashFile(filepath):
27 """Calculates the hash of a file without reading it all in memory at once."""
28 digest = hashlib.sha1()
29 with open(filepath,
'rb')
as f:
31 chunk = f.read(1024 * 1024)
35 return digest.hexdigest()
39 with open(fname,
'a'):
44 sha1_pattern = re.compile(
r'[0-9a-fA-F\-]+')
45 file_out = subprocess.check_output([read_elf,
'-n', exec_path])
46 build_id_line = file_out.splitlines()[-1].split()
47 if (build_id_line[0] != b
'Build' or build_id_line[1] != b
'ID:' or
48 not sha1_pattern.match(str(build_id_line[-1]))
or not len(build_id_line[-1]) > 2):
50 'Expected the last line of llvm-readelf to match "Build ID <Hex String>" Got: %s' % file_out
53 build_id = build_id_line[-1]
55 'build_id': build_id.decode(
'utf-8'),
'prefix_dir': build_id[:2].
decode(
'utf-8'),
56 'exec_name': build_id[2:].
decode(
'utf-8')
61 parser = argparse.ArgumentParser()
68 help=
'This is the name of the executable that we wish to layout debug symbols for.'
75 help=
'Path to the executable on the filesystem.'
82 help=
'Path to the base directory where the debug symbols are to be laid out.'
89 help=
'Executable at the specified path is stripped.'
95 help=
'Executable at the specified path is unstripped.'
102 help=
'Path to read-elf executable.'
105 args = parser.parse_args()
106 assert os.path.exists(args.exec_path), (
'exec_path "%s" does not exist' % args.exec_path)
107 assert os.path.exists(args.dest), (
'dest "%s" does not exist' % args.dest)
108 assert os.path.exists(args.read_elf), (
'read_elf "%s" does not exist' % args.read_elf)
111 dbg_prefix_base = os.path.join(args.dest, parts[
'prefix_dir'])
116 os.makedirs(dbg_prefix_base)
118 if e.errno != errno.EEXIST:
121 if not os.path.exists(dbg_prefix_base):
122 print(
'Unable to create directory: %s.' % dbg_prefix_base)
126 if not args.stripped:
127 dbg_suffix =
'.debug'
128 dbg_file_name =
'%s%s' % (parts[
'exec_name'], dbg_suffix)
129 dbg_file_path = os.path.join(dbg_prefix_base, dbg_file_name)
133 if os.path.exists(dbg_file_path)
and HashFile(args.exec_path) ==
HashFile(dbg_file_path):
136 shutil.copyfile(args.exec_path, dbg_file_path)
139 completion_file = os.path.join(args.dest,
'.%s_dbg_success' % args.exec_name)
140 Touch(completion_file)
145if __name__ ==
'__main__':
def GetBuildIdParts(exec_path, read_elf)
def print(*args, **kwargs)
static DecodeResult decode(std::string path)