Clone of official tools
Diff: memap.py
- Revision:
- 22:9e85236d8716
- Parent:
- 13:ab47a20b66f0
- Child:
- 24:25bff2709c20
--- a/memap.py Fri Jul 15 22:58:15 2016 +0100 +++ b/memap.py Sat Jul 16 00:34:03 2016 +0100 @@ -10,6 +10,7 @@ import csv import json import argparse +from utils import argparse_uppercase_type, argparse_lowercase_hyphen_type, argparse_filestring_type from prettytable import PrettyTable debug = False @@ -26,9 +27,9 @@ self.misc_flash_sections = ('.interrupts', '.flash_config') - self.other_sections = ('.interrupts_ram', '.init', '.ARM.extab', \ - '.ARM.exidx', '.ARM.attributes', '.eh_frame', \ - '.init_array', '.fini_array', '.jcr', '.stab', \ + self.other_sections = ('.interrupts_ram', '.init', '.ARM.extab', + '.ARM.exidx', '.ARM.attributes', '.eh_frame', + '.init_array', '.fini_array', '.jcr', '.stab', '.stabstr', '.ARM.exidx', '.ARM') # sections to print info (generic for all toolchains) @@ -43,6 +44,9 @@ # list of all object files and mappting to module names self.object_to_module = dict() + # Memory usage summary structure + self.mem_summary = dict() + def module_add(self, module_name, size, section): """ Adds a module / section to the list @@ -67,7 +71,7 @@ return i # should name of the section (assuming it's a known one) if line.startswith('.'): - return 'unknown' # all others are clasified are unknown + return 'unknown' # all others are classified are unknown else: return False # everything else, means no change in section @@ -336,6 +340,8 @@ else: self.object_to_module.update({object_name:module_name}) + export_formats = ["json", "csv-ci", "table"] + def generate_output(self, export_format, file_output=None): """ Generates summary of memory map data @@ -363,11 +369,12 @@ # Create table columns = ['Module'] - for i in list(self.print_sections): - columns.append(i) + columns.extend(self.print_sections) table = PrettyTable(columns) table.align["Module"] = "l" + for col in self.print_sections: + table.align[col] = 'r' for i in list(self.print_sections): table.align[i] = 'r' @@ -388,8 +395,12 @@ for k in self.print_sections: row.append(self.modules[i][k]) - json_obj.append({"module":i, "size":{\ - k:self.modules[i][k] for k in self.print_sections}}) + json_obj.append({ + "module":i, + "size":{ + k:self.modules[i][k] for k in self.print_sections + } + }) table.add_row(row) @@ -399,16 +410,19 @@ table.add_row(subtotal_row) + summary = { + 'summary':{ + 'static_ram':(subtotal['.data']+subtotal['.bss']), + 'heap':(subtotal['.heap']), + 'stack':(subtotal['.stack']), + 'total_ram':(subtotal['.data']+subtotal['.bss']+subtotal['.heap']+subtotal['.stack']), + 'total_flash':(subtotal['.text']+subtotal['.data']+misc_flash_mem), + } + } + if export_format == 'json': - json_obj.append({\ - 'summary':{\ - 'total_static_ram':(subtotal['.data']+subtotal['.bss']),\ - 'allocated_heap':(subtotal['.heap']),\ - 'allocated_stack':(subtotal['.stack']),\ - 'total_ram':(subtotal['.data']+subtotal['.bss']+subtotal['.heap']+subtotal['.stack']),\ - 'total_flash':(subtotal['.text']+subtotal['.data']+misc_flash_mem),}}) - - file_desc.write(json.dumps(json_obj, indent=4)) + json_to_file = json_obj + [summary] + file_desc.write(json.dumps(json_to_file, indent=4)) file_desc.write('\n') elif export_format == 'csv-ci': # CSV format for the CI system @@ -467,33 +481,40 @@ if file_desc is not sys.stdout: file_desc.close() + self.mem_summary = json_obj + [summary] + return True + def get_memory_summary(self): + """! Object is available only after self.generate_output('json') is called + @return Return memory summary object + """ + return self.mem_summary + + toolchains = ["ARM", "ARM_STD", "ARM_MICRO", "GCC_ARM", "IAR"] + def parse(self, mapfile, toolchain): """ Parse and decode map file depending on the toolchain """ + result = True try: - file_input = open(mapfile, 'rt') + with open(mapfile, 'rt') as file_input: + if toolchain == "ARM" or toolchain == "ARM_STD" or toolchain == "ARM_MICRO": + self.search_objects(os.path.abspath(mapfile), "ARM") + self.parse_map_file_armcc(file_input) + elif toolchain == "GCC_ARM": + self.parse_map_file_gcc(file_input) + elif toolchain == "IAR": + self.search_objects(os.path.abspath(mapfile), toolchain) + self.parse_map_file_iar(file_input) + else: + result = False except IOError as error: print "I/O error({0}): {1}".format(error.errno, error.strerror) - return False - - if toolchain == "ARM" or toolchain == "ARM_STD" or toolchain == "ARM_MICRO": - self.search_objects(os.path.abspath(mapfile), "ARM") - self.parse_map_file_armcc(file_input) - elif toolchain == "GCC_ARM": - self.parse_map_file_gcc(file_input) - elif toolchain == "IAR": - self.search_objects(os.path.abspath(mapfile), toolchain) - self.parse_map_file_iar(file_input) - else: - return False - - file_input.close() - - return True + result = False + return result def main(): @@ -502,15 +523,15 @@ # Parser handling parser = argparse.ArgumentParser(description="Memory Map File Analyser for ARM mbed\nversion %s" % version) - parser.add_argument('file', help='memory map file') + parser.add_argument('file', type=argparse_filestring_type, help='memory map file') - parser.add_argument('-t', '--toolchain', dest='toolchain', help='select a toolchain used to build the memory map file (ARM, GCC_ARM, IAR)',\ - required=True) + parser.add_argument('-t', '--toolchain', dest='toolchain', help='select a toolchain used to build the memory map file (%s)' % ", ".join(MemapParser.toolchains),\ + required=True, type=argparse_uppercase_type(MemapParser.toolchains, "toolchain")) parser.add_argument('-o', '--output', help='output file name', required=False) - parser.add_argument('-e', '--export', dest='export', required=False,\ - help="export format (examples: 'json', 'csv-ci', 'table': default)") + parser.add_argument('-e', '--export', dest='export', required=False, default='table', type=argparse_lowercase_hyphen_type(MemapParser.export_formats,'export format'),\ + help="export format (examples: %s: default)" % ", ".join(MemapParser.export_formats)) parser.add_argument('-v', '--version', action='version', version=version) @@ -528,13 +549,8 @@ # Parse and decode a map file if args.file and args.toolchain: if memap.parse(args.file, args.toolchain) is False: - print "Unknown toolchain for memory statistics %s" % args.toolchain sys.exit(0) - # default export format is table - if not args.export: - args.export = 'table' - # Write output in file if args.output != None: memap.generate_output(args.export, args.output)