2016-06-10 14:19:02 +00:00
#!/usr/bin/env python
# pylint: disable=too-many-arguments, too-many-locals, too-many-branches, too-many-lines, line-too-long, too-many-nested-blocks, too-many-public-methods, too-many-instance-attributes
# pylint: disable=invalid-name, missing-docstring
2016-06-09 22:50:03 +00:00
2016-06-27 14:02:05 +00:00
# Memory Map File Analyser for ARM mbed
2016-06-09 22:50:03 +00:00
import sys
import os
import re
2016-06-10 14:19:02 +00:00
import csv
2016-06-09 22:50:03 +00:00
import json
2016-06-10 14:19:02 +00:00
import argparse
2016-06-30 21:49:02 +00:00
from utils import argparse_uppercase_type , argparse_lowercase_hyphen_type , argparse_filestring_type
2016-06-09 22:50:03 +00:00
from prettytable import PrettyTable
debug = False
2016-06-10 14:19:02 +00:00
class MemapParser ( object ) :
2016-06-09 22:50:03 +00:00
def __init__ ( self ) :
"""
General initialization
"""
# list of all modules and their sections
self . modules = dict ( )
self . misc_flash_sections = ( ' .interrupts ' , ' .flash_config ' )
2016-06-28 15:34:28 +00:00
self . other_sections = ( ' .interrupts_ram ' , ' .init ' , ' .ARM.extab ' ,
' .ARM.exidx ' , ' .ARM.attributes ' , ' .eh_frame ' ,
' .init_array ' , ' .fini_array ' , ' .jcr ' , ' .stab ' ,
2016-06-10 14:19:02 +00:00
' .stabstr ' , ' .ARM.exidx ' , ' .ARM ' )
2016-06-09 22:50:03 +00:00
# sections to print info (generic for all toolchains)
2016-06-10 14:19:02 +00:00
self . sections = ( ' .text ' , ' .data ' , ' .bss ' , ' .heap ' , ' .stack ' )
2016-06-09 22:50:03 +00:00
2016-06-10 14:19:02 +00:00
# sections must be defined in this order to take irrelevant out
2016-06-09 22:50:03 +00:00
self . all_sections = self . sections + self . other_sections + \
self . misc_flash_sections + ( ' unknown ' , ' OUTPUT ' )
self . print_sections = ( ' .text ' , ' .data ' , ' .bss ' )
# list of all object files and mappting to module names
2016-06-10 14:19:02 +00:00
self . object_to_module = dict ( )
2016-06-09 22:50:03 +00:00
2016-06-28 15:34:28 +00:00
# Memory usage summary structure
self . mem_summary = dict ( )
2016-06-09 22:50:03 +00:00
def module_add ( self , module_name , size , section ) :
"""
Adds a module / section to the list
"""
if module_name in self . modules :
2016-06-10 14:19:02 +00:00
self . modules [ module_name ] [ section ] + = size
2016-06-09 22:50:03 +00:00
else :
temp_dic = dict ( )
2016-06-10 14:19:02 +00:00
for section_idx in self . all_sections :
temp_dic [ section_idx ] = 0
2016-06-09 22:50:03 +00:00
temp_dic [ section ] = size
self . modules [ module_name ] = temp_dic
2016-06-10 14:19:02 +00:00
def check_new_section_gcc ( self , line ) :
2016-06-09 22:50:03 +00:00
"""
Check whether a new section in a map file has been detected ( only applies to gcc )
"""
for i in self . all_sections :
if line . startswith ( i ) :
return i # should name of the section (assuming it's a known one)
if line . startswith ( ' . ' ) :
2016-06-28 15:34:28 +00:00
return ' unknown ' # all others are classified are unknown
2016-06-09 22:50:03 +00:00
else :
return False # everything else, means no change in section
2016-06-10 14:19:02 +00:00
def path_object_to_module_name ( self , txt ) :
2016-06-09 22:50:03 +00:00
"""
2016-06-10 14:19:02 +00:00
Parses path to object file and extracts module / object data
2016-06-09 22:50:03 +00:00
"""
2016-06-10 14:19:02 +00:00
txt = txt . replace ( ' \\ ' , ' / ' )
2016-06-09 22:50:03 +00:00
rex_mbed_os_name = r ' ^.+mbed-os \ /(.+) \ /(.+ \ .o)$ '
2016-06-10 14:19:02 +00:00
test_rex_mbed_os_name = re . match ( rex_mbed_os_name , txt )
2016-06-09 22:50:03 +00:00
if test_rex_mbed_os_name :
object_name = test_rex_mbed_os_name . group ( 2 )
data = test_rex_mbed_os_name . group ( 1 ) . split ( ' / ' )
ndata = len ( data )
if ndata == 1 :
module_name = data [ 0 ]
else :
module_name = data [ 0 ] + ' / ' + data [ 1 ]
return [ module_name , object_name ]
else :
return [ ' Misc ' , " " ]
2016-06-10 14:19:02 +00:00
def parse_section_gcc ( self , line ) :
2016-06-09 22:50:03 +00:00
"""
Parse data from a section of gcc map file
"""
# examples
# 0x00004308 0x7c ./.build/K64F/GCC_ARM/mbed-os/hal/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/spi_api.o
# .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
rex_address_len_name = r ' ^ \ s+.*0x( \ w { 8,16}) \ s+0x( \ w+) \ s(.+)$ '
2016-06-10 14:19:02 +00:00
test_address_len_name = re . match ( rex_address_len_name , line )
2016-06-09 22:50:03 +00:00
if test_address_len_name :
2016-06-10 14:19:02 +00:00
if int ( test_address_len_name . group ( 2 ) , 16 ) == 0 : # size == 0
return [ " " , 0 ] # no valid entry
2016-06-09 22:50:03 +00:00
else :
m_name , m_object = self . path_object_to_module_name ( test_address_len_name . group ( 3 ) )
2016-06-10 14:19:02 +00:00
m_size = int ( test_address_len_name . group ( 2 ) , 16 )
return [ m_name , m_size ]
2016-06-09 22:50:03 +00:00
2016-06-10 14:19:02 +00:00
else : # special corner case for *fill* sections
2016-06-09 22:50:03 +00:00
# example
# *fill* 0x0000abe4 0x4
rex_address_len = r ' ^ \ s+ \ *fill \ * \ s+0x( \ w { 8,16}) \ s+0x( \ w+).*$ '
2016-06-10 14:19:02 +00:00
test_address_len = re . match ( rex_address_len , line )
2016-06-09 22:50:03 +00:00
if test_address_len :
2016-06-10 14:19:02 +00:00
if int ( test_address_len . group ( 2 ) , 16 ) == 0 : # size == 0
return [ " " , 0 ] # no valid entry
2016-06-09 22:50:03 +00:00
else :
2016-06-10 14:19:02 +00:00
m_name = ' Fill '
m_size = int ( test_address_len . group ( 2 ) , 16 )
return [ m_name , m_size ]
2016-06-09 22:50:03 +00:00
else :
2016-06-10 14:19:02 +00:00
return [ " " , 0 ] # no valid entry
2016-06-09 22:50:03 +00:00
2016-06-10 14:19:02 +00:00
def parse_map_file_gcc ( self , file_desc ) :
2016-06-09 22:50:03 +00:00
"""
Main logic to decode gcc map files
"""
current_section = ' unknown '
2016-06-10 14:19:02 +00:00
with file_desc as infile :
2016-06-09 22:50:03 +00:00
# Search area to parse
for line in infile :
2016-06-10 14:19:02 +00:00
if line . startswith ( ' Linker script and memory map ' ) :
2016-06-09 22:50:03 +00:00
current_section = " unknown "
break
# Start decoding the map file
for line in infile :
change_section = self . check_new_section_gcc ( line )
if change_section == " OUTPUT " : # finish parsing file: exit
break
2016-06-10 14:19:02 +00:00
elif change_section != False :
2016-06-09 22:50:03 +00:00
current_section = change_section
[ module_name , module_size ] = self . parse_section_gcc ( line )
if module_size == 0 or module_name == " " :
pass
else :
self . module_add ( module_name , module_size , current_section )
if debug :
print " Line: %s " % line ,
2016-06-10 14:19:02 +00:00
print " Module: %s \t Section: %s \t Size: %s " % ( module_name , current_section , module_size )
2016-06-09 22:50:03 +00:00
raw_input ( " ---------- " )
2016-06-10 14:19:02 +00:00
def parse_section_armcc ( self , line ) :
2016-06-09 22:50:03 +00:00
"""
Parse data from an armcc map file
"""
# Examples of armcc map file:
# Base_Addr Size Type Attr Idx E Section Name Object
# 0x00000000 0x00000400 Data RO 11222 RESET startup_MK64F12.o
# 0x00000410 0x00000008 Code RO 49364 * !!!main c_w.l(__main.o)
rex_armcc = r ' ^ \ s+0x( \ w {8} ) \ s+0x( \ w {8} ) \ s+( \ w+) \ s+( \ w+) \ s+( \ d+) \ s+[*]?.+ \ s+(.+)$ '
2016-06-10 14:19:02 +00:00
test_rex_armcc = re . match ( rex_armcc , line )
2016-06-09 22:50:03 +00:00
if test_rex_armcc :
2016-06-10 14:19:02 +00:00
size = int ( test_rex_armcc . group ( 2 ) , 16 )
2016-06-09 22:50:03 +00:00
if test_rex_armcc . group ( 4 ) == ' RO ' :
section = ' .text '
else :
if test_rex_armcc . group ( 3 ) == ' Data ' :
section = ' .data '
elif test_rex_armcc . group ( 3 ) == ' Zero ' :
section = ' .bss '
else :
print " BUG armcc map parser "
raw_input ( )
# lookup object in dictionary and return module name
object_name = test_rex_armcc . group ( 6 )
if object_name in self . object_to_module :
module_name = self . object_to_module [ object_name ]
else :
module_name = ' Misc '
2016-06-10 14:19:02 +00:00
return [ module_name , size , section ]
2016-06-09 22:50:03 +00:00
else :
2016-06-10 14:19:02 +00:00
return [ " " , 0 , " " ] # no valid entry
2016-06-09 22:50:03 +00:00
2016-06-10 14:19:02 +00:00
def parse_section_iar ( self , line ) :
2016-06-09 22:50:03 +00:00
"""
Parse data from an IAR map file
"""
# Examples of IAR map file:
# Section Kind Address Size Object
# .intvec ro code 0x00000000 0x198 startup_MK64F12.o [15]
# .rodata const 0x00000198 0x0 zero_init3.o [133]
# .iar.init_table const 0x00008384 0x2c - Linker created -
# Initializer bytes const 0x00000198 0xb2 <for P3 s0>
# .data inited 0x20000000 0xd4 driverAtmelRFInterface.o [70]
# .bss zero 0x20000598 0x318 RTX_Conf_CM.o [4]
# .iar.dynexit uninit 0x20001448 0x204 <Block tail>
# HEAP uninit 0x20001650 0x10000 <Block tail>
rex_iar = r ' ^ \ s+(.+) \ s+(zero|const|ro code|inited|uninit) \ s+0x( \ w {8} ) \ s+0x( \ w+) \ s+(.+) \ s.+$ '
2016-06-10 14:19:02 +00:00
test_rex_iar = re . match ( rex_iar , line )
2016-06-09 22:50:03 +00:00
if test_rex_iar :
2016-06-10 14:19:02 +00:00
size = int ( test_rex_iar . group ( 4 ) , 16 )
2016-06-09 22:50:03 +00:00
if test_rex_iar . group ( 2 ) == ' const ' or test_rex_iar . group ( 2 ) == ' ro code ' :
section = ' .text '
elif test_rex_iar . group ( 2 ) == ' zero ' or test_rex_iar . group ( 2 ) == ' uninit ' :
if test_rex_iar . group ( 1 ) [ 0 : 4 ] == ' HEAP ' :
section = ' .heap '
elif test_rex_iar . group ( 1 ) [ 0 : 6 ] == ' CSTACK ' :
section = ' .stack '
else :
section = ' .bss ' # default section
elif test_rex_iar . group ( 2 ) == ' inited ' :
section = ' .data '
else :
print " BUG IAR map parser "
raw_input ( )
# lookup object in dictionary and return module name
object_name = test_rex_iar . group ( 5 )
if object_name in self . object_to_module :
module_name = self . object_to_module [ object_name ]
else :
module_name = ' Misc '
2016-06-10 14:19:02 +00:00
return [ module_name , size , section ]
2016-06-09 22:50:03 +00:00
else :
2016-06-10 14:19:02 +00:00
return [ " " , 0 , " " ] # no valid entry
2016-06-09 22:50:03 +00:00
2016-06-10 14:19:02 +00:00
def parse_map_file_armcc ( self , file_desc ) :
2016-06-09 22:50:03 +00:00
"""
Main logic to decode armcc map files
"""
2016-06-10 14:19:02 +00:00
with file_desc as infile :
2016-06-09 22:50:03 +00:00
# Search area to parse
for line in infile :
2016-06-10 14:19:02 +00:00
if line . startswith ( ' Base Addr Size ' ) :
2016-06-09 22:50:03 +00:00
break
# Start decoding the map file
for line in infile :
[ name , size , section ] = self . parse_section_armcc ( line )
if size == 0 or name == " " or section == " " :
pass
else :
self . module_add ( name , size , section )
2016-06-10 14:19:02 +00:00
def parse_map_file_iar ( self , file_desc ) :
2016-06-09 22:50:03 +00:00
"""
Main logic to decode armcc map files
"""
2016-06-10 14:19:02 +00:00
with file_desc as infile :
2016-06-09 22:50:03 +00:00
# Search area to parse
for line in infile :
2016-06-10 14:19:02 +00:00
if line . startswith ( ' Section ' ) :
2016-06-09 22:50:03 +00:00
break
# Start decoding the map file
for line in infile :
[ name , size , section ] = self . parse_section_iar ( line )
if size == 0 or name == " " or section == " " :
pass
else :
self . module_add ( name , size , section )
2016-06-10 14:19:02 +00:00
def search_objects ( self , path , toolchain ) :
2016-06-09 22:50:03 +00:00
"""
Check whether the specified map file matches with the toolchain .
Searches for object files and creates mapping : object - - > module
"""
2016-06-10 14:19:02 +00:00
path = path . replace ( ' \\ ' , ' / ' )
2016-06-09 22:50:03 +00:00
# check location of map file
rex = r ' ^(.+ \ /) ' + re . escape ( toolchain ) + r ' \ /(.+ \ .map)$ '
2016-06-10 14:19:02 +00:00
test_rex = re . match ( rex , path )
2016-06-09 22:50:03 +00:00
if test_rex :
search_path = test_rex . group ( 1 ) + toolchain + ' /mbed-os/ '
else :
2016-06-27 14:02:05 +00:00
# It looks this is not an mbed project
2016-06-09 22:50:03 +00:00
# object-to-module mapping cannot be generated
print " Warning: specified toolchain doesn ' t match with path to the memory map file. "
return
2016-06-10 14:19:02 +00:00
for root , dir , obj_files in os . walk ( search_path ) :
for obj_file in obj_files :
if obj_file . endswith ( " .o " ) :
module_name , object_name = self . path_object_to_module_name ( os . path . join ( root , obj_file ) )
2016-06-09 22:50:03 +00:00
if object_name in self . object_to_module :
2016-06-10 14:19:02 +00:00
if debug :
print " WARNING: multiple usages of object file: %s " % object_name
print " Current: %s " % self . object_to_module [ object_name ]
print " New: %s " % module_name
print " "
2016-06-09 22:50:03 +00:00
else :
self . object_to_module . update ( { object_name : module_name } )
2016-06-24 22:15:01 +00:00
export_formats = [ " json " , " csv-ci " , " table " ]
2016-06-10 14:19:02 +00:00
def generate_output ( self , export_format , file_output = None ) :
"""
Generates summary of memory map data
Parameters
json_mode : generates output in json formal ( True / False )
file_desc : descriptor ( either stdout or file )
"""
try :
if file_output :
file_desc = open ( file_output , ' wb ' )
else :
file_desc = sys . stdout
except IOError as error :
print " I/O error( {0} ): {1} " . format ( error . errno , error . strerror )
return False
# Calculate misc flash sections
misc_flash_mem = 0
for i in self . modules :
for k in self . misc_flash_sections :
if self . modules [ i ] [ k ] :
misc_flash_mem + = self . modules [ i ] [ k ]
# Create table
columns = [ ' Module ' ]
2016-06-28 15:34:28 +00:00
columns . extend ( self . print_sections )
2016-06-10 14:19:02 +00:00
table = PrettyTable ( columns )
table . align [ " Module " ] = " l "
2016-06-28 15:34:28 +00:00
for col in self . print_sections :
table . align [ col ] = ' r '
2016-06-10 14:19:02 +00:00
2016-06-27 10:44:01 +00:00
for i in list ( self . print_sections ) :
table . align [ i ] = ' r '
2016-06-10 14:19:02 +00:00
subtotal = dict ( )
for k in self . sections :
subtotal [ k ] = 0
json_obj = [ ]
for i in sorted ( self . modules ) :
row = [ ]
row . append ( i )
for k in self . sections :
subtotal [ k ] + = self . modules [ i ] [ k ]
for k in self . print_sections :
row . append ( self . modules [ i ] [ k ] )
2016-06-28 15:34:28 +00:00
json_obj . append ( {
" module " : i ,
" size " : {
k : self . modules [ i ] [ k ] for k in self . print_sections
}
} )
2016-06-10 14:19:02 +00:00
table . add_row ( row )
subtotal_row = [ ' Subtotals ' ]
for k in self . print_sections :
subtotal_row . append ( subtotal [ k ] )
table . add_row ( subtotal_row )
2016-06-28 15:34:28 +00:00
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 ) ,
}
}
2016-06-10 14:19:02 +00:00
if export_format == ' json ' :
2016-06-28 15:34:28 +00:00
json_to_file = json_obj + [ summary ]
file_desc . write ( json . dumps ( json_to_file , indent = 4 ) )
2016-06-10 14:19:02 +00:00
file_desc . write ( ' \n ' )
elif export_format == ' csv-ci ' : # CSV format for the CI system
csv_writer = csv . writer ( file_desc , delimiter = ' , ' , quoting = csv . QUOTE_NONE )
csv_module_section = [ ]
csv_sizes = [ ]
for i in sorted ( self . modules ) :
for k in self . print_sections :
csv_module_section + = [ i + k ]
csv_sizes + = [ self . modules [ i ] [ k ] ]
2016-06-27 10:44:01 +00:00
csv_module_section + = [ ' total_static_ram ' ]
2016-06-10 14:19:02 +00:00
csv_sizes + = [ subtotal [ ' .data ' ] + subtotal [ ' .bss ' ] ]
2016-06-27 12:31:56 +00:00
csv_module_section + = [ ' allocated_heap ' ]
if subtotal [ ' .heap ' ] == 0 :
csv_sizes + = [ ' unknown ' ]
else :
csv_sizes + = [ subtotal [ ' .heap ' ] ]
csv_module_section + = [ ' allocated_stack ' ]
if subtotal [ ' .stack ' ] == 0 :
csv_sizes + = [ ' unknown ' ]
else :
csv_sizes + = [ subtotal [ ' .stack ' ] ]
csv_module_section + = [ ' total_ram ' ]
csv_sizes + = [ subtotal [ ' .data ' ] + subtotal [ ' .bss ' ] + subtotal [ ' .heap ' ] + subtotal [ ' .stack ' ] ]
2016-06-10 14:19:02 +00:00
csv_module_section + = [ ' total_flash ' ]
csv_sizes + = [ subtotal [ ' .text ' ] + subtotal [ ' .data ' ] + misc_flash_mem ]
csv_writer . writerow ( csv_module_section )
csv_writer . writerow ( csv_sizes )
else : # default format is 'table'
file_desc . write ( table . get_string ( ) )
file_desc . write ( ' \n ' )
2016-06-27 12:31:56 +00:00
if subtotal [ ' .heap ' ] == 0 :
file_desc . write ( " Allocated Heap: unknown \n " )
else :
file_desc . write ( " Allocated Heap: %s bytes \n " % str ( subtotal [ ' .heap ' ] ) )
2016-06-27 14:02:05 +00:00
2016-06-27 12:31:56 +00:00
if subtotal [ ' .stack ' ] == 0 :
file_desc . write ( " Allocated Stack: unknown \n " )
else :
file_desc . write ( " Allocated Stack: %s bytes \n " % str ( subtotal [ ' .stack ' ] ) )
2016-06-27 10:44:01 +00:00
file_desc . write ( " Total Static RAM memory (data + bss): %s bytes \n " % ( str ( subtotal [ ' .data ' ] + subtotal [ ' .bss ' ] ) ) )
2016-06-27 12:31:56 +00:00
file_desc . write ( " Total RAM memory (data + bss + heap + stack): %s bytes \n " % ( str ( subtotal [ ' .data ' ] + subtotal [ ' .bss ' ] + subtotal [ ' .heap ' ] + subtotal [ ' .stack ' ] ) ) )
2016-06-27 10:44:01 +00:00
file_desc . write ( " Total Flash memory (text + data + misc): %s bytes \n " % ( str ( subtotal [ ' .text ' ] + subtotal [ ' .data ' ] + misc_flash_mem ) ) )
2016-06-10 14:19:02 +00:00
if file_desc is not sys . stdout :
file_desc . close ( )
2016-06-28 15:34:28 +00:00
self . mem_summary = json_obj + [ summary ]
2016-06-10 14:19:02 +00:00
return True
2016-06-28 15:34:28 +00:00
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
2016-06-24 22:15:01 +00:00
toolchains = [ " ARM " , " ARM_STD " , " ARM_MICRO " , " GCC_ARM " , " IAR " ]
2016-06-10 14:19:02 +00:00
def parse ( self , mapfile , toolchain ) :
"""
Parse and decode map file depending on the toolchain
"""
2016-06-28 15:34:28 +00:00
result = True
2016-06-10 14:19:02 +00:00
try :
2016-06-28 15:34:28 +00:00
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
2016-06-10 14:19:02 +00:00
except IOError as error :
print " I/O error( {0} ): {1} " . format ( error . errno , error . strerror )
2016-06-28 15:34:28 +00:00
result = False
return result
2016-06-10 14:19:02 +00:00
2016-06-09 22:50:03 +00:00
def main ( ) :
2016-06-27 10:44:01 +00:00
version = ' 0.3.11 '
2016-06-09 22:50:03 +00:00
# Parser handling
2016-06-27 14:02:05 +00:00
parser = argparse . ArgumentParser ( description = " Memory Map File Analyser for ARM mbed \n version %s " % version )
2016-06-09 22:50:03 +00:00
2016-06-30 21:49:02 +00:00
parser . add_argument ( ' file ' , type = argparse_filestring_type , help = ' memory map file ' )
2016-06-09 22:50:03 +00:00
2016-06-24 22:15:01 +00:00
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 " ) )
2016-06-09 22:50:03 +00:00
2016-06-10 14:19:02 +00:00
parser . add_argument ( ' -o ' , ' --output ' , help = ' output file name ' , required = False )
2016-06-09 22:50:03 +00:00
2016-06-24 22:15:01 +00:00
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 ) )
2016-06-09 22:50:03 +00:00
parser . add_argument ( ' -v ' , ' --version ' , action = ' version ' , version = version )
# Parse/run command
if len ( sys . argv ) < = 1 :
parser . print_help ( )
sys . exit ( 1 )
2016-06-10 14:19:02 +00:00
2016-06-09 22:50:03 +00:00
args , remainder = parser . parse_known_args ( )
2016-06-10 14:19:02 +00:00
# Create memap object
memap = MemapParser ( )
# Parse and decode a map file
if args . file and args . toolchain :
if memap . parse ( args . file , args . toolchain ) is False :
sys . exit ( 0 )
2016-06-09 22:50:03 +00:00
# Write output in file
if args . output != None :
2016-06-10 14:19:02 +00:00
memap . generate_output ( args . export , args . output )
2016-06-09 22:50:03 +00:00
else : # Write output in screen
2016-06-10 14:19:02 +00:00
memap . generate_output ( args . export )
2016-06-09 22:50:03 +00:00
sys . exit ( 0 )
if __name__ == " __main__ " :
2016-06-10 14:19:02 +00:00
main ( )