20
20
RE_IAR = re .compile (
21
21
r'^\s+(.+)\s+(zero|const|ro code|inited|uninit)\s'
22
22
r'+0x(\w{8})\s+0x(\w+)\s+(.+)\s.+$' )
23
+ RE_LIB_MATCH = re .compile ("^.*/(.*\.a)\((.*)\)$" )
23
24
24
25
class MemapParser (object ):
25
26
"""An object that represents parsed results, parses the memory map files,
@@ -37,13 +38,16 @@ class MemapParser(object):
37
38
38
39
# sections to print info (generic for all toolchains)
39
40
sections = ('.text' , '.data' , '.bss' , '.heap' , '.stack' )
41
+ MAXDEPTH = object ()
40
42
41
- def __init__ (self , detailed_misc = False ):
43
+ def __init__ (self , depth = 2 ):
42
44
""" General initialization
43
45
"""
44
- #
45
- self .detailed_misc = detailed_misc
46
-
46
+
47
+ self .depth = depth
48
+
49
+ self .mapfile = None
50
+
47
51
# list of all modules and their sections
48
52
self .modules = dict ()
49
53
@@ -98,7 +102,7 @@ def check_new_section_gcc(self, line):
98
102
else :
99
103
return False # everything else, means no change in section
100
104
101
-
105
+
102
106
def path_object_to_module_name (self , txt ):
103
107
""" Parse a path to object file to extract it's module and object data
104
108
@@ -107,32 +111,25 @@ def path_object_to_module_name(self, txt):
107
111
"""
108
112
109
113
txt = txt .replace ('\\ ' , '/' )
110
- rex_mbed_os_name = r'^.+mbed-os\/(.+)\/(.+\.o)$'
111
- test_rex_mbed_os_name = re .match (rex_mbed_os_name , txt )
112
-
113
- if test_rex_mbed_os_name :
114
-
115
- object_name = test_rex_mbed_os_name .group (2 )
116
- data = test_rex_mbed_os_name .group (1 ).split ('/' )
117
- ndata = len (data )
118
-
119
- if ndata == 1 :
120
- module_name = data [0 ]
114
+ name = txt .split ('/' )
115
+ mapfile_beginning = os .path .dirname (self .mapfile ).split ('/' )
116
+ if name [0 ] == "." or name [0 ] == "" :
117
+ name = name [1 :]
118
+ for thing in mapfile_beginning :
119
+ if name [0 ] == thing :
120
+ name = name [1 :]
121
+ elif name [0 ] in mapfile_beginning :
122
+ pass
121
123
else :
122
- module_name = data [0 ] + '/' + data [1 ]
123
-
124
- return [module_name , object_name ]
125
-
126
- elif self .detailed_misc :
127
- rex_obj_name = r'^.+\/(.+\.o\)*)$'
128
- test_rex_obj_name = re .match (rex_obj_name , txt )
129
- if test_rex_obj_name :
130
- object_name = test_rex_obj_name .group (1 )
131
- return ['Misc/' + object_name , "" ]
132
-
133
- return ['Misc' , "" ]
134
- else :
135
- return ['Misc' , "" ]
124
+ break
125
+ if name [0 ] == "mbed-os" :
126
+ name = name [1 :]
127
+ if name [0 ] == "features" :
128
+ name = name [1 :]
129
+ is_lib = RE_LIB_MATCH .match (txt )
130
+ if is_lib :
131
+ name = ["libraries" , is_lib .group (1 ), is_lib .group (2 )]
132
+ return "/" .join (name ), name [- 1 ]
136
133
137
134
def parse_section_gcc (self , line ):
138
135
""" Parse data from a section of gcc map file
@@ -367,15 +364,7 @@ def search_objects(self, path):
367
364
368
365
path = path .replace ('\\ ' , '/' )
369
366
370
- # check location of map file
371
- rex = r'^(.+)' + r'\/(.+\.map)$'
372
- test_rex = re .match (rex , path )
373
-
374
- if test_rex :
375
- search_path = test_rex .group (1 ) + '/mbed-os/'
376
- else :
377
- print "Warning: this doesn't look like an mbed project"
378
- return
367
+ search_path = os .path .dirname (path )
379
368
380
369
for root , _ , obj_files in os .walk (search_path ):
381
370
for obj_file in obj_files :
@@ -490,11 +479,19 @@ def generate_table(self, file_desc):
490
479
for i in list (self .print_sections ):
491
480
table .align [i ] = 'r'
492
481
482
+ local_modules = {}
493
483
for i in sorted (self .modules ):
484
+ module_name = "/" .join (i .split ("/" )[:self .depth ])
485
+ local_modules .setdefault (module_name ,
486
+ {k : 0 for k in self .print_sections })
487
+ for k in self .print_sections :
488
+ local_modules [module_name ][k ] += self .modules [i ][k ]
489
+
490
+ for i in sorted (local_modules .keys ()):
494
491
row = [i ]
495
492
496
493
for k in self .print_sections :
497
- row .append (self . modules [i ][k ])
494
+ row .append (local_modules [i ][k ])
498
495
499
496
table .add_row (row )
500
497
@@ -575,6 +572,8 @@ def parse(self, mapfile, toolchain):
575
572
toolchain - the toolchain used to create the file
576
573
"""
577
574
575
+ self .mapfile = mapfile
576
+
578
577
result = True
579
578
try :
580
579
with open (mapfile , 'r' ) as file_input :
@@ -589,9 +588,8 @@ def parse(self, mapfile, toolchain):
589
588
self .parse_map_file_iar (file_input )
590
589
else :
591
590
result = False
592
-
593
591
self .compute_report ()
594
-
592
+
595
593
except IOError as error :
596
594
print "I/O error({0}): {1}" .format (error .errno , error .strerror )
597
595
result = False
@@ -631,6 +629,7 @@ def main():
631
629
632
630
parser .add_argument ('-d' , '--detailed' , action = 'store_true' , help = 'Displays the elements in "Misc" in a detailed fashion' , required = False )
633
631
632
+ parser .add_argument ('--max-depth' , dest = 'max_depth' , type = int , help = 'Displays the elements in "Misc" in a detailed fashion' , required = False , default = None )
634
633
# Parse/run command
635
634
if len (sys .argv ) <= 1 :
636
635
parser .print_help ()
@@ -640,7 +639,7 @@ def main():
640
639
args = parser .parse_args ()
641
640
642
641
# Create memap object
643
- memap = MemapParser (detailed_misc = args .detailed )
642
+ memap = MemapParser (depth = ( args .max_depth or ( MemapParser . MAXDEPTH if args . detailed else 2 )) )
644
643
645
644
# Parse and decode a map file
646
645
if args .file and args .toolchain :
0 commit comments