Last active
August 29, 2015 14:01
-
-
Save lilliemarck/64dc1eb777fbb99b91ef to your computer and use it in GitHub Desktop.
Parses nm output and groups together templates with the same name
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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