PES4 / Mbed OS Queue_02
Committer:
demayer
Date:
Sat Mar 28 15:28:19 2020 +0000
Revision:
0:6bf0743ece18
IMU Thread with an event-queue running parallel to handle tasks like a 5 times blinking LED. Button with interrupt detected.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
demayer 0:6bf0743ece18 1 #!/usr/bin/env python
demayer 0:6bf0743ece18 2
demayer 0:6bf0743ece18 3 """Memory Map File Analyser for ARM mbed"""
demayer 0:6bf0743ece18 4
demayer 0:6bf0743ece18 5 import sys
demayer 0:6bf0743ece18 6 import os
demayer 0:6bf0743ece18 7 import re
demayer 0:6bf0743ece18 8 import csv
demayer 0:6bf0743ece18 9 import json
demayer 0:6bf0743ece18 10 import argparse
demayer 0:6bf0743ece18 11 from copy import deepcopy
demayer 0:6bf0743ece18 12 from prettytable import PrettyTable
demayer 0:6bf0743ece18 13
demayer 0:6bf0743ece18 14 from utils import argparse_filestring_type, \
demayer 0:6bf0743ece18 15 argparse_lowercase_hyphen_type, argparse_uppercase_type
demayer 0:6bf0743ece18 16
demayer 0:6bf0743ece18 17 RE_ARMCC = re.compile(
demayer 0:6bf0743ece18 18 r'^\s+0x(\w{8})\s+0x(\w{8})\s+(\w+)\s+(\w+)\s+(\d+)\s+[*]?.+\s+(.+)$')
demayer 0:6bf0743ece18 19 RE_IAR = re.compile(
demayer 0:6bf0743ece18 20 r'^\s+(.+)\s+(zero|const|ro code|inited|uninit)\s'
demayer 0:6bf0743ece18 21 r'+0x(\w{8})\s+0x(\w+)\s+(.+)\s.+$')
demayer 0:6bf0743ece18 22
demayer 0:6bf0743ece18 23 RE_CMDLINE_FILE_IAR = re.compile(r'^#\s+(.+\.o)')
demayer 0:6bf0743ece18 24 RE_LIBRARY_IAR = re.compile(r'^(.+\.a)\:.+$')
demayer 0:6bf0743ece18 25 RE_OBJECT_LIBRARY_IAR = re.compile(r'^\s+(.+\.o)\s.*')
demayer 0:6bf0743ece18 26
demayer 0:6bf0743ece18 27 RE_OBJECT_FILE_GCC = re.compile(r'^(.+\/.+\.o)$')
demayer 0:6bf0743ece18 28 RE_LIBRARY_OBJECT_GCC = re.compile(r'^.+\/lib(.+\.a)\((.+\.o)\)$')
demayer 0:6bf0743ece18 29 RE_STD_SECTION_GCC = re.compile(r'^\s+.*0x(\w{8,16})\s+0x(\w+)\s(.+)$')
demayer 0:6bf0743ece18 30 RE_FILL_SECTION_GCC = re.compile(r'^\s*\*fill\*\s+0x(\w{8,16})\s+0x(\w+).*$')
demayer 0:6bf0743ece18 31
demayer 0:6bf0743ece18 32 RE_OBJECT_ARMCC = re.compile(r'(.+\.(l|ar))\((.+\.o)\)')
demayer 0:6bf0743ece18 33
demayer 0:6bf0743ece18 34
demayer 0:6bf0743ece18 35 class MemapParser(object):
demayer 0:6bf0743ece18 36 """An object that represents parsed results, parses the memory map files,
demayer 0:6bf0743ece18 37 and writes out different file types of memory results
demayer 0:6bf0743ece18 38 """
demayer 0:6bf0743ece18 39
demayer 0:6bf0743ece18 40 print_sections = ('.text', '.data', '.bss')
demayer 0:6bf0743ece18 41
demayer 0:6bf0743ece18 42 misc_flash_sections = ('.interrupts', '.flash_config')
demayer 0:6bf0743ece18 43
demayer 0:6bf0743ece18 44 other_sections = ('.interrupts_ram', '.init', '.ARM.extab',
demayer 0:6bf0743ece18 45 '.ARM.exidx', '.ARM.attributes', '.eh_frame',
demayer 0:6bf0743ece18 46 '.init_array', '.fini_array', '.jcr', '.stab',
demayer 0:6bf0743ece18 47 '.stabstr', '.ARM.exidx', '.ARM')
demayer 0:6bf0743ece18 48
demayer 0:6bf0743ece18 49 # sections to print info (generic for all toolchains)
demayer 0:6bf0743ece18 50 sections = ('.text', '.data', '.bss', '.heap', '.stack')
demayer 0:6bf0743ece18 51
demayer 0:6bf0743ece18 52 def __init__(self):
demayer 0:6bf0743ece18 53 """ General initialization
demayer 0:6bf0743ece18 54 """
demayer 0:6bf0743ece18 55
demayer 0:6bf0743ece18 56 # list of all modules and their sections
demayer 0:6bf0743ece18 57 self.modules = dict() # full list - doesn't change with depth
demayer 0:6bf0743ece18 58 self.short_modules = dict() # short version with specific depth
demayer 0:6bf0743ece18 59
demayer 0:6bf0743ece18 60 # sections must be defined in this order to take irrelevant out
demayer 0:6bf0743ece18 61 self.all_sections = self.sections + self.other_sections + \
demayer 0:6bf0743ece18 62 self.misc_flash_sections + ('unknown', 'OUTPUT')
demayer 0:6bf0743ece18 63
demayer 0:6bf0743ece18 64 # Memory report (sections + summary)
demayer 0:6bf0743ece18 65 self.mem_report = []
demayer 0:6bf0743ece18 66
demayer 0:6bf0743ece18 67 # Just the memory summary section
demayer 0:6bf0743ece18 68 self.mem_summary = dict()
demayer 0:6bf0743ece18 69
demayer 0:6bf0743ece18 70 self.subtotal = dict()
demayer 0:6bf0743ece18 71
demayer 0:6bf0743ece18 72 self.misc_flash_mem = 0
demayer 0:6bf0743ece18 73
demayer 0:6bf0743ece18 74 # Modules passed to the linker on the command line
demayer 0:6bf0743ece18 75 # this is a dict because modules are looked up by their basename
demayer 0:6bf0743ece18 76 self.cmd_modules = {}
demayer 0:6bf0743ece18 77
demayer 0:6bf0743ece18 78
demayer 0:6bf0743ece18 79 def module_add(self, object_name, size, section):
demayer 0:6bf0743ece18 80 """ Adds a module / section to the list
demayer 0:6bf0743ece18 81
demayer 0:6bf0743ece18 82 Positional arguments:
demayer 0:6bf0743ece18 83 object_name - name of the entry to add
demayer 0:6bf0743ece18 84 size - the size of the module being added
demayer 0:6bf0743ece18 85 section - the section the module contributes to
demayer 0:6bf0743ece18 86 """
demayer 0:6bf0743ece18 87
demayer 0:6bf0743ece18 88 if not object_name or not size or not section:
demayer 0:6bf0743ece18 89 return
demayer 0:6bf0743ece18 90
demayer 0:6bf0743ece18 91 if object_name in self.modules:
demayer 0:6bf0743ece18 92 self.modules[object_name].setdefault(section, 0)
demayer 0:6bf0743ece18 93 self.modules[object_name][section] += size
demayer 0:6bf0743ece18 94 return
demayer 0:6bf0743ece18 95
demayer 0:6bf0743ece18 96 obj_split = os.sep + os.path.basename(object_name)
demayer 0:6bf0743ece18 97 for module_path, contents in self.modules.items():
demayer 0:6bf0743ece18 98 if module_path.endswith(obj_split) or module_path == object_name:
demayer 0:6bf0743ece18 99 contents.setdefault(section, 0)
demayer 0:6bf0743ece18 100 contents[section] += size
demayer 0:6bf0743ece18 101 return
demayer 0:6bf0743ece18 102
demayer 0:6bf0743ece18 103 new_module = {section: size}
demayer 0:6bf0743ece18 104 self.modules[object_name] = new_module
demayer 0:6bf0743ece18 105
demayer 0:6bf0743ece18 106 def module_replace(self, old_object, new_object):
demayer 0:6bf0743ece18 107 """ Replaces an object name with a new one
demayer 0:6bf0743ece18 108 """
demayer 0:6bf0743ece18 109 if old_object in self.modules:
demayer 0:6bf0743ece18 110 self.modules[new_object] = self.modules[old_object]
demayer 0:6bf0743ece18 111 del self.modules[old_object]
demayer 0:6bf0743ece18 112
demayer 0:6bf0743ece18 113 def check_new_section_gcc(self, line):
demayer 0:6bf0743ece18 114 """ Check whether a new section in a map file has been detected (only
demayer 0:6bf0743ece18 115 applies to gcc)
demayer 0:6bf0743ece18 116
demayer 0:6bf0743ece18 117 Positional arguments:
demayer 0:6bf0743ece18 118 line - the line to check for a new section
demayer 0:6bf0743ece18 119 """
demayer 0:6bf0743ece18 120
demayer 0:6bf0743ece18 121 for i in self.all_sections:
demayer 0:6bf0743ece18 122 if line.startswith(i):
demayer 0:6bf0743ece18 123 # should name of the section (assuming it's a known one)
demayer 0:6bf0743ece18 124 return i
demayer 0:6bf0743ece18 125
demayer 0:6bf0743ece18 126 if line.startswith('.'):
demayer 0:6bf0743ece18 127 return 'unknown' # all others are classified are unknown
demayer 0:6bf0743ece18 128 else:
demayer 0:6bf0743ece18 129 return False # everything else, means no change in section
demayer 0:6bf0743ece18 130
demayer 0:6bf0743ece18 131
demayer 0:6bf0743ece18 132 def parse_object_name_gcc(self, line):
demayer 0:6bf0743ece18 133 """ Parse a path to object file
demayer 0:6bf0743ece18 134
demayer 0:6bf0743ece18 135 Positional arguments:
demayer 0:6bf0743ece18 136 txt - the path to parse the object and module name from
demayer 0:6bf0743ece18 137 """
demayer 0:6bf0743ece18 138
demayer 0:6bf0743ece18 139 line = line.replace('\\', '/')
demayer 0:6bf0743ece18 140 test_re_mbed_os_name = re.match(RE_OBJECT_FILE_GCC, line)
demayer 0:6bf0743ece18 141
demayer 0:6bf0743ece18 142 if test_re_mbed_os_name:
demayer 0:6bf0743ece18 143
demayer 0:6bf0743ece18 144 object_name = test_re_mbed_os_name.group(1)
demayer 0:6bf0743ece18 145
demayer 0:6bf0743ece18 146 # corner case: certain objects are provided by the GCC toolchain
demayer 0:6bf0743ece18 147 if 'arm-none-eabi' in line:
demayer 0:6bf0743ece18 148 return '[lib]/misc/' + object_name
demayer 0:6bf0743ece18 149 return object_name
demayer 0:6bf0743ece18 150
demayer 0:6bf0743ece18 151 else:
demayer 0:6bf0743ece18 152
demayer 0:6bf0743ece18 153 test_re_obj_name = re.match(RE_LIBRARY_OBJECT_GCC, line)
demayer 0:6bf0743ece18 154
demayer 0:6bf0743ece18 155 if test_re_obj_name:
demayer 0:6bf0743ece18 156 object_name = test_re_obj_name.group(1) + '/' + \
demayer 0:6bf0743ece18 157 test_re_obj_name.group(2)
demayer 0:6bf0743ece18 158
demayer 0:6bf0743ece18 159 return '[lib]/' + object_name
demayer 0:6bf0743ece18 160
demayer 0:6bf0743ece18 161 else:
demayer 0:6bf0743ece18 162 print "Unknown object name found in GCC map file: %s" % line
demayer 0:6bf0743ece18 163 return '[misc]'
demayer 0:6bf0743ece18 164
demayer 0:6bf0743ece18 165 def parse_section_gcc(self, line):
demayer 0:6bf0743ece18 166 """ Parse data from a section of gcc map file
demayer 0:6bf0743ece18 167
demayer 0:6bf0743ece18 168 examples:
demayer 0:6bf0743ece18 169 0x00004308 0x7c ./BUILD/K64F/GCC_ARM/mbed-os/hal/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/spi_api.o
demayer 0:6bf0743ece18 170 .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
demayer 0:6bf0743ece18 171
demayer 0:6bf0743ece18 172 Positional arguments:
demayer 0:6bf0743ece18 173 line - the line to parse a section from
demayer 0:6bf0743ece18 174 """
demayer 0:6bf0743ece18 175
demayer 0:6bf0743ece18 176 is_fill = re.match(RE_FILL_SECTION_GCC, line)
demayer 0:6bf0743ece18 177 if is_fill:
demayer 0:6bf0743ece18 178 o_name = '[fill]'
demayer 0:6bf0743ece18 179 o_size = int(is_fill.group(2), 16)
demayer 0:6bf0743ece18 180 return [o_name, o_size]
demayer 0:6bf0743ece18 181
demayer 0:6bf0743ece18 182 is_section = re.match(RE_STD_SECTION_GCC, line)
demayer 0:6bf0743ece18 183 if is_section:
demayer 0:6bf0743ece18 184 o_size = int(is_section.group(2), 16)
demayer 0:6bf0743ece18 185 if o_size:
demayer 0:6bf0743ece18 186 o_name = self.parse_object_name_gcc(is_section.group(3))
demayer 0:6bf0743ece18 187 return [o_name, o_size]
demayer 0:6bf0743ece18 188
demayer 0:6bf0743ece18 189 return ["", 0]
demayer 0:6bf0743ece18 190
demayer 0:6bf0743ece18 191 def parse_map_file_gcc(self, file_desc):
demayer 0:6bf0743ece18 192 """ Main logic to decode gcc map files
demayer 0:6bf0743ece18 193
demayer 0:6bf0743ece18 194 Positional arguments:
demayer 0:6bf0743ece18 195 file_desc - a stream object to parse as a gcc map file
demayer 0:6bf0743ece18 196 """
demayer 0:6bf0743ece18 197
demayer 0:6bf0743ece18 198 current_section = 'unknown'
demayer 0:6bf0743ece18 199
demayer 0:6bf0743ece18 200 with file_desc as infile:
demayer 0:6bf0743ece18 201 for line in infile:
demayer 0:6bf0743ece18 202 if line.startswith('Linker script and memory map'):
demayer 0:6bf0743ece18 203 current_section = "unknown"
demayer 0:6bf0743ece18 204 break
demayer 0:6bf0743ece18 205
demayer 0:6bf0743ece18 206 for line in infile:
demayer 0:6bf0743ece18 207 next_section = self.check_new_section_gcc(line)
demayer 0:6bf0743ece18 208
demayer 0:6bf0743ece18 209 if next_section == "OUTPUT":
demayer 0:6bf0743ece18 210 break
demayer 0:6bf0743ece18 211 elif next_section:
demayer 0:6bf0743ece18 212 current_section = next_section
demayer 0:6bf0743ece18 213
demayer 0:6bf0743ece18 214 object_name, object_size = self.parse_section_gcc(line)
demayer 0:6bf0743ece18 215
demayer 0:6bf0743ece18 216 self.module_add(object_name, object_size, current_section)
demayer 0:6bf0743ece18 217
demayer 0:6bf0743ece18 218 common_prefix = os.path.dirname(os.path.commonprefix([
demayer 0:6bf0743ece18 219 o for o in self.modules.keys() if (o.endswith(".o") and not o.startswith("[lib]"))]))
demayer 0:6bf0743ece18 220 new_modules = {}
demayer 0:6bf0743ece18 221 for name, stats in self.modules.items():
demayer 0:6bf0743ece18 222 if name.startswith("[lib]"):
demayer 0:6bf0743ece18 223 new_modules[name] = stats
demayer 0:6bf0743ece18 224 elif name.endswith(".o"):
demayer 0:6bf0743ece18 225 new_modules[os.path.relpath(name, common_prefix)] = stats
demayer 0:6bf0743ece18 226 else:
demayer 0:6bf0743ece18 227 new_modules[name] = stats
demayer 0:6bf0743ece18 228 self.modules = new_modules
demayer 0:6bf0743ece18 229
demayer 0:6bf0743ece18 230 def parse_object_name_armcc(self, line):
demayer 0:6bf0743ece18 231 """ Parse object file
demayer 0:6bf0743ece18 232
demayer 0:6bf0743ece18 233 Positional arguments:
demayer 0:6bf0743ece18 234 line - the line containing the object or library
demayer 0:6bf0743ece18 235 """
demayer 0:6bf0743ece18 236
demayer 0:6bf0743ece18 237 # simple object (not library)
demayer 0:6bf0743ece18 238 if line[-2] == '.' and line[-1] == 'o':
demayer 0:6bf0743ece18 239 return line
demayer 0:6bf0743ece18 240
demayer 0:6bf0743ece18 241 else:
demayer 0:6bf0743ece18 242 is_obj = re.match(RE_OBJECT_ARMCC, line)
demayer 0:6bf0743ece18 243 if is_obj:
demayer 0:6bf0743ece18 244 object_name = os.path.basename(is_obj.group(1)) + '/' + is_obj.group(3)
demayer 0:6bf0743ece18 245 return '[lib]/' + object_name
demayer 0:6bf0743ece18 246 else:
demayer 0:6bf0743ece18 247 print "Malformed input found when parsing ARMCC map: %s" % line
demayer 0:6bf0743ece18 248 return '[misc]'
demayer 0:6bf0743ece18 249
demayer 0:6bf0743ece18 250
demayer 0:6bf0743ece18 251
demayer 0:6bf0743ece18 252 def parse_section_armcc(self, line):
demayer 0:6bf0743ece18 253 """ Parse data from an armcc map file
demayer 0:6bf0743ece18 254
demayer 0:6bf0743ece18 255 Examples of armcc map file:
demayer 0:6bf0743ece18 256 Base_Addr Size Type Attr Idx E Section Name Object
demayer 0:6bf0743ece18 257 0x00000000 0x00000400 Data RO 11222 RESET startup_MK64F12.o
demayer 0:6bf0743ece18 258 0x00000410 0x00000008 Code RO 49364 * !!!main c_w.l(__main.o)
demayer 0:6bf0743ece18 259
demayer 0:6bf0743ece18 260 Positional arguments:
demayer 0:6bf0743ece18 261 line - the line to parse the section data from
demayer 0:6bf0743ece18 262 """
demayer 0:6bf0743ece18 263
demayer 0:6bf0743ece18 264 test_re_armcc = re.match(RE_ARMCC, line)
demayer 0:6bf0743ece18 265
demayer 0:6bf0743ece18 266 if test_re_armcc:
demayer 0:6bf0743ece18 267
demayer 0:6bf0743ece18 268 size = int(test_re_armcc.group(2), 16)
demayer 0:6bf0743ece18 269
demayer 0:6bf0743ece18 270 if test_re_armcc.group(4) == 'RO':
demayer 0:6bf0743ece18 271 section = '.text'
demayer 0:6bf0743ece18 272 else:
demayer 0:6bf0743ece18 273 if test_re_armcc.group(3) == 'Data':
demayer 0:6bf0743ece18 274 section = '.data'
demayer 0:6bf0743ece18 275 elif test_re_armcc.group(3) == 'Zero':
demayer 0:6bf0743ece18 276 section = '.bss'
demayer 0:6bf0743ece18 277 else:
demayer 0:6bf0743ece18 278 print "Malformed input found when parsing armcc map: %s" %\
demayer 0:6bf0743ece18 279 line
demayer 0:6bf0743ece18 280
demayer 0:6bf0743ece18 281 # check name of object or library
demayer 0:6bf0743ece18 282 object_name = self.parse_object_name_armcc(\
demayer 0:6bf0743ece18 283 test_re_armcc.group(6))
demayer 0:6bf0743ece18 284
demayer 0:6bf0743ece18 285 return [object_name, size, section]
demayer 0:6bf0743ece18 286
demayer 0:6bf0743ece18 287 else:
demayer 0:6bf0743ece18 288 return ["", 0, ""]
demayer 0:6bf0743ece18 289
demayer 0:6bf0743ece18 290 def parse_object_name_iar(self, object_name):
demayer 0:6bf0743ece18 291 """ Parse object file
demayer 0:6bf0743ece18 292
demayer 0:6bf0743ece18 293 Positional arguments:
demayer 0:6bf0743ece18 294 line - the line containing the object or library
demayer 0:6bf0743ece18 295 """
demayer 0:6bf0743ece18 296
demayer 0:6bf0743ece18 297 # simple object (not library)
demayer 0:6bf0743ece18 298 if object_name.endswith(".o"):
demayer 0:6bf0743ece18 299 try:
demayer 0:6bf0743ece18 300 return self.cmd_modules[object_name]
demayer 0:6bf0743ece18 301 except KeyError:
demayer 0:6bf0743ece18 302 return object_name
demayer 0:6bf0743ece18 303 else:
demayer 0:6bf0743ece18 304 return '[misc]'
demayer 0:6bf0743ece18 305
demayer 0:6bf0743ece18 306
demayer 0:6bf0743ece18 307 def parse_section_iar(self, line):
demayer 0:6bf0743ece18 308 """ Parse data from an IAR map file
demayer 0:6bf0743ece18 309
demayer 0:6bf0743ece18 310 Examples of IAR map file:
demayer 0:6bf0743ece18 311 Section Kind Address Size Object
demayer 0:6bf0743ece18 312 .intvec ro code 0x00000000 0x198 startup_MK64F12.o [15]
demayer 0:6bf0743ece18 313 .rodata const 0x00000198 0x0 zero_init3.o [133]
demayer 0:6bf0743ece18 314 .iar.init_table const 0x00008384 0x2c - Linker created -
demayer 0:6bf0743ece18 315 Initializer bytes const 0x00000198 0xb2 <for P3 s0>
demayer 0:6bf0743ece18 316 .data inited 0x20000000 0xd4 driverAtmelRFInterface.o [70]
demayer 0:6bf0743ece18 317 .bss zero 0x20000598 0x318 RTX_Conf_CM.o [4]
demayer 0:6bf0743ece18 318 .iar.dynexit uninit 0x20001448 0x204 <Block tail>
demayer 0:6bf0743ece18 319 HEAP uninit 0x20001650 0x10000 <Block tail>
demayer 0:6bf0743ece18 320
demayer 0:6bf0743ece18 321 Positional_arguments:
demayer 0:6bf0743ece18 322 line - the line to parse section data from
demayer 0:6bf0743ece18 323 """
demayer 0:6bf0743ece18 324
demayer 0:6bf0743ece18 325 test_re_iar = re.match(RE_IAR, line)
demayer 0:6bf0743ece18 326
demayer 0:6bf0743ece18 327 if test_re_iar:
demayer 0:6bf0743ece18 328
demayer 0:6bf0743ece18 329 size = int(test_re_iar.group(4), 16)
demayer 0:6bf0743ece18 330
demayer 0:6bf0743ece18 331 if (test_re_iar.group(2) == 'const' or
demayer 0:6bf0743ece18 332 test_re_iar.group(2) == 'ro code'):
demayer 0:6bf0743ece18 333 section = '.text'
demayer 0:6bf0743ece18 334 elif (test_re_iar.group(2) == 'zero' or
demayer 0:6bf0743ece18 335 test_re_iar.group(2) == 'uninit'):
demayer 0:6bf0743ece18 336 if test_re_iar.group(1)[0:4] == 'HEAP':
demayer 0:6bf0743ece18 337 section = '.heap'
demayer 0:6bf0743ece18 338 elif test_re_iar.group(1)[0:6] == 'CSTACK':
demayer 0:6bf0743ece18 339 section = '.stack'
demayer 0:6bf0743ece18 340 else:
demayer 0:6bf0743ece18 341 section = '.bss' # default section
demayer 0:6bf0743ece18 342
demayer 0:6bf0743ece18 343 elif test_re_iar.group(2) == 'inited':
demayer 0:6bf0743ece18 344 section = '.data'
demayer 0:6bf0743ece18 345 else:
demayer 0:6bf0743ece18 346 print "Malformed input found when parsing IAR map: %s" % line
demayer 0:6bf0743ece18 347
demayer 0:6bf0743ece18 348 # lookup object in dictionary and return module name
demayer 0:6bf0743ece18 349 object_name = self.parse_object_name_iar(test_re_iar.group(5))
demayer 0:6bf0743ece18 350
demayer 0:6bf0743ece18 351 return [object_name, size, section]
demayer 0:6bf0743ece18 352
demayer 0:6bf0743ece18 353 else:
demayer 0:6bf0743ece18 354 return ["", 0, ""] # no valid entry
demayer 0:6bf0743ece18 355
demayer 0:6bf0743ece18 356 def parse_map_file_armcc(self, file_desc):
demayer 0:6bf0743ece18 357 """ Main logic to decode armc5 map files
demayer 0:6bf0743ece18 358
demayer 0:6bf0743ece18 359 Positional arguments:
demayer 0:6bf0743ece18 360 file_desc - a file like object to parse as an armc5 map file
demayer 0:6bf0743ece18 361 """
demayer 0:6bf0743ece18 362
demayer 0:6bf0743ece18 363 with file_desc as infile:
demayer 0:6bf0743ece18 364
demayer 0:6bf0743ece18 365 # Search area to parse
demayer 0:6bf0743ece18 366 for line in infile:
demayer 0:6bf0743ece18 367 if line.startswith(' Base Addr Size'):
demayer 0:6bf0743ece18 368 break
demayer 0:6bf0743ece18 369
demayer 0:6bf0743ece18 370 # Start decoding the map file
demayer 0:6bf0743ece18 371 for line in infile:
demayer 0:6bf0743ece18 372 self.module_add(*self.parse_section_armcc(line))
demayer 0:6bf0743ece18 373
demayer 0:6bf0743ece18 374 common_prefix = os.path.dirname(os.path.commonprefix([
demayer 0:6bf0743ece18 375 o for o in self.modules.keys() if (o.endswith(".o") and o != "anon$$obj.o" and not o.startswith("[lib]"))]))
demayer 0:6bf0743ece18 376 new_modules = {}
demayer 0:6bf0743ece18 377 for name, stats in self.modules.items():
demayer 0:6bf0743ece18 378 if name == "anon$$obj.o" or name.startswith("[lib]"):
demayer 0:6bf0743ece18 379 new_modules[name] = stats
demayer 0:6bf0743ece18 380 elif name.endswith(".o"):
demayer 0:6bf0743ece18 381 new_modules[os.path.relpath(name, common_prefix)] = stats
demayer 0:6bf0743ece18 382 else:
demayer 0:6bf0743ece18 383 new_modules[name] = stats
demayer 0:6bf0743ece18 384 self.modules = new_modules
demayer 0:6bf0743ece18 385
demayer 0:6bf0743ece18 386
demayer 0:6bf0743ece18 387
demayer 0:6bf0743ece18 388 def check_new_library_iar(self, line):
demayer 0:6bf0743ece18 389 """
demayer 0:6bf0743ece18 390 Searches for libraries and returns name. Example:
demayer 0:6bf0743ece18 391 m7M_tls.a: [43]
demayer 0:6bf0743ece18 392
demayer 0:6bf0743ece18 393 """
demayer 0:6bf0743ece18 394
demayer 0:6bf0743ece18 395
demayer 0:6bf0743ece18 396 test_address_line = re.match(RE_LIBRARY_IAR, line)
demayer 0:6bf0743ece18 397
demayer 0:6bf0743ece18 398 if test_address_line:
demayer 0:6bf0743ece18 399 return test_address_line.group(1)
demayer 0:6bf0743ece18 400 else:
demayer 0:6bf0743ece18 401 return ""
demayer 0:6bf0743ece18 402
demayer 0:6bf0743ece18 403 def check_new_object_lib_iar(self, line):
demayer 0:6bf0743ece18 404 """
demayer 0:6bf0743ece18 405 Searches for objects within a library section and returns name. Example:
demayer 0:6bf0743ece18 406 rt7M_tl.a: [44]
demayer 0:6bf0743ece18 407 ABImemclr4.o 6
demayer 0:6bf0743ece18 408 ABImemcpy_unaligned.o 118
demayer 0:6bf0743ece18 409 ABImemset48.o 50
demayer 0:6bf0743ece18 410 I64DivMod.o 238
demayer 0:6bf0743ece18 411 I64DivZer.o 2
demayer 0:6bf0743ece18 412
demayer 0:6bf0743ece18 413 """
demayer 0:6bf0743ece18 414
demayer 0:6bf0743ece18 415 test_address_line = re.match(RE_OBJECT_LIBRARY_IAR, line)
demayer 0:6bf0743ece18 416
demayer 0:6bf0743ece18 417 if test_address_line:
demayer 0:6bf0743ece18 418 return test_address_line.group(1)
demayer 0:6bf0743ece18 419 else:
demayer 0:6bf0743ece18 420 return ""
demayer 0:6bf0743ece18 421
demayer 0:6bf0743ece18 422 def parse_iar_command_line(self, lines):
demayer 0:6bf0743ece18 423 """Parse the files passed on the command line to the iar linker
demayer 0:6bf0743ece18 424
demayer 0:6bf0743ece18 425 Positional arguments:
demayer 0:6bf0743ece18 426 lines -- an iterator over the lines within a file
demayer 0:6bf0743ece18 427 """
demayer 0:6bf0743ece18 428 for line in lines:
demayer 0:6bf0743ece18 429 if line.startswith("*"):
demayer 0:6bf0743ece18 430 break
demayer 0:6bf0743ece18 431 is_cmdline_file = RE_CMDLINE_FILE_IAR.match(line)
demayer 0:6bf0743ece18 432 if is_cmdline_file:
demayer 0:6bf0743ece18 433 full_path = is_cmdline_file.group(1)
demayer 0:6bf0743ece18 434 self.cmd_modules[os.path.basename(full_path)] = full_path
demayer 0:6bf0743ece18 435
demayer 0:6bf0743ece18 436 common_prefix = os.path.dirname(os.path.commonprefix(self.cmd_modules.values()))
demayer 0:6bf0743ece18 437 self.cmd_modules = {s: os.path.relpath(f, common_prefix)
demayer 0:6bf0743ece18 438 for s, f in self.cmd_modules.items()}
demayer 0:6bf0743ece18 439
demayer 0:6bf0743ece18 440
demayer 0:6bf0743ece18 441 def parse_map_file_iar(self, file_desc):
demayer 0:6bf0743ece18 442 """ Main logic to decode IAR map files
demayer 0:6bf0743ece18 443
demayer 0:6bf0743ece18 444 Positional arguments:
demayer 0:6bf0743ece18 445 file_desc - a file like object to parse as an IAR map file
demayer 0:6bf0743ece18 446 """
demayer 0:6bf0743ece18 447
demayer 0:6bf0743ece18 448 with file_desc as infile:
demayer 0:6bf0743ece18 449 self.parse_iar_command_line(infile)
demayer 0:6bf0743ece18 450
demayer 0:6bf0743ece18 451 for line in infile:
demayer 0:6bf0743ece18 452 if line.startswith(' Section '):
demayer 0:6bf0743ece18 453 break
demayer 0:6bf0743ece18 454
demayer 0:6bf0743ece18 455 for line in infile:
demayer 0:6bf0743ece18 456 self.module_add(*self.parse_section_iar(line))
demayer 0:6bf0743ece18 457
demayer 0:6bf0743ece18 458 if line.startswith('*** MODULE SUMMARY'): # finish section
demayer 0:6bf0743ece18 459 break
demayer 0:6bf0743ece18 460
demayer 0:6bf0743ece18 461 current_library = ""
demayer 0:6bf0743ece18 462 for line in infile:
demayer 0:6bf0743ece18 463
demayer 0:6bf0743ece18 464 library = self.check_new_library_iar(line)
demayer 0:6bf0743ece18 465
demayer 0:6bf0743ece18 466 if library:
demayer 0:6bf0743ece18 467 current_library = library
demayer 0:6bf0743ece18 468
demayer 0:6bf0743ece18 469 object_name = self.check_new_object_lib_iar(line)
demayer 0:6bf0743ece18 470
demayer 0:6bf0743ece18 471 if object_name and current_library:
demayer 0:6bf0743ece18 472 temp = '[lib]' + '/'+ current_library + '/'+ object_name
demayer 0:6bf0743ece18 473 self.module_replace(object_name, temp)
demayer 0:6bf0743ece18 474
demayer 0:6bf0743ece18 475
demayer 0:6bf0743ece18 476 def reduce_depth(self, depth):
demayer 0:6bf0743ece18 477 """
demayer 0:6bf0743ece18 478 populates the short_modules attribute with a truncated module list
demayer 0:6bf0743ece18 479
demayer 0:6bf0743ece18 480 (1) depth = 1:
demayer 0:6bf0743ece18 481 main.o
demayer 0:6bf0743ece18 482 mbed-os
demayer 0:6bf0743ece18 483
demayer 0:6bf0743ece18 484 (2) depth = 2:
demayer 0:6bf0743ece18 485 main.o
demayer 0:6bf0743ece18 486 mbed-os/test.o
demayer 0:6bf0743ece18 487 mbed-os/drivers
demayer 0:6bf0743ece18 488
demayer 0:6bf0743ece18 489 """
demayer 0:6bf0743ece18 490 if depth == 0 or depth == None:
demayer 0:6bf0743ece18 491 self.short_modules = deepcopy(self.modules)
demayer 0:6bf0743ece18 492 else:
demayer 0:6bf0743ece18 493 self.short_modules = dict()
demayer 0:6bf0743ece18 494 for module_name, v in self.modules.items():
demayer 0:6bf0743ece18 495 split_name = module_name.split('/')
demayer 0:6bf0743ece18 496 if split_name[0] == '':
demayer 0:6bf0743ece18 497 split_name = split_name[1:]
demayer 0:6bf0743ece18 498 new_name = "/".join(split_name[:depth])
demayer 0:6bf0743ece18 499 self.short_modules.setdefault(new_name, {})
demayer 0:6bf0743ece18 500 for section_idx, value in v.items():
demayer 0:6bf0743ece18 501 self.short_modules[new_name].setdefault(section_idx, 0)
demayer 0:6bf0743ece18 502 self.short_modules[new_name][section_idx] += self.modules[module_name][section_idx]
demayer 0:6bf0743ece18 503
demayer 0:6bf0743ece18 504
demayer 0:6bf0743ece18 505 export_formats = ["json", "csv-ci", "table"]
demayer 0:6bf0743ece18 506
demayer 0:6bf0743ece18 507 def generate_output(self, export_format, depth, file_output=None):
demayer 0:6bf0743ece18 508 """ Generates summary of memory map data
demayer 0:6bf0743ece18 509
demayer 0:6bf0743ece18 510 Positional arguments:
demayer 0:6bf0743ece18 511 export_format - the format to dump
demayer 0:6bf0743ece18 512
demayer 0:6bf0743ece18 513 Keyword arguments:
demayer 0:6bf0743ece18 514 file_desc - descriptor (either stdout or file)
demayer 0:6bf0743ece18 515 depth - directory depth on report
demayer 0:6bf0743ece18 516
demayer 0:6bf0743ece18 517 Returns: generated string for the 'table' format, otherwise None
demayer 0:6bf0743ece18 518 """
demayer 0:6bf0743ece18 519
demayer 0:6bf0743ece18 520 self.reduce_depth(depth)
demayer 0:6bf0743ece18 521 self.compute_report()
demayer 0:6bf0743ece18 522
demayer 0:6bf0743ece18 523 try:
demayer 0:6bf0743ece18 524 if file_output:
demayer 0:6bf0743ece18 525 file_desc = open(file_output, 'wb')
demayer 0:6bf0743ece18 526 else:
demayer 0:6bf0743ece18 527 file_desc = sys.stdout
demayer 0:6bf0743ece18 528 except IOError as error:
demayer 0:6bf0743ece18 529 print "I/O error({0}): {1}".format(error.errno, error.strerror)
demayer 0:6bf0743ece18 530 return False
demayer 0:6bf0743ece18 531
demayer 0:6bf0743ece18 532 to_call = {'json': self.generate_json,
demayer 0:6bf0743ece18 533 'csv-ci': self.generate_csv,
demayer 0:6bf0743ece18 534 'table': self.generate_table}[export_format]
demayer 0:6bf0743ece18 535 output = to_call(file_desc)
demayer 0:6bf0743ece18 536
demayer 0:6bf0743ece18 537 if file_desc is not sys.stdout:
demayer 0:6bf0743ece18 538 file_desc.close()
demayer 0:6bf0743ece18 539
demayer 0:6bf0743ece18 540 return output
demayer 0:6bf0743ece18 541
demayer 0:6bf0743ece18 542 def generate_json(self, file_desc):
demayer 0:6bf0743ece18 543 """Generate a json file from a memory map
demayer 0:6bf0743ece18 544
demayer 0:6bf0743ece18 545 Positional arguments:
demayer 0:6bf0743ece18 546 file_desc - the file to write out the final report to
demayer 0:6bf0743ece18 547 """
demayer 0:6bf0743ece18 548 file_desc.write(json.dumps(self.mem_report, indent=4))
demayer 0:6bf0743ece18 549 file_desc.write('\n')
demayer 0:6bf0743ece18 550
demayer 0:6bf0743ece18 551 return None
demayer 0:6bf0743ece18 552
demayer 0:6bf0743ece18 553 def generate_csv(self, file_desc):
demayer 0:6bf0743ece18 554 """Generate a CSV file from a memoy map
demayer 0:6bf0743ece18 555
demayer 0:6bf0743ece18 556 Positional arguments:
demayer 0:6bf0743ece18 557 file_desc - the file to write out the final report to
demayer 0:6bf0743ece18 558 """
demayer 0:6bf0743ece18 559 csv_writer = csv.writer(file_desc, delimiter=',',
demayer 0:6bf0743ece18 560 quoting=csv.QUOTE_MINIMAL)
demayer 0:6bf0743ece18 561
demayer 0:6bf0743ece18 562 csv_module_section = []
demayer 0:6bf0743ece18 563 csv_sizes = []
demayer 0:6bf0743ece18 564 for i in sorted(self.short_modules):
demayer 0:6bf0743ece18 565 for k in self.print_sections:
demayer 0:6bf0743ece18 566 csv_module_section += [i+k]
demayer 0:6bf0743ece18 567 csv_sizes += [self.short_modules[i][k]]
demayer 0:6bf0743ece18 568
demayer 0:6bf0743ece18 569 csv_module_section += ['static_ram']
demayer 0:6bf0743ece18 570 csv_sizes += [self.mem_summary['static_ram']]
demayer 0:6bf0743ece18 571
demayer 0:6bf0743ece18 572 csv_module_section += ['total_flash']
demayer 0:6bf0743ece18 573 csv_sizes += [self.mem_summary['total_flash']]
demayer 0:6bf0743ece18 574
demayer 0:6bf0743ece18 575 csv_writer.writerow(csv_module_section)
demayer 0:6bf0743ece18 576 csv_writer.writerow(csv_sizes)
demayer 0:6bf0743ece18 577
demayer 0:6bf0743ece18 578 return None
demayer 0:6bf0743ece18 579
demayer 0:6bf0743ece18 580 def generate_table(self, file_desc):
demayer 0:6bf0743ece18 581 """Generate a table from a memoy map
demayer 0:6bf0743ece18 582
demayer 0:6bf0743ece18 583 Returns: string of the generated table
demayer 0:6bf0743ece18 584 """
demayer 0:6bf0743ece18 585 # Create table
demayer 0:6bf0743ece18 586 columns = ['Module']
demayer 0:6bf0743ece18 587 columns.extend(self.print_sections)
demayer 0:6bf0743ece18 588
demayer 0:6bf0743ece18 589 table = PrettyTable(columns)
demayer 0:6bf0743ece18 590 table.align["Module"] = "l"
demayer 0:6bf0743ece18 591 for col in self.print_sections:
demayer 0:6bf0743ece18 592 table.align[col] = 'r'
demayer 0:6bf0743ece18 593
demayer 0:6bf0743ece18 594 for i in list(self.print_sections):
demayer 0:6bf0743ece18 595 table.align[i] = 'r'
demayer 0:6bf0743ece18 596
demayer 0:6bf0743ece18 597 for i in sorted(self.short_modules):
demayer 0:6bf0743ece18 598 row = [i]
demayer 0:6bf0743ece18 599
demayer 0:6bf0743ece18 600 for k in self.print_sections:
demayer 0:6bf0743ece18 601 row.append(self.short_modules[i][k])
demayer 0:6bf0743ece18 602
demayer 0:6bf0743ece18 603 table.add_row(row)
demayer 0:6bf0743ece18 604
demayer 0:6bf0743ece18 605 subtotal_row = ['Subtotals']
demayer 0:6bf0743ece18 606 for k in self.print_sections:
demayer 0:6bf0743ece18 607 subtotal_row.append(self.subtotal[k])
demayer 0:6bf0743ece18 608
demayer 0:6bf0743ece18 609 table.add_row(subtotal_row)
demayer 0:6bf0743ece18 610
demayer 0:6bf0743ece18 611 output = table.get_string()
demayer 0:6bf0743ece18 612 output += '\n'
demayer 0:6bf0743ece18 613
demayer 0:6bf0743ece18 614 output += "Total Static RAM memory (data + bss): %s bytes\n" % \
demayer 0:6bf0743ece18 615 str(self.mem_summary['static_ram'])
demayer 0:6bf0743ece18 616 output += "Total Flash memory (text + data): %s bytes\n" % \
demayer 0:6bf0743ece18 617 str(self.mem_summary['total_flash'])
demayer 0:6bf0743ece18 618
demayer 0:6bf0743ece18 619 return output
demayer 0:6bf0743ece18 620
demayer 0:6bf0743ece18 621 toolchains = ["ARM", "ARM_STD", "ARM_MICRO", "GCC_ARM", "GCC_CR", "IAR"]
demayer 0:6bf0743ece18 622
demayer 0:6bf0743ece18 623 def compute_report(self):
demayer 0:6bf0743ece18 624 """ Generates summary of memory usage for main areas
demayer 0:6bf0743ece18 625 """
demayer 0:6bf0743ece18 626 for k in self.sections:
demayer 0:6bf0743ece18 627 self.subtotal[k] = 0
demayer 0:6bf0743ece18 628
demayer 0:6bf0743ece18 629 for i in self.short_modules:
demayer 0:6bf0743ece18 630 for k in self.sections:
demayer 0:6bf0743ece18 631 self.short_modules[i].setdefault(k, 0)
demayer 0:6bf0743ece18 632 self.subtotal[k] += self.short_modules[i][k]
demayer 0:6bf0743ece18 633
demayer 0:6bf0743ece18 634 self.mem_summary = {
demayer 0:6bf0743ece18 635 'static_ram': (self.subtotal['.data'] + self.subtotal['.bss']),
demayer 0:6bf0743ece18 636 'total_flash': (self.subtotal['.text'] + self.subtotal['.data']),
demayer 0:6bf0743ece18 637 }
demayer 0:6bf0743ece18 638
demayer 0:6bf0743ece18 639 self.mem_report = []
demayer 0:6bf0743ece18 640 for i in sorted(self.short_modules):
demayer 0:6bf0743ece18 641 self.mem_report.append({
demayer 0:6bf0743ece18 642 "module":i,
demayer 0:6bf0743ece18 643 "size":{
demayer 0:6bf0743ece18 644 k: self.short_modules[i][k] for k in self.print_sections
demayer 0:6bf0743ece18 645 }
demayer 0:6bf0743ece18 646 })
demayer 0:6bf0743ece18 647
demayer 0:6bf0743ece18 648 self.mem_report.append({
demayer 0:6bf0743ece18 649 'summary': self.mem_summary
demayer 0:6bf0743ece18 650 })
demayer 0:6bf0743ece18 651
demayer 0:6bf0743ece18 652 def parse(self, mapfile, toolchain):
demayer 0:6bf0743ece18 653 """ Parse and decode map file depending on the toolchain
demayer 0:6bf0743ece18 654
demayer 0:6bf0743ece18 655 Positional arguments:
demayer 0:6bf0743ece18 656 mapfile - the file name of the memory map file
demayer 0:6bf0743ece18 657 toolchain - the toolchain used to create the file
demayer 0:6bf0743ece18 658 """
demayer 0:6bf0743ece18 659
demayer 0:6bf0743ece18 660 result = True
demayer 0:6bf0743ece18 661 try:
demayer 0:6bf0743ece18 662 with open(mapfile, 'r') as file_input:
demayer 0:6bf0743ece18 663 if toolchain in ("ARM", "ARM_STD", "ARM_MICRO", "ARMC6"):
demayer 0:6bf0743ece18 664 self.parse_map_file_armcc(file_input)
demayer 0:6bf0743ece18 665 elif toolchain == "GCC_ARM" or toolchain == "GCC_CR":
demayer 0:6bf0743ece18 666 self.parse_map_file_gcc(file_input)
demayer 0:6bf0743ece18 667 elif toolchain == "IAR":
demayer 0:6bf0743ece18 668 self.parse_map_file_iar(file_input)
demayer 0:6bf0743ece18 669 else:
demayer 0:6bf0743ece18 670 result = False
demayer 0:6bf0743ece18 671
demayer 0:6bf0743ece18 672 except IOError as error:
demayer 0:6bf0743ece18 673 print "I/O error({0}): {1}".format(error.errno, error.strerror)
demayer 0:6bf0743ece18 674 result = False
demayer 0:6bf0743ece18 675 return result
demayer 0:6bf0743ece18 676
demayer 0:6bf0743ece18 677 def main():
demayer 0:6bf0743ece18 678 """Entry Point"""
demayer 0:6bf0743ece18 679
demayer 0:6bf0743ece18 680 version = '0.4.0'
demayer 0:6bf0743ece18 681
demayer 0:6bf0743ece18 682 # Parser handling
demayer 0:6bf0743ece18 683 parser = argparse.ArgumentParser(
demayer 0:6bf0743ece18 684 description="Memory Map File Analyser for ARM mbed\nversion %s" %
demayer 0:6bf0743ece18 685 version)
demayer 0:6bf0743ece18 686
demayer 0:6bf0743ece18 687 parser.add_argument(
demayer 0:6bf0743ece18 688 'file', type=argparse_filestring_type, help='memory map file')
demayer 0:6bf0743ece18 689
demayer 0:6bf0743ece18 690 parser.add_argument(
demayer 0:6bf0743ece18 691 '-t', '--toolchain', dest='toolchain',
demayer 0:6bf0743ece18 692 help='select a toolchain used to build the memory map file (%s)' %
demayer 0:6bf0743ece18 693 ", ".join(MemapParser.toolchains),
demayer 0:6bf0743ece18 694 required=True,
demayer 0:6bf0743ece18 695 type=argparse_uppercase_type(MemapParser.toolchains, "toolchain"))
demayer 0:6bf0743ece18 696
demayer 0:6bf0743ece18 697 parser.add_argument(
demayer 0:6bf0743ece18 698 '-d', '--depth', dest='depth', type=int,
demayer 0:6bf0743ece18 699 help='specify directory depth level to display report', required=False)
demayer 0:6bf0743ece18 700
demayer 0:6bf0743ece18 701 parser.add_argument(
demayer 0:6bf0743ece18 702 '-o', '--output', help='output file name', required=False)
demayer 0:6bf0743ece18 703
demayer 0:6bf0743ece18 704 parser.add_argument(
demayer 0:6bf0743ece18 705 '-e', '--export', dest='export', required=False, default='table',
demayer 0:6bf0743ece18 706 type=argparse_lowercase_hyphen_type(MemapParser.export_formats,
demayer 0:6bf0743ece18 707 'export format'),
demayer 0:6bf0743ece18 708 help="export format (examples: %s: default)" %
demayer 0:6bf0743ece18 709 ", ".join(MemapParser.export_formats))
demayer 0:6bf0743ece18 710
demayer 0:6bf0743ece18 711 parser.add_argument('-v', '--version', action='version', version=version)
demayer 0:6bf0743ece18 712
demayer 0:6bf0743ece18 713 # Parse/run command
demayer 0:6bf0743ece18 714 if len(sys.argv) <= 1:
demayer 0:6bf0743ece18 715 parser.print_help()
demayer 0:6bf0743ece18 716 sys.exit(1)
demayer 0:6bf0743ece18 717
demayer 0:6bf0743ece18 718 args = parser.parse_args()
demayer 0:6bf0743ece18 719
demayer 0:6bf0743ece18 720 # Create memap object
demayer 0:6bf0743ece18 721 memap = MemapParser()
demayer 0:6bf0743ece18 722
demayer 0:6bf0743ece18 723 # Parse and decode a map file
demayer 0:6bf0743ece18 724 if args.file and args.toolchain:
demayer 0:6bf0743ece18 725 if memap.parse(args.file, args.toolchain) is False:
demayer 0:6bf0743ece18 726 sys.exit(0)
demayer 0:6bf0743ece18 727
demayer 0:6bf0743ece18 728 if args.depth is None:
demayer 0:6bf0743ece18 729 depth = 2 # default depth level
demayer 0:6bf0743ece18 730 else:
demayer 0:6bf0743ece18 731 depth = args.depth
demayer 0:6bf0743ece18 732
demayer 0:6bf0743ece18 733 returned_string = None
demayer 0:6bf0743ece18 734 # Write output in file
demayer 0:6bf0743ece18 735 if args.output != None:
demayer 0:6bf0743ece18 736 returned_string = memap.generate_output(args.export, \
demayer 0:6bf0743ece18 737 depth, args.output)
demayer 0:6bf0743ece18 738 else: # Write output in screen
demayer 0:6bf0743ece18 739 returned_string = memap.generate_output(args.export, depth)
demayer 0:6bf0743ece18 740
demayer 0:6bf0743ece18 741 if args.export == 'table' and returned_string:
demayer 0:6bf0743ece18 742 print returned_string
demayer 0:6bf0743ece18 743
demayer 0:6bf0743ece18 744 sys.exit(0)
demayer 0:6bf0743ece18 745
demayer 0:6bf0743ece18 746 if __name__ == "__main__":
demayer 0:6bf0743ece18 747 main()