Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-sdk-tools by
Diff: memap.py
- Revision:
- 22:9e85236d8716
- Parent:
- 13:ab47a20b66f0
- Child:
- 24:25bff2709c20
diff -r 4fdf0dd04f6f -r 9e85236d8716 memap.py --- 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)