Merge pull request #2918 from theotherjimmy/memap-improvements

Allow max-depth specification in memap
pull/2958/head
Sam Grove 2016-10-06 15:57:39 -05:00 committed by GitHub
commit 41323855ec
1 changed files with 42 additions and 43 deletions

View File

@ -20,6 +20,7 @@ RE_ARMCC = re.compile(
RE_IAR = re.compile( RE_IAR = re.compile(
r'^\s+(.+)\s+(zero|const|ro code|inited|uninit)\s' r'^\s+(.+)\s+(zero|const|ro code|inited|uninit)\s'
r'+0x(\w{8})\s+0x(\w+)\s+(.+)\s.+$') r'+0x(\w{8})\s+0x(\w+)\s+(.+)\s.+$')
RE_LIB_MATCH = re.compile("^.*/(.*\.a)\((.*)\)$")
class MemapParser(object): class MemapParser(object):
"""An object that represents parsed results, parses the memory map files, """An object that represents parsed results, parses the memory map files,
@ -37,13 +38,16 @@ class MemapParser(object):
# sections to print info (generic for all toolchains) # sections to print info (generic for all toolchains)
sections = ('.text', '.data', '.bss', '.heap', '.stack') sections = ('.text', '.data', '.bss', '.heap', '.stack')
MAXDEPTH = object()
def __init__(self, detailed_misc=False): def __init__(self, depth=2):
""" General initialization """ General initialization
""" """
#
self.detailed_misc = detailed_misc self.depth = depth
self.mapfile = None
# list of all modules and their sections # list of all modules and their sections
self.modules = dict() self.modules = dict()
@ -98,7 +102,7 @@ class MemapParser(object):
else: else:
return False # everything else, means no change in section return False # everything else, means no change in section
def path_object_to_module_name(self, txt): def path_object_to_module_name(self, txt):
""" Parse a path to object file to extract it's module and object data """ Parse a path to object file to extract it's module and object data
@ -107,32 +111,25 @@ class MemapParser(object):
""" """
txt = txt.replace('\\', '/') txt = txt.replace('\\', '/')
rex_mbed_os_name = r'^.+mbed-os\/(.+)\/(.+\.o)$' name = txt.split('/')
test_rex_mbed_os_name = re.match(rex_mbed_os_name, txt) mapfile_beginning = os.path.dirname(self.mapfile).split('/')
if name[0] == "." or name[0] == "":
if test_rex_mbed_os_name: name = name[1:]
for thing in mapfile_beginning:
object_name = test_rex_mbed_os_name.group(2) if name[0] == thing:
data = test_rex_mbed_os_name.group(1).split('/') name = name[1:]
ndata = len(data) elif name[0] in mapfile_beginning:
pass
if ndata == 1:
module_name = data[0]
else: else:
module_name = data[0] + '/' + data[1] break
if name[0] == "mbed-os":
return [module_name, object_name] name = name[1:]
if name[0] == "features":
elif self.detailed_misc: name = name[1:]
rex_obj_name = r'^.+\/(.+\.o\)*)$' is_lib = RE_LIB_MATCH.match(txt)
test_rex_obj_name = re.match(rex_obj_name, txt) if is_lib:
if test_rex_obj_name: name = ["libraries", is_lib.group(1), is_lib.group(2)]
object_name = test_rex_obj_name.group(1) return "/".join(name), name[-1]
return ['Misc/' + object_name, ""]
return ['Misc', ""]
else:
return ['Misc', ""]
def parse_section_gcc(self, line): def parse_section_gcc(self, line):
""" Parse data from a section of gcc map file """ Parse data from a section of gcc map file
@ -367,15 +364,7 @@ class MemapParser(object):
path = path.replace('\\', '/') path = path.replace('\\', '/')
# check location of map file search_path = os.path.dirname(path)
rex = r'^(.+)' + r'\/(.+\.map)$'
test_rex = re.match(rex, path)
if test_rex:
search_path = test_rex.group(1) + '/mbed-os/'
else:
print "Warning: this doesn't look like an mbed project"
return
for root, _, obj_files in os.walk(search_path): for root, _, obj_files in os.walk(search_path):
for obj_file in obj_files: for obj_file in obj_files:
@ -490,11 +479,19 @@ class MemapParser(object):
for i in list(self.print_sections): for i in list(self.print_sections):
table.align[i] = 'r' table.align[i] = 'r'
local_modules = {}
for i in sorted(self.modules): for i in sorted(self.modules):
module_name = "/".join(i.split("/")[:self.depth])
local_modules.setdefault(module_name,
{k: 0 for k in self.print_sections})
for k in self.print_sections:
local_modules[module_name][k] += self.modules[i][k]
for i in sorted(local_modules.keys()):
row = [i] row = [i]
for k in self.print_sections: for k in self.print_sections:
row.append(self.modules[i][k]) row.append(local_modules[i][k])
table.add_row(row) table.add_row(row)
@ -575,6 +572,8 @@ class MemapParser(object):
toolchain - the toolchain used to create the file toolchain - the toolchain used to create the file
""" """
self.mapfile = mapfile
result = True result = True
try: try:
with open(mapfile, 'r') as file_input: with open(mapfile, 'r') as file_input:
@ -589,9 +588,8 @@ class MemapParser(object):
self.parse_map_file_iar(file_input) self.parse_map_file_iar(file_input)
else: else:
result = False result = False
self.compute_report() self.compute_report()
except IOError as error: except IOError as error:
print "I/O error({0}): {1}".format(error.errno, error.strerror) print "I/O error({0}): {1}".format(error.errno, error.strerror)
result = False result = False
@ -631,6 +629,7 @@ def main():
parser.add_argument('-d', '--detailed', action='store_true', help='Displays the elements in "Misc" in a detailed fashion', required=False) parser.add_argument('-d', '--detailed', action='store_true', help='Displays the elements in "Misc" in a detailed fashion', required=False)
parser.add_argument('--max-depth', dest='max_depth', type=int, help='Displays the elements in "Misc" in a detailed fashion', required=False, default=None)
# Parse/run command # Parse/run command
if len(sys.argv) <= 1: if len(sys.argv) <= 1:
parser.print_help() parser.print_help()
@ -640,7 +639,7 @@ def main():
args = parser.parse_args() args = parser.parse_args()
# Create memap object # Create memap object
memap = MemapParser(detailed_misc=args.detailed) memap = MemapParser(depth=(args.max_depth or (MemapParser.MAXDEPTH if args.detailed else 2)))
# Parse and decode a map file # Parse and decode a map file
if args.file and args.toolchain: if args.file and args.toolchain: