mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
On my laptop, a few symbol names raise errors as invalid when attempting to demangle them. This should not stop the rest of the symbol table from building.
75 lines
1.9 KiB
Python
Executable File
75 lines
1.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Generate the jsix style symbol table. The format in memory of this table
|
|
# is as follows:
|
|
#
|
|
# <num_entires> : 8 bytes
|
|
# <index> : 16 * N bytes
|
|
# <name data> : variable
|
|
#
|
|
# Each index entry has the format
|
|
# <symbol address> : 8 bytes
|
|
# <offset of name> : 8 bytes
|
|
#
|
|
# Name offsets are from the start of the symbol table as a whole. (ie,
|
|
# where <num_entries> is located.)
|
|
|
|
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)."""
|
|
|
|
from cxxfilt import demangle, InvalidName
|
|
|
|
syms = []
|
|
for line in sys.stdin:
|
|
addr, t, mangled = line.split()
|
|
if t not in "tTvVwW": continue
|
|
|
|
try:
|
|
addr = int(addr, base=16)
|
|
name = demangle(mangled)
|
|
syms.append((addr, name))
|
|
except InvalidName:
|
|
pass
|
|
|
|
return sorted(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("@QQ") * len(syms), 1)
|
|
nul = b'\0'
|
|
|
|
positions = {}
|
|
for s in syms:
|
|
addr, name = s
|
|
positions[addr] = outfile.tell()
|
|
|
|
data = name.encode('utf-8')
|
|
outfile.write(name.encode('utf-8'))
|
|
outfile.write(nul)
|
|
|
|
outfile.seek(index_pos)
|
|
for s in syms:
|
|
addr = s[0]
|
|
pos = positions[addr]
|
|
outfile.write(struct.pack("@QQ", addr, pos))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
if len(sys.argv) != 2:
|
|
print(f"Usage: {sys.argv[0]} <output>")
|
|
sys.exit(1)
|
|
|
|
outfile = open(sys.argv[1], "wb")
|
|
write_table(parse_syms(sys.stdin), outfile)
|