Includes library modifications to allow access to AIN_4 (AIN_0 / 5)

Committer:
bryantaylor
Date:
Tue Sep 20 21:26:12 2016 +0000
Revision:
0:eafc3fd41f75
hackathon

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bryantaylor 0:eafc3fd41f75 1 #!/usr/bin/env python
bryantaylor 0:eafc3fd41f75 2
bryantaylor 0:eafc3fd41f75 3 """Memory Map File Analyser for ARM mbed"""
bryantaylor 0:eafc3fd41f75 4
bryantaylor 0:eafc3fd41f75 5 import sys
bryantaylor 0:eafc3fd41f75 6 import os
bryantaylor 0:eafc3fd41f75 7 import re
bryantaylor 0:eafc3fd41f75 8 import csv
bryantaylor 0:eafc3fd41f75 9 import json
bryantaylor 0:eafc3fd41f75 10 import argparse
bryantaylor 0:eafc3fd41f75 11 from prettytable import PrettyTable
bryantaylor 0:eafc3fd41f75 12
bryantaylor 0:eafc3fd41f75 13 from tools.utils import argparse_filestring_type, \
bryantaylor 0:eafc3fd41f75 14 argparse_lowercase_hyphen_type, argparse_uppercase_type
bryantaylor 0:eafc3fd41f75 15
bryantaylor 0:eafc3fd41f75 16 DEBUG = False
bryantaylor 0:eafc3fd41f75 17 RE_ARMCC = re.compile(
bryantaylor 0:eafc3fd41f75 18 r'^\s+0x(\w{8})\s+0x(\w{8})\s+(\w+)\s+(\w+)\s+(\d+)\s+[*]?.+\s+(.+)$')
bryantaylor 0:eafc3fd41f75 19 RE_IAR = re.compile(
bryantaylor 0:eafc3fd41f75 20 r'^\s+(.+)\s+(zero|const|ro code|inited|uninit)\s'
bryantaylor 0:eafc3fd41f75 21 r'+0x(\w{8})\s+0x(\w+)\s+(.+)\s.+$')
bryantaylor 0:eafc3fd41f75 22
bryantaylor 0:eafc3fd41f75 23 class MemapParser(object):
bryantaylor 0:eafc3fd41f75 24 """An object that represents parsed results, parses the memory map files,
bryantaylor 0:eafc3fd41f75 25 and writes out different file types of memory results
bryantaylor 0:eafc3fd41f75 26 """
bryantaylor 0:eafc3fd41f75 27
bryantaylor 0:eafc3fd41f75 28 print_sections = ('.text', '.data', '.bss')
bryantaylor 0:eafc3fd41f75 29
bryantaylor 0:eafc3fd41f75 30 misc_flash_sections = ('.interrupts', '.flash_config')
bryantaylor 0:eafc3fd41f75 31
bryantaylor 0:eafc3fd41f75 32 other_sections = ('.interrupts_ram', '.init', '.ARM.extab',
bryantaylor 0:eafc3fd41f75 33 '.ARM.exidx', '.ARM.attributes', '.eh_frame',
bryantaylor 0:eafc3fd41f75 34 '.init_array', '.fini_array', '.jcr', '.stab',
bryantaylor 0:eafc3fd41f75 35 '.stabstr', '.ARM.exidx', '.ARM')
bryantaylor 0:eafc3fd41f75 36
bryantaylor 0:eafc3fd41f75 37 # sections to print info (generic for all toolchains)
bryantaylor 0:eafc3fd41f75 38 sections = ('.text', '.data', '.bss', '.heap', '.stack')
bryantaylor 0:eafc3fd41f75 39
bryantaylor 0:eafc3fd41f75 40 def __init__(self):
bryantaylor 0:eafc3fd41f75 41 """ General initialization
bryantaylor 0:eafc3fd41f75 42 """
bryantaylor 0:eafc3fd41f75 43
bryantaylor 0:eafc3fd41f75 44 # list of all modules and their sections
bryantaylor 0:eafc3fd41f75 45 self.modules = dict()
bryantaylor 0:eafc3fd41f75 46
bryantaylor 0:eafc3fd41f75 47 # sections must be defined in this order to take irrelevant out
bryantaylor 0:eafc3fd41f75 48 self.all_sections = self.sections + self.other_sections + \
bryantaylor 0:eafc3fd41f75 49 self.misc_flash_sections + ('unknown', 'OUTPUT')
bryantaylor 0:eafc3fd41f75 50
bryantaylor 0:eafc3fd41f75 51 # list of all object files and mappting to module names
bryantaylor 0:eafc3fd41f75 52 self.object_to_module = dict()
bryantaylor 0:eafc3fd41f75 53
bryantaylor 0:eafc3fd41f75 54 # Memory usage summary structure
bryantaylor 0:eafc3fd41f75 55 self.mem_summary = dict()
bryantaylor 0:eafc3fd41f75 56
bryantaylor 0:eafc3fd41f75 57 def module_add(self, module_name, size, section):
bryantaylor 0:eafc3fd41f75 58 """ Adds a module / section to the list
bryantaylor 0:eafc3fd41f75 59
bryantaylor 0:eafc3fd41f75 60 Positional arguments:
bryantaylor 0:eafc3fd41f75 61 module_name - name of the module to add
bryantaylor 0:eafc3fd41f75 62 size - the size of the module being added
bryantaylor 0:eafc3fd41f75 63 section - the section the module contributes to
bryantaylor 0:eafc3fd41f75 64 """
bryantaylor 0:eafc3fd41f75 65
bryantaylor 0:eafc3fd41f75 66 if module_name in self.modules:
bryantaylor 0:eafc3fd41f75 67 self.modules[module_name][section] += size
bryantaylor 0:eafc3fd41f75 68 else:
bryantaylor 0:eafc3fd41f75 69 temp_dic = dict()
bryantaylor 0:eafc3fd41f75 70 for section_idx in self.all_sections:
bryantaylor 0:eafc3fd41f75 71 temp_dic[section_idx] = 0
bryantaylor 0:eafc3fd41f75 72 temp_dic[section] = size
bryantaylor 0:eafc3fd41f75 73 self.modules[module_name] = temp_dic
bryantaylor 0:eafc3fd41f75 74
bryantaylor 0:eafc3fd41f75 75 def check_new_section_gcc(self, line):
bryantaylor 0:eafc3fd41f75 76 """ Check whether a new section in a map file has been detected (only
bryantaylor 0:eafc3fd41f75 77 applies to gcc)
bryantaylor 0:eafc3fd41f75 78
bryantaylor 0:eafc3fd41f75 79 Positional arguments:
bryantaylor 0:eafc3fd41f75 80 line - the line to check for a new section
bryantaylor 0:eafc3fd41f75 81 """
bryantaylor 0:eafc3fd41f75 82
bryantaylor 0:eafc3fd41f75 83 for i in self.all_sections:
bryantaylor 0:eafc3fd41f75 84 if line.startswith(i):
bryantaylor 0:eafc3fd41f75 85 # should name of the section (assuming it's a known one)
bryantaylor 0:eafc3fd41f75 86 return i
bryantaylor 0:eafc3fd41f75 87
bryantaylor 0:eafc3fd41f75 88 if line.startswith('.'):
bryantaylor 0:eafc3fd41f75 89 return 'unknown' # all others are classified are unknown
bryantaylor 0:eafc3fd41f75 90 else:
bryantaylor 0:eafc3fd41f75 91 return False # everything else, means no change in section
bryantaylor 0:eafc3fd41f75 92
bryantaylor 0:eafc3fd41f75 93 @staticmethod
bryantaylor 0:eafc3fd41f75 94 def path_object_to_module_name(txt):
bryantaylor 0:eafc3fd41f75 95 """ Parse a path to object file to extract it's module and object data
bryantaylor 0:eafc3fd41f75 96
bryantaylor 0:eafc3fd41f75 97 Positional arguments:
bryantaylor 0:eafc3fd41f75 98 txt - the path to parse the object and module name from
bryantaylor 0:eafc3fd41f75 99 """
bryantaylor 0:eafc3fd41f75 100
bryantaylor 0:eafc3fd41f75 101 txt = txt.replace('\\', '/')
bryantaylor 0:eafc3fd41f75 102 rex_mbed_os_name = r'^.+mbed-os\/(.+)\/(.+\.o)$'
bryantaylor 0:eafc3fd41f75 103 test_rex_mbed_os_name = re.match(rex_mbed_os_name, txt)
bryantaylor 0:eafc3fd41f75 104
bryantaylor 0:eafc3fd41f75 105 if test_rex_mbed_os_name:
bryantaylor 0:eafc3fd41f75 106
bryantaylor 0:eafc3fd41f75 107 object_name = test_rex_mbed_os_name.group(2)
bryantaylor 0:eafc3fd41f75 108 data = test_rex_mbed_os_name.group(1).split('/')
bryantaylor 0:eafc3fd41f75 109 ndata = len(data)
bryantaylor 0:eafc3fd41f75 110
bryantaylor 0:eafc3fd41f75 111 if ndata == 1:
bryantaylor 0:eafc3fd41f75 112 module_name = data[0]
bryantaylor 0:eafc3fd41f75 113 else:
bryantaylor 0:eafc3fd41f75 114 module_name = data[0] + '/' + data[1]
bryantaylor 0:eafc3fd41f75 115
bryantaylor 0:eafc3fd41f75 116 return [module_name, object_name]
bryantaylor 0:eafc3fd41f75 117 else:
bryantaylor 0:eafc3fd41f75 118 return ['Misc', ""]
bryantaylor 0:eafc3fd41f75 119
bryantaylor 0:eafc3fd41f75 120
bryantaylor 0:eafc3fd41f75 121 def parse_section_gcc(self, line):
bryantaylor 0:eafc3fd41f75 122 """ Parse data from a section of gcc map file
bryantaylor 0:eafc3fd41f75 123
bryantaylor 0:eafc3fd41f75 124 examples:
bryantaylor 0:eafc3fd41f75 125 0x00004308 0x7c ./.build/K64F/GCC_ARM/mbed-os/hal/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/spi_api.o
bryantaylor 0:eafc3fd41f75 126 .text 0x00000608 0x198 ./.build/K64F/GCC_ARM/mbed-os/core/mbed-rtos/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_GCC/HAL_CM4.o
bryantaylor 0:eafc3fd41f75 127
bryantaylor 0:eafc3fd41f75 128 Positional arguments:
bryantaylor 0:eafc3fd41f75 129 line - the line to parse a section from
bryantaylor 0:eafc3fd41f75 130 """
bryantaylor 0:eafc3fd41f75 131 rex_address_len_name = re.compile(
bryantaylor 0:eafc3fd41f75 132 r'^\s+.*0x(\w{8,16})\s+0x(\w+)\s(.+)$')
bryantaylor 0:eafc3fd41f75 133
bryantaylor 0:eafc3fd41f75 134 test_address_len_name = re.match(rex_address_len_name, line)
bryantaylor 0:eafc3fd41f75 135
bryantaylor 0:eafc3fd41f75 136 if test_address_len_name:
bryantaylor 0:eafc3fd41f75 137
bryantaylor 0:eafc3fd41f75 138 if int(test_address_len_name.group(2), 16) == 0: # size == 0
bryantaylor 0:eafc3fd41f75 139 return ["", 0] # no valid entry
bryantaylor 0:eafc3fd41f75 140 else:
bryantaylor 0:eafc3fd41f75 141 m_name, _ = self.path_object_to_module_name(
bryantaylor 0:eafc3fd41f75 142 test_address_len_name.group(3))
bryantaylor 0:eafc3fd41f75 143 m_size = int(test_address_len_name.group(2), 16)
bryantaylor 0:eafc3fd41f75 144 return [m_name, m_size]
bryantaylor 0:eafc3fd41f75 145
bryantaylor 0:eafc3fd41f75 146 else: # special corner case for *fill* sections
bryantaylor 0:eafc3fd41f75 147 # example
bryantaylor 0:eafc3fd41f75 148 # *fill* 0x0000abe4 0x4
bryantaylor 0:eafc3fd41f75 149 rex_address_len = r'^\s+\*fill\*\s+0x(\w{8,16})\s+0x(\w+).*$'
bryantaylor 0:eafc3fd41f75 150 test_address_len = re.match(rex_address_len, line)
bryantaylor 0:eafc3fd41f75 151
bryantaylor 0:eafc3fd41f75 152 if test_address_len:
bryantaylor 0:eafc3fd41f75 153 if int(test_address_len.group(2), 16) == 0: # size == 0
bryantaylor 0:eafc3fd41f75 154 return ["", 0] # no valid entry
bryantaylor 0:eafc3fd41f75 155 else:
bryantaylor 0:eafc3fd41f75 156 m_name = 'Fill'
bryantaylor 0:eafc3fd41f75 157 m_size = int(test_address_len.group(2), 16)
bryantaylor 0:eafc3fd41f75 158 return [m_name, m_size]
bryantaylor 0:eafc3fd41f75 159 else:
bryantaylor 0:eafc3fd41f75 160 return ["", 0] # no valid entry
bryantaylor 0:eafc3fd41f75 161
bryantaylor 0:eafc3fd41f75 162 def parse_map_file_gcc(self, file_desc):
bryantaylor 0:eafc3fd41f75 163 """ Main logic to decode gcc map files
bryantaylor 0:eafc3fd41f75 164
bryantaylor 0:eafc3fd41f75 165 Positional arguments:
bryantaylor 0:eafc3fd41f75 166 file_desc - a stream object to parse as a gcc map file
bryantaylor 0:eafc3fd41f75 167 """
bryantaylor 0:eafc3fd41f75 168
bryantaylor 0:eafc3fd41f75 169 current_section = 'unknown'
bryantaylor 0:eafc3fd41f75 170
bryantaylor 0:eafc3fd41f75 171 with file_desc as infile:
bryantaylor 0:eafc3fd41f75 172
bryantaylor 0:eafc3fd41f75 173 # Search area to parse
bryantaylor 0:eafc3fd41f75 174 for line in infile:
bryantaylor 0:eafc3fd41f75 175 if line.startswith('Linker script and memory map'):
bryantaylor 0:eafc3fd41f75 176 current_section = "unknown"
bryantaylor 0:eafc3fd41f75 177 break
bryantaylor 0:eafc3fd41f75 178
bryantaylor 0:eafc3fd41f75 179 # Start decoding the map file
bryantaylor 0:eafc3fd41f75 180 for line in infile:
bryantaylor 0:eafc3fd41f75 181
bryantaylor 0:eafc3fd41f75 182 change_section = self.check_new_section_gcc(line)
bryantaylor 0:eafc3fd41f75 183
bryantaylor 0:eafc3fd41f75 184 if change_section == "OUTPUT": # finish parsing file: exit
bryantaylor 0:eafc3fd41f75 185 break
bryantaylor 0:eafc3fd41f75 186 elif change_section != False:
bryantaylor 0:eafc3fd41f75 187 current_section = change_section
bryantaylor 0:eafc3fd41f75 188
bryantaylor 0:eafc3fd41f75 189 [module_name, module_size] = self.parse_section_gcc(line)
bryantaylor 0:eafc3fd41f75 190
bryantaylor 0:eafc3fd41f75 191 if module_size == 0 or module_name == "":
bryantaylor 0:eafc3fd41f75 192 pass
bryantaylor 0:eafc3fd41f75 193 else:
bryantaylor 0:eafc3fd41f75 194 self.module_add(module_name, module_size, current_section)
bryantaylor 0:eafc3fd41f75 195
bryantaylor 0:eafc3fd41f75 196 if DEBUG:
bryantaylor 0:eafc3fd41f75 197 print "Line: %s" % line,
bryantaylor 0:eafc3fd41f75 198 print "Module: %s\tSection: %s\tSize: %s" % \
bryantaylor 0:eafc3fd41f75 199 (module_name, current_section, module_size)
bryantaylor 0:eafc3fd41f75 200 raw_input("----------")
bryantaylor 0:eafc3fd41f75 201
bryantaylor 0:eafc3fd41f75 202 def parse_section_armcc(self, line):
bryantaylor 0:eafc3fd41f75 203 """ Parse data from an armcc map file
bryantaylor 0:eafc3fd41f75 204
bryantaylor 0:eafc3fd41f75 205 Examples of armcc map file:
bryantaylor 0:eafc3fd41f75 206 Base_Addr Size Type Attr Idx E Section Name Object
bryantaylor 0:eafc3fd41f75 207 0x00000000 0x00000400 Data RO 11222 RESET startup_MK64F12.o
bryantaylor 0:eafc3fd41f75 208 0x00000410 0x00000008 Code RO 49364 * !!!main c_w.l(__main.o)
bryantaylor 0:eafc3fd41f75 209
bryantaylor 0:eafc3fd41f75 210 Positional arguments:
bryantaylor 0:eafc3fd41f75 211 line - the line to parse the section data from
bryantaylor 0:eafc3fd41f75 212 """
bryantaylor 0:eafc3fd41f75 213
bryantaylor 0:eafc3fd41f75 214 test_rex_armcc = re.match(RE_ARMCC, line)
bryantaylor 0:eafc3fd41f75 215
bryantaylor 0:eafc3fd41f75 216 if test_rex_armcc:
bryantaylor 0:eafc3fd41f75 217
bryantaylor 0:eafc3fd41f75 218 size = int(test_rex_armcc.group(2), 16)
bryantaylor 0:eafc3fd41f75 219
bryantaylor 0:eafc3fd41f75 220 if test_rex_armcc.group(4) == 'RO':
bryantaylor 0:eafc3fd41f75 221 section = '.text'
bryantaylor 0:eafc3fd41f75 222 else:
bryantaylor 0:eafc3fd41f75 223 if test_rex_armcc.group(3) == 'Data':
bryantaylor 0:eafc3fd41f75 224 section = '.data'
bryantaylor 0:eafc3fd41f75 225 elif test_rex_armcc.group(3) == 'Zero':
bryantaylor 0:eafc3fd41f75 226 section = '.bss'
bryantaylor 0:eafc3fd41f75 227 else:
bryantaylor 0:eafc3fd41f75 228 print "BUG armcc map parser"
bryantaylor 0:eafc3fd41f75 229 raw_input()
bryantaylor 0:eafc3fd41f75 230
bryantaylor 0:eafc3fd41f75 231 # lookup object in dictionary and return module name
bryantaylor 0:eafc3fd41f75 232 object_name = test_rex_armcc.group(6)
bryantaylor 0:eafc3fd41f75 233 if object_name in self.object_to_module:
bryantaylor 0:eafc3fd41f75 234 module_name = self.object_to_module[object_name]
bryantaylor 0:eafc3fd41f75 235 else:
bryantaylor 0:eafc3fd41f75 236 module_name = 'Misc'
bryantaylor 0:eafc3fd41f75 237
bryantaylor 0:eafc3fd41f75 238 return [module_name, size, section]
bryantaylor 0:eafc3fd41f75 239
bryantaylor 0:eafc3fd41f75 240 else:
bryantaylor 0:eafc3fd41f75 241 return ["", 0, ""] # no valid entry
bryantaylor 0:eafc3fd41f75 242
bryantaylor 0:eafc3fd41f75 243 def parse_section_iar(self, line):
bryantaylor 0:eafc3fd41f75 244 """ Parse data from an IAR map file
bryantaylor 0:eafc3fd41f75 245
bryantaylor 0:eafc3fd41f75 246 Examples of IAR map file:
bryantaylor 0:eafc3fd41f75 247 Section Kind Address Size Object
bryantaylor 0:eafc3fd41f75 248 .intvec ro code 0x00000000 0x198 startup_MK64F12.o [15]
bryantaylor 0:eafc3fd41f75 249 .rodata const 0x00000198 0x0 zero_init3.o [133]
bryantaylor 0:eafc3fd41f75 250 .iar.init_table const 0x00008384 0x2c - Linker created -
bryantaylor 0:eafc3fd41f75 251 Initializer bytes const 0x00000198 0xb2 <for P3 s0>
bryantaylor 0:eafc3fd41f75 252 .data inited 0x20000000 0xd4 driverAtmelRFInterface.o [70]
bryantaylor 0:eafc3fd41f75 253 .bss zero 0x20000598 0x318 RTX_Conf_CM.o [4]
bryantaylor 0:eafc3fd41f75 254 .iar.dynexit uninit 0x20001448 0x204 <Block tail>
bryantaylor 0:eafc3fd41f75 255 HEAP uninit 0x20001650 0x10000 <Block tail>
bryantaylor 0:eafc3fd41f75 256
bryantaylor 0:eafc3fd41f75 257 Positional_arguments:
bryantaylor 0:eafc3fd41f75 258 line - the line to parse section data from
bryantaylor 0:eafc3fd41f75 259 """
bryantaylor 0:eafc3fd41f75 260
bryantaylor 0:eafc3fd41f75 261 test_rex_iar = re.match(RE_IAR, line)
bryantaylor 0:eafc3fd41f75 262
bryantaylor 0:eafc3fd41f75 263 if test_rex_iar:
bryantaylor 0:eafc3fd41f75 264
bryantaylor 0:eafc3fd41f75 265 size = int(test_rex_iar.group(4), 16)
bryantaylor 0:eafc3fd41f75 266
bryantaylor 0:eafc3fd41f75 267 if test_rex_iar.group(2) == 'const' or \
bryantaylor 0:eafc3fd41f75 268 test_rex_iar.group(2) == 'ro code':
bryantaylor 0:eafc3fd41f75 269 section = '.text'
bryantaylor 0:eafc3fd41f75 270 elif test_rex_iar.group(2) == 'zero' or \
bryantaylor 0:eafc3fd41f75 271 test_rex_iar.group(2) == 'uninit':
bryantaylor 0:eafc3fd41f75 272 if test_rex_iar.group(1)[0:4] == 'HEAP':
bryantaylor 0:eafc3fd41f75 273 section = '.heap'
bryantaylor 0:eafc3fd41f75 274 elif test_rex_iar.group(1)[0:6] == 'CSTACK':
bryantaylor 0:eafc3fd41f75 275 section = '.stack'
bryantaylor 0:eafc3fd41f75 276 else:
bryantaylor 0:eafc3fd41f75 277 section = '.bss' # default section
bryantaylor 0:eafc3fd41f75 278
bryantaylor 0:eafc3fd41f75 279 elif test_rex_iar.group(2) == 'inited':
bryantaylor 0:eafc3fd41f75 280 section = '.data'
bryantaylor 0:eafc3fd41f75 281 else:
bryantaylor 0:eafc3fd41f75 282 print "BUG IAR map parser"
bryantaylor 0:eafc3fd41f75 283 raw_input()
bryantaylor 0:eafc3fd41f75 284
bryantaylor 0:eafc3fd41f75 285 # lookup object in dictionary and return module name
bryantaylor 0:eafc3fd41f75 286 object_name = test_rex_iar.group(5)
bryantaylor 0:eafc3fd41f75 287 if object_name in self.object_to_module:
bryantaylor 0:eafc3fd41f75 288 module_name = self.object_to_module[object_name]
bryantaylor 0:eafc3fd41f75 289 else:
bryantaylor 0:eafc3fd41f75 290 module_name = 'Misc'
bryantaylor 0:eafc3fd41f75 291
bryantaylor 0:eafc3fd41f75 292 return [module_name, size, section]
bryantaylor 0:eafc3fd41f75 293
bryantaylor 0:eafc3fd41f75 294 else:
bryantaylor 0:eafc3fd41f75 295 return ["", 0, ""] # no valid entry
bryantaylor 0:eafc3fd41f75 296
bryantaylor 0:eafc3fd41f75 297 def parse_map_file_armcc(self, file_desc):
bryantaylor 0:eafc3fd41f75 298 """ Main logic to decode armc5 map files
bryantaylor 0:eafc3fd41f75 299
bryantaylor 0:eafc3fd41f75 300 Positional arguments:
bryantaylor 0:eafc3fd41f75 301 file_desc - a file like object to parse as an armc5 map file
bryantaylor 0:eafc3fd41f75 302 """
bryantaylor 0:eafc3fd41f75 303
bryantaylor 0:eafc3fd41f75 304 with file_desc as infile:
bryantaylor 0:eafc3fd41f75 305
bryantaylor 0:eafc3fd41f75 306 # Search area to parse
bryantaylor 0:eafc3fd41f75 307 for line in infile:
bryantaylor 0:eafc3fd41f75 308 if line.startswith(' Base Addr Size'):
bryantaylor 0:eafc3fd41f75 309 break
bryantaylor 0:eafc3fd41f75 310
bryantaylor 0:eafc3fd41f75 311 # Start decoding the map file
bryantaylor 0:eafc3fd41f75 312 for line in infile:
bryantaylor 0:eafc3fd41f75 313
bryantaylor 0:eafc3fd41f75 314 [name, size, section] = self.parse_section_armcc(line)
bryantaylor 0:eafc3fd41f75 315
bryantaylor 0:eafc3fd41f75 316 if size == 0 or name == "" or section == "":
bryantaylor 0:eafc3fd41f75 317 pass
bryantaylor 0:eafc3fd41f75 318 else:
bryantaylor 0:eafc3fd41f75 319 self.module_add(name, size, section)
bryantaylor 0:eafc3fd41f75 320
bryantaylor 0:eafc3fd41f75 321 def parse_map_file_iar(self, file_desc):
bryantaylor 0:eafc3fd41f75 322 """ Main logic to decode IAR map files
bryantaylor 0:eafc3fd41f75 323
bryantaylor 0:eafc3fd41f75 324 Positional arguments:
bryantaylor 0:eafc3fd41f75 325 file_desc - a file like object to parse as an IAR map file
bryantaylor 0:eafc3fd41f75 326 """
bryantaylor 0:eafc3fd41f75 327
bryantaylor 0:eafc3fd41f75 328 with file_desc as infile:
bryantaylor 0:eafc3fd41f75 329
bryantaylor 0:eafc3fd41f75 330 # Search area to parse
bryantaylor 0:eafc3fd41f75 331 for line in infile:
bryantaylor 0:eafc3fd41f75 332 if line.startswith(' Section '):
bryantaylor 0:eafc3fd41f75 333 break
bryantaylor 0:eafc3fd41f75 334
bryantaylor 0:eafc3fd41f75 335 # Start decoding the map file
bryantaylor 0:eafc3fd41f75 336 for line in infile:
bryantaylor 0:eafc3fd41f75 337
bryantaylor 0:eafc3fd41f75 338 [name, size, section] = self.parse_section_iar(line)
bryantaylor 0:eafc3fd41f75 339
bryantaylor 0:eafc3fd41f75 340 if size == 0 or name == "" or section == "":
bryantaylor 0:eafc3fd41f75 341 pass
bryantaylor 0:eafc3fd41f75 342 else:
bryantaylor 0:eafc3fd41f75 343 self.module_add(name, size, section)
bryantaylor 0:eafc3fd41f75 344
bryantaylor 0:eafc3fd41f75 345 def search_objects(self, path, toolchain):
bryantaylor 0:eafc3fd41f75 346 """ Check whether the specified map file matches with the toolchain.
bryantaylor 0:eafc3fd41f75 347 Searches for object files and creates mapping: object --> module
bryantaylor 0:eafc3fd41f75 348
bryantaylor 0:eafc3fd41f75 349 Positional arguments:
bryantaylor 0:eafc3fd41f75 350 path - the path to an object file
bryantaylor 0:eafc3fd41f75 351 toolchain - the toolchain used to build the object file
bryantaylor 0:eafc3fd41f75 352 """
bryantaylor 0:eafc3fd41f75 353
bryantaylor 0:eafc3fd41f75 354 path = path.replace('\\', '/')
bryantaylor 0:eafc3fd41f75 355
bryantaylor 0:eafc3fd41f75 356 # check location of map file
bryantaylor 0:eafc3fd41f75 357 rex = r'^(.+\/)' + re.escape(toolchain) + r'\/(.+\.map)$'
bryantaylor 0:eafc3fd41f75 358 test_rex = re.match(rex, path)
bryantaylor 0:eafc3fd41f75 359
bryantaylor 0:eafc3fd41f75 360 if test_rex:
bryantaylor 0:eafc3fd41f75 361 search_path = test_rex.group(1) + toolchain + '/mbed-os/'
bryantaylor 0:eafc3fd41f75 362 else:
bryantaylor 0:eafc3fd41f75 363 # It looks this is not an mbed project
bryantaylor 0:eafc3fd41f75 364 # object-to-module mapping cannot be generated
bryantaylor 0:eafc3fd41f75 365 print "Warning: specified toolchain doesn't match with"\
bryantaylor 0:eafc3fd41f75 366 " path to the memory map file."
bryantaylor 0:eafc3fd41f75 367 return
bryantaylor 0:eafc3fd41f75 368
bryantaylor 0:eafc3fd41f75 369 for root, _, obj_files in os.walk(search_path):
bryantaylor 0:eafc3fd41f75 370 for obj_file in obj_files:
bryantaylor 0:eafc3fd41f75 371 if obj_file.endswith(".o"):
bryantaylor 0:eafc3fd41f75 372 module_name, object_name = self.path_object_to_module_name(
bryantaylor 0:eafc3fd41f75 373 os.path.join(root, obj_file))
bryantaylor 0:eafc3fd41f75 374
bryantaylor 0:eafc3fd41f75 375 if object_name in self.object_to_module:
bryantaylor 0:eafc3fd41f75 376 if DEBUG:
bryantaylor 0:eafc3fd41f75 377 print "WARNING: multiple usages of object file: %s"\
bryantaylor 0:eafc3fd41f75 378 % object_name
bryantaylor 0:eafc3fd41f75 379 print " Current: %s" % \
bryantaylor 0:eafc3fd41f75 380 self.object_to_module[object_name]
bryantaylor 0:eafc3fd41f75 381 print " New: %s" % module_name
bryantaylor 0:eafc3fd41f75 382 print " "
bryantaylor 0:eafc3fd41f75 383 else:
bryantaylor 0:eafc3fd41f75 384 self.object_to_module.update({object_name:module_name})
bryantaylor 0:eafc3fd41f75 385
bryantaylor 0:eafc3fd41f75 386 export_formats = ["json", "csv-ci", "table"]
bryantaylor 0:eafc3fd41f75 387
bryantaylor 0:eafc3fd41f75 388 def generate_output(self, export_format, file_output=None):
bryantaylor 0:eafc3fd41f75 389 """ Generates summary of memory map data
bryantaylor 0:eafc3fd41f75 390
bryantaylor 0:eafc3fd41f75 391 Positional arguments:
bryantaylor 0:eafc3fd41f75 392 export_format - the format to dump
bryantaylor 0:eafc3fd41f75 393
bryantaylor 0:eafc3fd41f75 394 Keyword arguments:
bryantaylor 0:eafc3fd41f75 395 file_desc - descriptor (either stdout or file)
bryantaylor 0:eafc3fd41f75 396 """
bryantaylor 0:eafc3fd41f75 397
bryantaylor 0:eafc3fd41f75 398 try:
bryantaylor 0:eafc3fd41f75 399 if file_output:
bryantaylor 0:eafc3fd41f75 400 file_desc = open(file_output, 'wb')
bryantaylor 0:eafc3fd41f75 401 else:
bryantaylor 0:eafc3fd41f75 402 file_desc = sys.stdout
bryantaylor 0:eafc3fd41f75 403 except IOError as error:
bryantaylor 0:eafc3fd41f75 404 print "I/O error({0}): {1}".format(error.errno, error.strerror)
bryantaylor 0:eafc3fd41f75 405 return False
bryantaylor 0:eafc3fd41f75 406
bryantaylor 0:eafc3fd41f75 407 subtotal = dict()
bryantaylor 0:eafc3fd41f75 408 for k in self.sections:
bryantaylor 0:eafc3fd41f75 409 subtotal[k] = 0
bryantaylor 0:eafc3fd41f75 410
bryantaylor 0:eafc3fd41f75 411 # Calculate misc flash sections
bryantaylor 0:eafc3fd41f75 412 misc_flash_mem = 0
bryantaylor 0:eafc3fd41f75 413 for i in self.modules:
bryantaylor 0:eafc3fd41f75 414 for k in self.misc_flash_sections:
bryantaylor 0:eafc3fd41f75 415 if self.modules[i][k]:
bryantaylor 0:eafc3fd41f75 416 misc_flash_mem += self.modules[i][k]
bryantaylor 0:eafc3fd41f75 417
bryantaylor 0:eafc3fd41f75 418 json_obj = []
bryantaylor 0:eafc3fd41f75 419 for i in sorted(self.modules):
bryantaylor 0:eafc3fd41f75 420
bryantaylor 0:eafc3fd41f75 421 row = []
bryantaylor 0:eafc3fd41f75 422
bryantaylor 0:eafc3fd41f75 423 json_obj.append({
bryantaylor 0:eafc3fd41f75 424 "module":i,
bryantaylor 0:eafc3fd41f75 425 "size":{
bryantaylor 0:eafc3fd41f75 426 k:self.modules[i][k] for k in self.print_sections
bryantaylor 0:eafc3fd41f75 427 }
bryantaylor 0:eafc3fd41f75 428 })
bryantaylor 0:eafc3fd41f75 429
bryantaylor 0:eafc3fd41f75 430 summary = {
bryantaylor 0:eafc3fd41f75 431 'summary':{
bryantaylor 0:eafc3fd41f75 432 'static_ram': (subtotal['.data'] + subtotal['.bss']),
bryantaylor 0:eafc3fd41f75 433 'heap': (subtotal['.heap']),
bryantaylor 0:eafc3fd41f75 434 'stack': (subtotal['.stack']),
bryantaylor 0:eafc3fd41f75 435 'total_ram': (subtotal['.data'] + subtotal['.bss'] +
bryantaylor 0:eafc3fd41f75 436 subtotal['.heap']+subtotal['.stack']),
bryantaylor 0:eafc3fd41f75 437 'total_flash': (subtotal['.text'] + subtotal['.data'] +
bryantaylor 0:eafc3fd41f75 438 misc_flash_mem),
bryantaylor 0:eafc3fd41f75 439 }
bryantaylor 0:eafc3fd41f75 440 }
bryantaylor 0:eafc3fd41f75 441
bryantaylor 0:eafc3fd41f75 442 self.mem_summary = json_obj + [summary]
bryantaylor 0:eafc3fd41f75 443
bryantaylor 0:eafc3fd41f75 444 to_call = {'json': self.generate_json,
bryantaylor 0:eafc3fd41f75 445 'csv-ci': self.generate_csv,
bryantaylor 0:eafc3fd41f75 446 'table': self.generate_table}[export_format]
bryantaylor 0:eafc3fd41f75 447 to_call(subtotal, misc_flash_mem, file_desc)
bryantaylor 0:eafc3fd41f75 448
bryantaylor 0:eafc3fd41f75 449 if file_desc is not sys.stdout:
bryantaylor 0:eafc3fd41f75 450 file_desc.close()
bryantaylor 0:eafc3fd41f75 451
bryantaylor 0:eafc3fd41f75 452 def generate_json(self, _, dummy, file_desc):
bryantaylor 0:eafc3fd41f75 453 """Generate a json file from a memory map
bryantaylor 0:eafc3fd41f75 454
bryantaylor 0:eafc3fd41f75 455 Positional arguments:
bryantaylor 0:eafc3fd41f75 456 subtotal - total sizes for each module
bryantaylor 0:eafc3fd41f75 457 misc_flash_mem - size of misc flash sections
bryantaylor 0:eafc3fd41f75 458 file_desc - the file to write out the final report to
bryantaylor 0:eafc3fd41f75 459 """
bryantaylor 0:eafc3fd41f75 460 file_desc.write(json.dumps(self.mem_summary, indent=4))
bryantaylor 0:eafc3fd41f75 461 file_desc.write('\n')
bryantaylor 0:eafc3fd41f75 462
bryantaylor 0:eafc3fd41f75 463 def generate_csv(self, subtotal, misc_flash_mem, file_desc):
bryantaylor 0:eafc3fd41f75 464 """Generate a CSV file from a memoy map
bryantaylor 0:eafc3fd41f75 465
bryantaylor 0:eafc3fd41f75 466 Positional arguments:
bryantaylor 0:eafc3fd41f75 467 subtotal - total sizes for each module
bryantaylor 0:eafc3fd41f75 468 misc_flash_mem - size of misc flash sections
bryantaylor 0:eafc3fd41f75 469 file_desc - the file to write out the final report to
bryantaylor 0:eafc3fd41f75 470 """
bryantaylor 0:eafc3fd41f75 471 csv_writer = csv.writer(file_desc, delimiter=',',
bryantaylor 0:eafc3fd41f75 472 quoting=csv.QUOTE_NONE)
bryantaylor 0:eafc3fd41f75 473
bryantaylor 0:eafc3fd41f75 474 csv_module_section = []
bryantaylor 0:eafc3fd41f75 475 csv_sizes = []
bryantaylor 0:eafc3fd41f75 476 for i in sorted(self.modules):
bryantaylor 0:eafc3fd41f75 477 for k in self.print_sections:
bryantaylor 0:eafc3fd41f75 478 csv_module_section += [i+k]
bryantaylor 0:eafc3fd41f75 479 csv_sizes += [self.modules[i][k]]
bryantaylor 0:eafc3fd41f75 480
bryantaylor 0:eafc3fd41f75 481 csv_module_section += ['static_ram']
bryantaylor 0:eafc3fd41f75 482 csv_sizes += [subtotal['.data']+subtotal['.bss']]
bryantaylor 0:eafc3fd41f75 483
bryantaylor 0:eafc3fd41f75 484 csv_module_section += ['heap']
bryantaylor 0:eafc3fd41f75 485 if subtotal['.heap'] == 0:
bryantaylor 0:eafc3fd41f75 486 csv_sizes += ['unknown']
bryantaylor 0:eafc3fd41f75 487 else:
bryantaylor 0:eafc3fd41f75 488 csv_sizes += [subtotal['.heap']]
bryantaylor 0:eafc3fd41f75 489
bryantaylor 0:eafc3fd41f75 490 csv_module_section += ['stack']
bryantaylor 0:eafc3fd41f75 491 if subtotal['.stack'] == 0:
bryantaylor 0:eafc3fd41f75 492 csv_sizes += ['unknown']
bryantaylor 0:eafc3fd41f75 493 else:
bryantaylor 0:eafc3fd41f75 494 csv_sizes += [subtotal['.stack']]
bryantaylor 0:eafc3fd41f75 495
bryantaylor 0:eafc3fd41f75 496 csv_module_section += ['total_ram']
bryantaylor 0:eafc3fd41f75 497 csv_sizes += [subtotal['.data'] + subtotal['.bss'] +
bryantaylor 0:eafc3fd41f75 498 subtotal['.heap'] + subtotal['.stack']]
bryantaylor 0:eafc3fd41f75 499
bryantaylor 0:eafc3fd41f75 500 csv_module_section += ['total_flash']
bryantaylor 0:eafc3fd41f75 501 csv_sizes += [subtotal['.text']+subtotal['.data']+misc_flash_mem]
bryantaylor 0:eafc3fd41f75 502
bryantaylor 0:eafc3fd41f75 503 csv_writer.writerow(csv_module_section)
bryantaylor 0:eafc3fd41f75 504 csv_writer.writerow(csv_sizes)
bryantaylor 0:eafc3fd41f75 505
bryantaylor 0:eafc3fd41f75 506 def generate_table(self, subtotal, misc_flash_mem, file_desc):
bryantaylor 0:eafc3fd41f75 507 """Generate a table from a memoy map
bryantaylor 0:eafc3fd41f75 508
bryantaylor 0:eafc3fd41f75 509 Positional arguments:
bryantaylor 0:eafc3fd41f75 510 subtotal - total sizes for each module
bryantaylor 0:eafc3fd41f75 511 misc_flash_mem - size of misc flash sections
bryantaylor 0:eafc3fd41f75 512 file_desc - the file to write out the final report to
bryantaylor 0:eafc3fd41f75 513 """
bryantaylor 0:eafc3fd41f75 514 # Create table
bryantaylor 0:eafc3fd41f75 515 columns = ['Module']
bryantaylor 0:eafc3fd41f75 516 columns.extend(self.print_sections)
bryantaylor 0:eafc3fd41f75 517
bryantaylor 0:eafc3fd41f75 518 table = PrettyTable(columns)
bryantaylor 0:eafc3fd41f75 519 table.align["Module"] = "l"
bryantaylor 0:eafc3fd41f75 520 for col in self.print_sections:
bryantaylor 0:eafc3fd41f75 521 table.align[col] = 'r'
bryantaylor 0:eafc3fd41f75 522
bryantaylor 0:eafc3fd41f75 523 for i in list(self.print_sections):
bryantaylor 0:eafc3fd41f75 524 table.align[i] = 'r'
bryantaylor 0:eafc3fd41f75 525
bryantaylor 0:eafc3fd41f75 526 for i in sorted(self.modules):
bryantaylor 0:eafc3fd41f75 527 row = [i]
bryantaylor 0:eafc3fd41f75 528
bryantaylor 0:eafc3fd41f75 529 for k in self.sections:
bryantaylor 0:eafc3fd41f75 530 subtotal[k] += self.modules[i][k]
bryantaylor 0:eafc3fd41f75 531
bryantaylor 0:eafc3fd41f75 532 for k in self.print_sections:
bryantaylor 0:eafc3fd41f75 533 row.append(self.modules[i][k])
bryantaylor 0:eafc3fd41f75 534
bryantaylor 0:eafc3fd41f75 535 table.add_row(row)
bryantaylor 0:eafc3fd41f75 536
bryantaylor 0:eafc3fd41f75 537 subtotal_row = ['Subtotals']
bryantaylor 0:eafc3fd41f75 538 for k in self.print_sections:
bryantaylor 0:eafc3fd41f75 539 subtotal_row.append(subtotal[k])
bryantaylor 0:eafc3fd41f75 540
bryantaylor 0:eafc3fd41f75 541 table.add_row(subtotal_row)
bryantaylor 0:eafc3fd41f75 542
bryantaylor 0:eafc3fd41f75 543 file_desc.write(table.get_string())
bryantaylor 0:eafc3fd41f75 544 file_desc.write('\n')
bryantaylor 0:eafc3fd41f75 545
bryantaylor 0:eafc3fd41f75 546 if subtotal['.heap'] == 0:
bryantaylor 0:eafc3fd41f75 547 file_desc.write("Allocated Heap: unknown\n")
bryantaylor 0:eafc3fd41f75 548 else:
bryantaylor 0:eafc3fd41f75 549 file_desc.write("Allocated Heap: %s bytes\n" %
bryantaylor 0:eafc3fd41f75 550 str(subtotal['.heap']))
bryantaylor 0:eafc3fd41f75 551
bryantaylor 0:eafc3fd41f75 552 if subtotal['.stack'] == 0:
bryantaylor 0:eafc3fd41f75 553 file_desc.write("Allocated Stack: unknown\n")
bryantaylor 0:eafc3fd41f75 554 else:
bryantaylor 0:eafc3fd41f75 555 file_desc.write("Allocated Stack: %s bytes\n" %
bryantaylor 0:eafc3fd41f75 556 str(subtotal['.stack']))
bryantaylor 0:eafc3fd41f75 557
bryantaylor 0:eafc3fd41f75 558 file_desc.write("Total Static RAM memory (data + bss): %s bytes\n" %
bryantaylor 0:eafc3fd41f75 559 (str(subtotal['.data'] + subtotal['.bss'])))
bryantaylor 0:eafc3fd41f75 560 file_desc.write(
bryantaylor 0:eafc3fd41f75 561 "Total RAM memory (data + bss + heap + stack): %s bytes\n"
bryantaylor 0:eafc3fd41f75 562 % (str(subtotal['.data'] + subtotal['.bss'] + subtotal['.heap'] +
bryantaylor 0:eafc3fd41f75 563 subtotal['.stack'])))
bryantaylor 0:eafc3fd41f75 564 file_desc.write("Total Flash memory (text + data + misc): %s bytes\n" %
bryantaylor 0:eafc3fd41f75 565 (str(subtotal['.text'] + subtotal['.data'] +
bryantaylor 0:eafc3fd41f75 566 misc_flash_mem)))
bryantaylor 0:eafc3fd41f75 567
bryantaylor 0:eafc3fd41f75 568 toolchains = ["ARM", "ARM_STD", "ARM_MICRO", "GCC_ARM", "IAR"]
bryantaylor 0:eafc3fd41f75 569
bryantaylor 0:eafc3fd41f75 570 def parse(self, mapfile, toolchain):
bryantaylor 0:eafc3fd41f75 571 """ Parse and decode map file depending on the toolchain
bryantaylor 0:eafc3fd41f75 572
bryantaylor 0:eafc3fd41f75 573 Positional arguments:
bryantaylor 0:eafc3fd41f75 574 mapfile - the file name of the memory map file
bryantaylor 0:eafc3fd41f75 575 toolchain - the toolchain used to create the file
bryantaylor 0:eafc3fd41f75 576 """
bryantaylor 0:eafc3fd41f75 577
bryantaylor 0:eafc3fd41f75 578 result = True
bryantaylor 0:eafc3fd41f75 579 try:
bryantaylor 0:eafc3fd41f75 580 with open(mapfile, 'r') as file_input:
bryantaylor 0:eafc3fd41f75 581 if toolchain == "ARM" or toolchain == "ARM_STD" or\
bryantaylor 0:eafc3fd41f75 582 toolchain == "ARM_MICRO":
bryantaylor 0:eafc3fd41f75 583 self.search_objects(os.path.abspath(mapfile), "ARM")
bryantaylor 0:eafc3fd41f75 584 self.parse_map_file_armcc(file_input)
bryantaylor 0:eafc3fd41f75 585 elif toolchain == "GCC_ARM":
bryantaylor 0:eafc3fd41f75 586 self.parse_map_file_gcc(file_input)
bryantaylor 0:eafc3fd41f75 587 elif toolchain == "IAR":
bryantaylor 0:eafc3fd41f75 588 self.search_objects(os.path.abspath(mapfile), toolchain)
bryantaylor 0:eafc3fd41f75 589 self.parse_map_file_iar(file_input)
bryantaylor 0:eafc3fd41f75 590 else:
bryantaylor 0:eafc3fd41f75 591 result = False
bryantaylor 0:eafc3fd41f75 592 except IOError as error:
bryantaylor 0:eafc3fd41f75 593 print "I/O error({0}): {1}".format(error.errno, error.strerror)
bryantaylor 0:eafc3fd41f75 594 result = False
bryantaylor 0:eafc3fd41f75 595 return result
bryantaylor 0:eafc3fd41f75 596
bryantaylor 0:eafc3fd41f75 597 def main():
bryantaylor 0:eafc3fd41f75 598 """Entry Point"""
bryantaylor 0:eafc3fd41f75 599
bryantaylor 0:eafc3fd41f75 600 version = '0.3.11'
bryantaylor 0:eafc3fd41f75 601
bryantaylor 0:eafc3fd41f75 602 # Parser handling
bryantaylor 0:eafc3fd41f75 603 parser = argparse.ArgumentParser(
bryantaylor 0:eafc3fd41f75 604 description="Memory Map File Analyser for ARM mbed\nversion %s" %
bryantaylor 0:eafc3fd41f75 605 version)
bryantaylor 0:eafc3fd41f75 606
bryantaylor 0:eafc3fd41f75 607 parser.add_argument(
bryantaylor 0:eafc3fd41f75 608 'file', type=argparse_filestring_type, help='memory map file')
bryantaylor 0:eafc3fd41f75 609
bryantaylor 0:eafc3fd41f75 610 parser.add_argument(
bryantaylor 0:eafc3fd41f75 611 '-t', '--toolchain', dest='toolchain',
bryantaylor 0:eafc3fd41f75 612 help='select a toolchain used to build the memory map file (%s)' %
bryantaylor 0:eafc3fd41f75 613 ", ".join(MemapParser.toolchains),
bryantaylor 0:eafc3fd41f75 614 required=True,
bryantaylor 0:eafc3fd41f75 615 type=argparse_uppercase_type(MemapParser.toolchains, "toolchain"))
bryantaylor 0:eafc3fd41f75 616
bryantaylor 0:eafc3fd41f75 617 parser.add_argument(
bryantaylor 0:eafc3fd41f75 618 '-o', '--output', help='output file name', required=False)
bryantaylor 0:eafc3fd41f75 619
bryantaylor 0:eafc3fd41f75 620 parser.add_argument(
bryantaylor 0:eafc3fd41f75 621 '-e', '--export', dest='export', required=False, default='table',
bryantaylor 0:eafc3fd41f75 622 type=argparse_lowercase_hyphen_type(MemapParser.export_formats,
bryantaylor 0:eafc3fd41f75 623 'export format'),
bryantaylor 0:eafc3fd41f75 624 help="export format (examples: %s: default)" %
bryantaylor 0:eafc3fd41f75 625 ", ".join(MemapParser.export_formats))
bryantaylor 0:eafc3fd41f75 626
bryantaylor 0:eafc3fd41f75 627 parser.add_argument('-v', '--version', action='version', version=version)
bryantaylor 0:eafc3fd41f75 628
bryantaylor 0:eafc3fd41f75 629 # Parse/run command
bryantaylor 0:eafc3fd41f75 630 if len(sys.argv) <= 1:
bryantaylor 0:eafc3fd41f75 631 parser.print_help()
bryantaylor 0:eafc3fd41f75 632 sys.exit(1)
bryantaylor 0:eafc3fd41f75 633
bryantaylor 0:eafc3fd41f75 634
bryantaylor 0:eafc3fd41f75 635 args = parser.parse_args()
bryantaylor 0:eafc3fd41f75 636
bryantaylor 0:eafc3fd41f75 637 # Create memap object
bryantaylor 0:eafc3fd41f75 638 memap = MemapParser()
bryantaylor 0:eafc3fd41f75 639
bryantaylor 0:eafc3fd41f75 640 # Parse and decode a map file
bryantaylor 0:eafc3fd41f75 641 if args.file and args.toolchain:
bryantaylor 0:eafc3fd41f75 642 if memap.parse(args.file, args.toolchain) is False:
bryantaylor 0:eafc3fd41f75 643 sys.exit(0)
bryantaylor 0:eafc3fd41f75 644
bryantaylor 0:eafc3fd41f75 645 # Write output in file
bryantaylor 0:eafc3fd41f75 646 if args.output != None:
bryantaylor 0:eafc3fd41f75 647 memap.generate_output(args.export, args.output)
bryantaylor 0:eafc3fd41f75 648 else: # Write output in screen
bryantaylor 0:eafc3fd41f75 649 memap.generate_output(args.export)
bryantaylor 0:eafc3fd41f75 650
bryantaylor 0:eafc3fd41f75 651 sys.exit(0)
bryantaylor 0:eafc3fd41f75 652
bryantaylor 0:eafc3fd41f75 653 if __name__ == "__main__":
bryantaylor 0:eafc3fd41f75 654 main()