#!/usr/bin/env python3 # # Generate the jsix style symbol table. The format in memory of this table # is as follows: # # : 8 bytes # : 24 * N bytes # : variable # # Each index entry has the format # : 8 bytes # : 8 bytes # : 8 bytes # # Name offsets are from the start of the symbol table as a whole. (ie, # where is located.) import re sym_re = re.compile(r'([0-9a-fA-F]{16}) ([0-9a-fA-F]{16}) [tTvVwW] (.*)') def parse_syms(infile): """Take the output of the `nm` command, and parse it into a tuple representing the symbols in the text segment of the binary. Returns a list of (address, symbol_name).""" syms = [] for line in sys.stdin: match = sym_re.match(line) if not match: continue addr = int(match.group(1), base=16) size = int(match.group(2), base=16) name = match.group(3) syms.append([addr, size, name, 0]) return syms def write_table(syms, outfile): """Write the given symbol table as generated by parse_syms() to the outfile, index first, and then name character data.""" import struct outfile.write(struct.pack("@Q", len(syms))) index_pos = outfile.tell() outfile.seek(struct.calcsize("@QQQ") * len(syms), 1) nul = b'\0' for s in syms: s[3] = outfile.tell() outfile.write(s[2].encode('utf-8')) outfile.write(nul) outfile.seek(index_pos) for s in syms: addr = s[0] size = s[1] pos = s[3] outfile.write(struct.pack("@QQQ", addr, size, pos)) if __name__ == "__main__": import sys if len(sys.argv) != 2: print(f"Usage: nm -n -S --demangle | {sys.argv[0]} ") sys.exit(1) outfile = open(sys.argv[1], "wb") write_table(parse_syms(sys.stdin), outfile)