Skip to content

Instantly share code, notes, and snippets.

@lilliemarck
Last active August 29, 2015 14:01
Show Gist options
  • Save lilliemarck/64dc1eb777fbb99b91ef to your computer and use it in GitHub Desktop.
Save lilliemarck/64dc1eb777fbb99b91ef to your computer and use it in GitHub Desktop.
Parses nm output and groups together templates with the same name
import argparse
import fileinput
import re
import sqlite3
import sys
class Symbol:
def __init__(self, name, size, type, template):
self.name = name
self.size = size
self.type = type
self.template = template
symbols = []
def parse_template_name(symbol):
"""Return the bare name or None if not a template."""
name = ""
is_template = False
targ_depth = 0
c_prev = None
for c in symbol:
if targ_depth == 0:
if c == '<':
if re.match("(.*[^0-9A-Za-z_])?operator<?$", name):
name += c
else:
is_template = True
targ_depth += 1
elif c == '(' or c == '[':
break
elif c == ' ':
if re.match("(.*[^0-9A-Za-z_])?operator(\"\")?$", name):
name += c
c = None
else:
if (c_prev == ' '):
name = c
else:
name += c
else:
if c == '<':
targ_depth += 1
elif c == '>':
targ_depth -= 1
c_prev = c
if not is_template:
return None
return name
def parse_nm_line(line):
"""Parse a line of nm output store in the global symbols variables."""
match = re.match("[0-9A-Fa-f]+ (?P<size>[0-9A-Fa-f]+) (?P<type>\w) (?P<name>.+)", line)
if not match:
return
name = match.group("name");
size = int(match.group("size"), base=16)
type = match.group("type")
template = parse_template_name(name)
symbols.append(Symbol(name, size, type, template))
def total_size(symbols):
size = 0
for symbol in symbols:
size += symbol.size
return size
parser = argparse.ArgumentParser(description="Reads the output of 'nm -CS ...' and groups symbols together with their templates.")
parser.add_argument('file', nargs='?', help="read from a file instead of stdin")
parser.add_argument('--sqlite3', metavar='FILE', help="create an SQlite 3 database")
args = parser.parse_args()
if args.file:
with open(args.file) as file:
for line in file:
parse_nm_line(line)
else:
for line in sys.stdin:
parse_nm_line(line)
if args.sqlite3:
conn = sqlite3.connect(args.sqlite3)
conn.execute("CREATE TABLE IF NOT EXISTS symbols (template TEXT, size INTEGER, name TEXT)")
conn.execute("DELETE FROM symbols")
for symbol in symbols:
conn.execute("INSERT INTO symbols VALUES(?, ?, ?)", (symbol.template, symbol.size, symbol.name))
conn.commit()
conn.close()
else:
templates = {}
for symbol in symbols:
if symbol.template:
template_symbols = templates.get(symbol.template)
if not template_symbols:
template_symbols = []
templates[symbol.template] = template_symbols
template_symbols.append(symbol)
for name, symbols in templates.items():
print(str(total_size(symbols)) + " " + name)
for symbol in symbols:
print(" " + str(symbol.size) + " " + symbol.type + " " + symbol.name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment