Format memap

pull/5775/head
Jimmy Brisson 2018-01-02 10:42:29 -06:00
parent 003913b22f
commit fc9bd60d4c
1 changed files with 13 additions and 54 deletions

View File

@ -50,12 +50,11 @@ class MemapParser(object):
sections = ('.text', '.data', '.bss', '.heap', '.stack')
def __init__(self):
""" General initialization
"""
# list of all modules and their sections
self.modules = dict() # full list - doesn't change with depth
self.short_modules = dict() # short version with specific depth
# full list - doesn't change with depth
self.modules = dict()
# short version with specific depth
self.short_modules = dict()
# sections must be defined in this order to take irrelevant out
self.all_sections = self.sections + self.other_sections + \
@ -64,27 +63,27 @@ class MemapParser(object):
# Memory report (sections + summary)
self.mem_report = []
# Just the memory summary section
# Memory summary
self.mem_summary = dict()
# Totals of ".text", ".data" and ".bss"
self.subtotal = dict()
# Flash no associated with a module
self.misc_flash_mem = 0
# Modules passed to the linker on the command line
# this is a dict because modules are looked up by their basename
self.cmd_modules = {}
def module_add(self, object_name, size, section):
""" Adds a module / section to the list
""" Adds a module or section to the list
Positional arguments:
object_name - name of the entry to add
size - the size of the module being added
section - the section the module contributes to
"""
if not object_name or not size or not section:
return
@ -117,7 +116,6 @@ class MemapParser(object):
Positional arguments:
line - the line to check for a new section
"""
for i in self.all_sections:
if line.startswith(i):
# should name of the section (assuming it's a known one)
@ -135,11 +133,9 @@ class MemapParser(object):
Positional arguments:
txt - the path to parse the object and module name from
"""
test_re_mbed_os_name = re.match(RE_OBJECT_FILE_GCC, line)
if test_re_mbed_os_name:
object_name = test_re_mbed_os_name.group(1)
# corner case: certain objects are provided by the GCC toolchain
@ -148,15 +144,12 @@ class MemapParser(object):
return object_name
else:
test_re_obj_name = re.match(RE_LIBRARY_OBJECT_GCC, line)
if test_re_obj_name:
object_name = os.path.join(test_re_obj_name.group(1),
test_re_obj_name.group(2))
return os.path.join('[lib]', object_name)
else:
print "Unknown object name found in GCC map file: %s" % line
return '[misc]'
@ -171,7 +164,6 @@ class MemapParser(object):
Positional arguments:
line - the line to parse a section from
"""
is_fill = re.match(RE_FILL_SECTION_GCC, line)
if is_fill:
o_name = '[fill]'
@ -193,7 +185,6 @@ class MemapParser(object):
Positional arguments:
file_desc - a stream object to parse as a gcc map file
"""
current_section = 'unknown'
with file_desc as infile:
@ -211,7 +202,6 @@ class MemapParser(object):
current_section = next_section
object_name, object_size = self.parse_section_gcc(line)
self.module_add(object_name, object_size, current_section)
common_prefix = os.path.dirname(os.path.commonprefix([
@ -232,9 +222,7 @@ class MemapParser(object):
Positional arguments:
line - the line containing the object or library
"""
# simple object (not library)
if line[-2] == '.' and line[-1] == 'o':
if line.endswith(".o"):
return line
else:
@ -247,8 +235,6 @@ class MemapParser(object):
print "Malformed input found when parsing ARMCC map: %s" % line
return '[misc]'
def parse_section_armcc(self, line):
""" Parse data from an armcc map file
@ -260,11 +246,9 @@ class MemapParser(object):
Positional arguments:
line - the line to parse the section data from
"""
test_re_armcc = re.match(RE_ARMCC, line)
if test_re_armcc:
size = int(test_re_armcc.group(2), 16)
if test_re_armcc.group(4) == 'RO':
@ -283,7 +267,7 @@ class MemapParser(object):
return ["", 0, ""]
# check name of object or library
object_name = self.parse_object_name_armcc(\
object_name = self.parse_object_name_armcc(
test_re_armcc.group(6))
return [object_name, size, section]
@ -297,8 +281,6 @@ class MemapParser(object):
Positional arguments:
line - the line containing the object or library
"""
# simple object (not library)
if object_name.endswith(".o"):
try:
return self.cmd_modules[object_name]
@ -307,7 +289,6 @@ class MemapParser(object):
else:
return '[misc]'
def parse_section_iar(self, line):
""" Parse data from an IAR map file
@ -325,13 +306,8 @@ class MemapParser(object):
Positional_arguments:
line - the line to parse section data from
"""
test_re_iar = re.match(RE_IAR, line)
if test_re_iar:
size = int(test_re_iar.group(4), 16)
if (test_re_iar.group(2) == 'const' or
test_re_iar.group(2) == 'ro code'):
section = '.text'
@ -348,14 +324,16 @@ class MemapParser(object):
section = '.data'
else:
print "Malformed input found when parsing IAR map: %s" % line
return ["", 0, ""]
# lookup object in dictionary and return module name
object_name = self.parse_object_name_iar(test_re_iar.group(5))
size = int(test_re_iar.group(4), 16)
return [object_name, size, section]
else:
return ["", 0, ""] # no valid entry
return ["", 0, ""]
def parse_map_file_armcc(self, file_desc):
""" Main logic to decode armc5 map files
@ -363,9 +341,7 @@ class MemapParser(object):
Positional arguments:
file_desc - a file like object to parse as an armc5 map file
"""
with file_desc as infile:
# Search area to parse
for line in infile:
if line.startswith(' Base Addr Size'):
@ -387,18 +363,13 @@ class MemapParser(object):
new_modules[name] = stats
self.modules = new_modules
def check_new_library_iar(self, line):
"""
Searches for libraries and returns name. Example:
m7M_tls.a: [43]
"""
test_address_line = re.match(RE_LIBRARY_IAR, line)
if test_address_line:
return test_address_line.group(1)
else:
@ -415,9 +386,7 @@ class MemapParser(object):
I64DivZer.o 2
"""
test_address_line = re.match(RE_OBJECT_LIBRARY_IAR, line)
if test_address_line:
return test_address_line.group(1)
else:
@ -447,7 +416,6 @@ class MemapParser(object):
Positional arguments:
file_desc - a file like object to parse as an IAR map file
"""
with file_desc as infile:
self.parse_iar_command_line(infile)
@ -463,7 +431,6 @@ class MemapParser(object):
current_library = ""
for line in infile:
library = self.check_new_library_iar(line)
if library:
@ -475,7 +442,6 @@ class MemapParser(object):
temp = os.path.join('[lib]', current_library, object_name)
self.module_replace(object_name, temp)
def reduce_depth(self, depth):
"""
populates the short_modules attribute with a truncated module list
@ -504,7 +470,6 @@ class MemapParser(object):
self.short_modules[new_name].setdefault(section_idx, 0)
self.short_modules[new_name][section_idx] += self.modules[module_name][section_idx]
export_formats = ["json", "csv-ci", "table"]
def generate_output(self, export_format, depth, file_output=None):
@ -519,10 +484,8 @@ class MemapParser(object):
Returns: generated string for the 'table' format, otherwise None
"""
self.reduce_depth(depth)
self.compute_report()
try:
if file_output:
file_desc = open(file_output, 'wb')
@ -550,7 +513,6 @@ class MemapParser(object):
"""
file_desc.write(json.dumps(self.mem_report, indent=4))
file_desc.write('\n')
return None
def generate_csv(self, file_desc):
@ -577,7 +539,6 @@ class MemapParser(object):
csv_writer.writerow(csv_module_section)
csv_writer.writerow(csv_sizes)
return None
def generate_table(self, file_desc):
@ -659,7 +620,6 @@ class MemapParser(object):
mapfile - the file name of the memory map file
toolchain - the toolchain used to create the file
"""
result = True
try:
with open(mapfile, 'r') as file_input:
@ -679,7 +639,6 @@ class MemapParser(object):
def main():
"""Entry Point"""
version = '0.4.0'
# Parser handling