5 sym_line = re.compile(r"^(?P<addr>[0-9a-f]+)\s[a-z]\s+F\s+\.[a-z._]+\s+[0-9a-f]+(?P<label>.+)$")
7 def main(kbin, sym_out, endianness='little', bits=32, just_print=False):
9 assert (1 << int(math.log2(bits))) == bits
12 result = subprocess.run(["objdump", "--syms", kbin],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
13 if result.returncode != 0:
17 def to_native(val: int):
18 return val.to_bytes(b_len, endianness, signed=False)
20 output = result.stdout.split(b'\n')
27 mo = sym_line.match(l)
32 addr = int(mg["addr"], 16)
33 label = mg["label"].strip() + '\0'
35 functions.append((addr, label))
37 functions = sorted(functions, key=lambda x: x[0])
40 for (a, l) in functions:
46 # unsigned int label_off;
48 sym_struct_sz = b_len * 2
49 meta_struct_sz = 4 * 2
50 label_off_base = sym_struct_sz * len(functions) + meta_struct_sz
51 alignment = bytearray([b'\0' for _ in range(b_len - 4)])
55 text_region = bytearray()
56 null = bytearray(b'\0')
57 with open(sym_out, mode='wb') as f:
59 # unsigned int num_entry;
60 # unsigned int label_off_base;
62 f.write(to_native(len(functions)))
63 f.write(to_native(label_off_base))
65 for a, l in functions:
67 f.write(to_native(label_off))
70 text_region += bytes(l, 'ascii')
71 aligned_len = (len(l) + bmask) & ~bmask
72 for i in range(aligned_len - len(l)):
73 text_region.append(null[0])
75 label_off += aligned_len
81 if __name__ == "__main__":
82 parser = argparse.ArgumentParser()
83 parser.add_argument('elf_exec')
84 parser.add_argument('-o', '--outfile', required=True)
85 parser.add_argument('--bits', default=32)
86 parser.add_argument('--order', default='little')
87 parser.add_argument('-p', '--just-print', action='store_true')
89 args = parser.parse_args()
91 main(args.elf_exec, args.outfile, endianness=args.order, bits=int(args.bits), just_print=args.just_print)