Merge pull request #5178 from ARMmbed/release-candidate

Release candidate for mbed-os-5.6.0-rc3
pull/5394/head mbed-os-5.6.0
Jimmy Brisson 2017-09-23 08:10:56 -05:00 committed by GitHub
commit 5499db1e81
9 changed files with 349 additions and 240 deletions

View File

@ -20,6 +20,18 @@ RE_IAR = re.compile(
r'^\s+(.+)\s+(zero|const|ro code|inited|uninit)\s' r'^\s+(.+)\s+(zero|const|ro code|inited|uninit)\s'
r'+0x(\w{8})\s+0x(\w+)\s+(.+)\s.+$') r'+0x(\w{8})\s+0x(\w+)\s+(.+)\s.+$')
RE_CMDLINE_FILE_IAR = re.compile(r'^#\s+(.+\.o)')
RE_LIBRARY_IAR = re.compile(r'^(.+\.a)\:.+$')
RE_OBJECT_LIBRARY_IAR = re.compile(r'^\s+(.+\.o)\s.*')
RE_OBJECT_FILE_GCC = re.compile(r'^(.+\/.+\.o)$')
RE_LIBRARY_OBJECT_GCC = re.compile(r'^.+\/lib(.+\.a)\((.+\.o)\)$')
RE_STD_SECTION_GCC = re.compile(r'^\s+.*0x(\w{8,16})\s+0x(\w+)\s(.+)$')
RE_FILL_SECTION_GCC = re.compile(r'^\s*\*fill\*\s+0x(\w{8,16})\s+0x(\w+).*$')
RE_OBJECT_ARMCC = re.compile(r'(.+\.(l|ar))\((.+\.o)\)')
class MemapParser(object): class MemapParser(object):
"""An object that represents parsed results, parses the memory map files, """An object that represents parsed results, parses the memory map files,
and writes out different file types of memory results and writes out different file types of memory results
@ -59,31 +71,10 @@ class MemapParser(object):
self.misc_flash_mem = 0 self.misc_flash_mem = 0
# Modules passed to the linker on the command line
# this is a dict because modules are looked up by their basename
self.cmd_modules = {}
def remove_unused_modules(self):
""" Removes modules/objects that were compiled but are not used
"""
# Using keys to be able to remove entry
for i in self.modules.keys():
size = 0
for k in self.print_sections:
size += self.modules[i][k]
if size == 0:
del self.modules[i]
def module_init(self, object_name):
""" Initialize a module. Just adds the name of the module
Positional arguments:
object_name - name of the entry to add
"""
if object_name not in self.modules:
temp_dic = dict()
for section_idx in self.all_sections:
temp_dic[section_idx] = 0
self.modules[object_name] = temp_dic
def module_add(self, object_name, size, section): def module_add(self, object_name, size, section):
""" Adds a module / section to the list """ Adds a module / section to the list
@ -94,28 +85,27 @@ class MemapParser(object):
section - the section the module contributes to section - the section the module contributes to
""" """
# Check if object is a sub-string of key if not object_name or not size or not section:
for module_path in self.modules: return
# this is required to differenciate: main.o vs xxxmain.o if object_name in self.modules:
module_split = os.path.basename(module_path) self.modules[object_name].setdefault(section, 0)
obj_split = os.path.basename(object_name) self.modules[object_name][section] += size
return
if module_split == obj_split: obj_split = os.sep + os.path.basename(object_name)
self.modules[module_path][section] += size for module_path, contents in self.modules.items():
if module_path.endswith(obj_split) or module_path == object_name:
contents.setdefault(section, 0)
contents[section] += size
return return
new_module = dict() new_module = {section: size}
for section_idx in self.all_sections:
new_module[section_idx] = 0
new_module[section] = size
self.modules[object_name] = new_module self.modules[object_name] = new_module
def module_replace(self, old_object, new_object): def module_replace(self, old_object, new_object):
""" Replaces an object name with a new one """ Replaces an object name with a new one
""" """
# Check if object is a sub-string of key
if old_object in self.modules: if old_object in self.modules:
self.modules[new_object] = self.modules[old_object] self.modules[new_object] = self.modules[old_object]
del self.modules[old_object] del self.modules[old_object]
@ -147,8 +137,7 @@ class MemapParser(object):
""" """
line = line.replace('\\', '/') line = line.replace('\\', '/')
RE_OBJECT_FILE = r'^.+\/(.+\.o)$' test_re_mbed_os_name = re.match(RE_OBJECT_FILE_GCC, line)
test_re_mbed_os_name = re.match(RE_OBJECT_FILE, line)
if test_re_mbed_os_name: if test_re_mbed_os_name:
@ -156,14 +145,12 @@ class MemapParser(object):
# corner case: certain objects are provided by the GCC toolchain # corner case: certain objects are provided by the GCC toolchain
if 'arm-none-eabi' in line: if 'arm-none-eabi' in line:
object_name = '[lib]/misc/' + object_name return '[lib]/misc/' + object_name
return object_name return object_name
else: else:
RE_LIBRARY_OBJECT_FILE = r'^.+\/(lib.+\.a)\((.+\.o)\)$' test_re_obj_name = re.match(RE_LIBRARY_OBJECT_GCC, line)
test_re_obj_name = re.match(RE_LIBRARY_OBJECT_FILE, line)
if test_re_obj_name: if test_re_obj_name:
object_name = test_re_obj_name.group(1) + '/' + \ object_name = test_re_obj_name.group(1) + '/' + \
@ -172,7 +159,7 @@ class MemapParser(object):
return '[lib]/' + object_name return '[lib]/' + object_name
else: else:
print "Malformed input found when parsing GCC map: %s" % line print "Unknown object name found in GCC map file: %s" % line
return '[misc]' return '[misc]'
def parse_section_gcc(self, line): def parse_section_gcc(self, line):
@ -186,40 +173,20 @@ class MemapParser(object):
line - the line to parse a section from line - the line to parse a section from
""" """
RE_STD_SECTION_GCC = re.compile( is_fill = re.match(RE_FILL_SECTION_GCC, line)
r'^\s+.*0x(\w{8,16})\s+0x(\w+)\s(.+)$') if is_fill:
o_name = '[fill]'
test_address_len_name = re.match(RE_STD_SECTION_GCC, line) o_size = int(is_fill.group(2), 16)
return [o_name, o_size]
if test_address_len_name:
if int(test_address_len_name.group(2), 16) == 0: # size == 0
return ["", 0] # no valid entry
else:
o_name = self.parse_object_name_gcc(\
test_address_len_name.group(3))
o_size = int(test_address_len_name.group(2), 16)
is_section = re.match(RE_STD_SECTION_GCC, line)
if is_section:
o_size = int(is_section.group(2), 16)
if o_size:
o_name = self.parse_object_name_gcc(is_section.group(3))
return [o_name, o_size] return [o_name, o_size]
else: # special corner case for *fill* sections return ["", 0]
# example
# *fill* 0x0000abe4 0x4
RE_FILL_SECTION_GCC = r'^\s+\*fill\*\s+0x(\w{8,16})\s+0x(\w+).*$'
test_address_len = re.match(RE_FILL_SECTION_GCC, line)
if test_address_len:
if int(test_address_len.group(2), 16) == 0: # size == 0
return ["", 0] # no valid entry
else:
o_name = '[fill]'
o_size = int(test_address_len.group(2), 16)
return [o_name, o_size]
else:
return ["", 0] # no valid entry
def parse_map_file_gcc(self, file_desc): def parse_map_file_gcc(self, file_desc):
""" Main logic to decode gcc map files """ Main logic to decode gcc map files
@ -231,30 +198,34 @@ class MemapParser(object):
current_section = 'unknown' current_section = 'unknown'
with file_desc as infile: with file_desc as infile:
# Search area to parse
for line in infile: for line in infile:
if line.startswith('Linker script and memory map'): if line.startswith('Linker script and memory map'):
current_section = "unknown" current_section = "unknown"
break break
# Start decoding the map file
for line in infile: for line in infile:
next_section = self.check_new_section_gcc(line)
change_section = self.check_new_section_gcc(line) if next_section == "OUTPUT":
if change_section == "OUTPUT": # finish parsing file: exit
break break
elif change_section != False: elif next_section:
current_section = change_section current_section = next_section
[object_name, object_size] = self.parse_section_gcc(line) object_name, object_size = self.parse_section_gcc(line)
if object_size == 0 or object_name == "": self.module_add(object_name, object_size, current_section)
pass
else: common_prefix = os.path.dirname(os.path.commonprefix([
self.module_add(object_name, object_size,\ o for o in self.modules.keys() if (o.endswith(".o") and not o.startswith("[lib]"))]))
current_section) new_modules = {}
for name, stats in self.modules.items():
if name.startswith("[lib]"):
new_modules[name] = stats
elif name.endswith(".o"):
new_modules[os.path.relpath(name, common_prefix)] = stats
else:
new_modules[name] = stats
self.modules = new_modules
def parse_object_name_armcc(self, line): def parse_object_name_armcc(self, line):
""" Parse object file """ Parse object file
@ -268,14 +239,9 @@ class MemapParser(object):
return line return line
else: else:
is_obj = re.match(RE_OBJECT_ARMCC, line)
RE_OBJECT_ARMCC = r'(.+\.(l|ar))\((.+\.o)\)' if is_obj:
test_re_obj_name = re.match(RE_OBJECT_ARMCC, line) object_name = os.path.basename(is_obj.group(1)) + '/' + is_obj.group(3)
if test_re_obj_name:
object_name = test_re_obj_name.group(1) + '/' + \
test_re_obj_name.group(2)
return '[lib]/' + object_name return '[lib]/' + object_name
else: else:
print "Malformed input found when parsing ARMCC map: %s" % line print "Malformed input found when parsing ARMCC map: %s" % line
@ -321,7 +287,7 @@ class MemapParser(object):
else: else:
return ["", 0, ""] return ["", 0, ""]
def parse_object_name_iar(self, line): def parse_object_name_iar(self, object_name):
""" Parse object file """ Parse object file
Positional arguments: Positional arguments:
@ -329,10 +295,11 @@ class MemapParser(object):
""" """
# simple object (not library) # simple object (not library)
if line[-2] == '.' and line[-1] == 'o': if object_name.endswith(".o"):
object_name = line try:
return object_name return self.cmd_modules[object_name]
except KeyError:
return object_name
else: else:
return '[misc]' return '[misc]'
@ -361,11 +328,11 @@ class MemapParser(object):
size = int(test_re_iar.group(4), 16) size = int(test_re_iar.group(4), 16)
if test_re_iar.group(2) == 'const' or \ if (test_re_iar.group(2) == 'const' or
test_re_iar.group(2) == 'ro code': test_re_iar.group(2) == 'ro code'):
section = '.text' section = '.text'
elif test_re_iar.group(2) == 'zero' or \ elif (test_re_iar.group(2) == 'zero' or
test_re_iar.group(2) == 'uninit': test_re_iar.group(2) == 'uninit'):
if test_re_iar.group(1)[0:4] == 'HEAP': if test_re_iar.group(1)[0:4] == 'HEAP':
section = '.heap' section = '.heap'
elif test_re_iar.group(1)[0:6] == 'CSTACK': elif test_re_iar.group(1)[0:6] == 'CSTACK':
@ -379,8 +346,7 @@ class MemapParser(object):
print "Malformed input found when parsing IAR map: %s" % line print "Malformed input found when parsing IAR map: %s" % line
# lookup object in dictionary and return module name # lookup object in dictionary and return module name
temp = test_re_iar.group(5) object_name = self.parse_object_name_iar(test_re_iar.group(5))
object_name = self.parse_object_name_iar(temp)
return [object_name, size, section] return [object_name, size, section]
@ -403,14 +369,20 @@ class MemapParser(object):
# Start decoding the map file # Start decoding the map file
for line in infile: for line in infile:
self.module_add(*self.parse_section_armcc(line))
[object_name, object_size, section] = \ common_prefix = os.path.dirname(os.path.commonprefix([
self.parse_section_armcc(line) o for o in self.modules.keys() if (o.endswith(".o") and o != "anon$$obj.o" and not o.startswith("[lib]"))]))
new_modules = {}
for name, stats in self.modules.items():
if name == "anon$$obj.o" or name.startswith("[lib]"):
new_modules[name] = stats
elif name.endswith(".o"):
new_modules[os.path.relpath(name, common_prefix)] = stats
else:
new_modules[name] = stats
self.modules = new_modules
if object_size == 0 or object_name == "" or section == "":
pass
else:
self.module_add(object_name, object_size, section)
def check_new_library_iar(self, line): def check_new_library_iar(self, line):
@ -420,7 +392,6 @@ class MemapParser(object):
""" """
RE_LIBRARY_IAR = re.compile(r'^(.+\.a)\:.+$')
test_address_line = re.match(RE_LIBRARY_IAR, line) test_address_line = re.match(RE_LIBRARY_IAR, line)
@ -441,8 +412,6 @@ class MemapParser(object):
""" """
RE_OBJECT_LIBRARY_IAR = re.compile(r'^\s+(.+\.o)\s.*')
test_address_line = re.match(RE_OBJECT_LIBRARY_IAR, line) test_address_line = re.match(RE_OBJECT_LIBRARY_IAR, line)
if test_address_line: if test_address_line:
@ -450,6 +419,25 @@ class MemapParser(object):
else: else:
return "" return ""
def parse_iar_command_line(self, lines):
"""Parse the files passed on the command line to the iar linker
Positional arguments:
lines -- an iterator over the lines within a file
"""
for line in lines:
if line.startswith("*"):
break
is_cmdline_file = RE_CMDLINE_FILE_IAR.match(line)
if is_cmdline_file:
full_path = is_cmdline_file.group(1)
self.cmd_modules[os.path.basename(full_path)] = full_path
common_prefix = os.path.dirname(os.path.commonprefix(self.cmd_modules.values()))
self.cmd_modules = {s: os.path.relpath(f, common_prefix)
for s, f in self.cmd_modules.items()}
def parse_map_file_iar(self, file_desc): def parse_map_file_iar(self, file_desc):
""" Main logic to decode IAR map files """ Main logic to decode IAR map files
@ -457,106 +445,38 @@ class MemapParser(object):
file_desc - a file like object to parse as an IAR map file file_desc - a file like object to parse as an IAR map file
""" """
# first round, search for objects
with file_desc as infile: with file_desc as infile:
# Search area to parse self.parse_iar_command_line(infile)
for line in infile: for line in infile:
if line.startswith(' Section '): if line.startswith(' Section '):
break break
# Start decoding the map file
for line in infile: for line in infile:
self.module_add(*self.parse_section_iar(line))
[name, size, section] = self.parse_section_iar(line)
if size == 0 or name == "" or section == "":
pass
else:
self.module_add(name, size, section)
if line.startswith('*** MODULE SUMMARY'): # finish section if line.startswith('*** MODULE SUMMARY'): # finish section
break break
# Start decoding the map file
current_library = "" current_library = ""
for line in infile: for line in infile:
library = self.check_new_library_iar(line) library = self.check_new_library_iar(line)
if library != "": if library:
current_library = library current_library = library
object_name = self.check_new_object_lib_iar(line) object_name = self.check_new_object_lib_iar(line)
if object_name != "" and current_library != "": if object_name and current_library:
print("Replacing module", object_name, current_library)
temp = '[lib]' + '/'+ current_library + '/'+ object_name temp = '[lib]' + '/'+ current_library + '/'+ object_name
self.module_replace(object_name, temp) self.module_replace(object_name, temp)
export_formats = ["json", "csv-ci", "table"]
def list_dir_obj(self, path):
""" Searches all objects in BUILD directory and creates list
Positional arguments:
path - the path to a map file
"""
path = path.replace('\\', '/')
# check location of map file
RE_PATH_MAP_FILE = r'^(.+)\/.+\.map$'
test_re = re.match(RE_PATH_MAP_FILE, path)
if test_re:
search_path = test_re.group(1)
else:
print "Warning: this doesn't look like an mbed project"
return
# create empty disctionary
self.modules = dict()
# search for object files
for root, _, obj_files in os.walk(search_path):
for obj_file in obj_files:
if obj_file.endswith(".o"):
txt = os.path.join(root, obj_file)
txt = txt.replace('\\', '/')
# add relative path + object to list
self.module_init(txt[len(search_path)+1:])
# The code below is a special case for TESTS.
# mbed-os lives in a separate location and we need to explicitly search
# their object files skiping the TESTS folder (already scanned above)
# check location of mbed-os
RE_PATH_MAP_FILE = r'^(.+)\/mbed-os\/.*TESTS\/.+\.map$'
test_re = re.match(RE_PATH_MAP_FILE, path)
if test_re == None:
return
search_path = test_re.group(1)
# search for object files
for root, _, obj_files in os.walk(search_path):
for obj_file in obj_files:
if 'TESTS' not in root and obj_file.endswith(".o"):
txt = os.path.join(root, obj_file)
txt = txt.replace('\\', '/')
# add relative path + object to list
self.module_init(txt[len(search_path)+1:])
def reduce_depth(self, depth): def reduce_depth(self, depth):
""" """
prints list of directories and objects. Examples: populates the short_modules attribute with a truncated module list
(1) depth = 1: (1) depth = 1:
main.o main.o
@ -568,43 +488,19 @@ class MemapParser(object):
mbed-os/drivers mbed-os/drivers
""" """
# depth 0 or None shows all entries
if depth == 0 or depth == None: if depth == 0 or depth == None:
self.short_modules = deepcopy(self.modules) self.short_modules = deepcopy(self.modules)
return else:
self.short_modules = dict()
self.short_modules = dict() for module_name, v in self.modules.items():
split_name = module_name.split('/')
# create reduced list if split_name[0] == '':
for line in self.modules: split_name = split_name[1:]
new_name = "/".join(split_name[:depth])
data = line.split('/') self.short_modules.setdefault(new_name, {})
ndir = len(data) for section_idx, value in v.items():
self.short_modules[new_name].setdefault(section_idx, 0)
temp = '' self.short_modules[new_name][section_idx] += self.modules[module_name][section_idx]
count = 0
# iterate until the max depth level
max_level = min(depth, ndir)
# rebuild the path based on depth level
while count < max_level:
if count > 0: # ignore '/' from first entry
temp = temp + '/'
temp = temp + data[count]
count += 1
if temp not in self.short_modules:
temp_dic = dict()
for section_idx in self.all_sections:
temp_dic[section_idx] = 0
self.short_modules[temp] = temp_dic
for section_idx in self.all_sections:
self.short_modules[temp][section_idx] += \
self.modules[line][section_idx]
export_formats = ["json", "csv-ci", "table"] export_formats = ["json", "csv-ci", "table"]
@ -728,12 +624,12 @@ class MemapParser(object):
def compute_report(self): def compute_report(self):
""" Generates summary of memory usage for main areas """ Generates summary of memory usage for main areas
""" """
for k in self.sections: for k in self.sections:
self.subtotal[k] = 0 self.subtotal[k] = 0
for i in sorted(self.short_modules): for i in self.short_modules:
for k in self.sections: for k in self.sections:
self.short_modules[i].setdefault(k, 0)
self.subtotal[k] += self.short_modules[i][k] self.subtotal[k] += self.short_modules[i][k]
self.mem_summary = { self.mem_summary = {
@ -746,7 +642,7 @@ class MemapParser(object):
self.mem_report.append({ self.mem_report.append({
"module":i, "module":i,
"size":{ "size":{
k:self.short_modules[i][k] for k in self.print_sections k: self.short_modules[i][k] for k in self.print_sections
} }
}) })
@ -765,10 +661,6 @@ class MemapParser(object):
result = True result = True
try: try:
with open(mapfile, 'r') as file_input: with open(mapfile, 'r') as file_input:
# Common to all toolchains: first search for objects in BUILD
self.list_dir_obj(os.path.abspath(mapfile))
if toolchain in ("ARM", "ARM_STD", "ARM_MICRO", "ARMC6"): if toolchain in ("ARM", "ARM_STD", "ARM_MICRO", "ARMC6"):
self.parse_map_file_armcc(file_input) self.parse_map_file_armcc(file_input)
elif toolchain == "GCC_ARM" or toolchain == "GCC_CR": elif toolchain == "GCC_ARM" or toolchain == "GCC_CR":
@ -778,8 +670,6 @@ class MemapParser(object):
else: else:
result = False result = False
self.remove_unused_modules()
except IOError as error: except IOError as error:
print "I/O error({0}): {1}".format(error.errno, error.strerror) print "I/O error({0}): {1}".format(error.errno, error.strerror)
result = False result = False

View File

@ -34,7 +34,7 @@
"asm": [], "asm": [],
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
"cxx": ["--cpp", "--no_rtti", "--no_vla"], "cxx": ["--cpp", "--no_rtti", "--no_vla"],
"ld": [] "ld": ["--show_full_path"]
}, },
"uARM": { "uARM": {
"common": ["-c", "--gnu", "-Otime", "--split_sections", "common": ["-c", "--gnu", "-Otime", "--split_sections",

View File

@ -31,7 +31,7 @@
"asm": [], "asm": [],
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
"cxx": ["--cpp", "--no_rtti", "--no_vla"], "cxx": ["--cpp", "--no_rtti", "--no_vla"],
"ld": [] "ld": ["--show_full_path"]
}, },
"uARM": { "uARM": {
"common": ["-c", "--gnu", "-Otime", "--split_sections", "common": ["-c", "--gnu", "-Otime", "--split_sections",

View File

@ -31,7 +31,7 @@
"asm": [], "asm": [],
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
"cxx": ["--cpp", "--no_rtti", "--no_vla"], "cxx": ["--cpp", "--no_rtti", "--no_vla"],
"ld": [] "ld": ["--show_full_path"]
}, },
"uARM": { "uARM": {
"common": ["-c", "--gnu", "-Ospace", "--split_sections", "common": ["-c", "--gnu", "-Ospace", "--split_sections",

47
tools/test/memap/arm.map Normal file
View File

@ -0,0 +1,47 @@
Component: ARM Compiler 5.06 update 5 (build 528) Tool: armlink [4d35e2]
==============================================================================
Memory Map of the image
Image Entry point : 0x0001b0c1
Load Region LR_IROM1 (Base: 0x0001b000, Size: 0x0000ed04, Max: 0x00025000, ABSOLUTE, COMPRESSED[0x0000e23c])
Execution Region ER_IROM1 (Base: 0x0001b000, Size: 0x0000e1c4, Max: 0x00025000, ABSOLUTE)
Base Addr Size Type Attr Idx E Section Name Object
0x0001b000 0x000000c0 Data RO 7002 RESET /common/path/startup/startup.o
0x0001b0c0 0x00000008 Code RO 8820 * !!!main /installed/libs/../lib/armlib/c_p.l(__main.o)
0x0001b26c 0x00000098 Code RO 6076 .text /common/path/irqs/irqs.o
0x000206a0 0x00000036 Code RO 27 i._Z9time_funcPN4mbed5TimerEi /common/path/main.o
0x200039b4 0x00000018 Data RW 8092 .data /common/path/data/data.o
0x20003af8 0x00000198 Zero RW 57 .bss /common/path/data/data.o
==============================================================================
Image component sizes
Code (inc. data) RO Data RW Data ZI Data Debug
344 368 0 24 408 36188 Object Totals
8 0 0 0 0 7596 Library Totals
==============================================================================
Code (inc. data) RO Data RW Data ZI Data Debug
352 376 0 24 408 17208 Grand Totals
352 376 0 24 408 17208 ELF Image Totals (compressed)
352 376 0 24 0 0 ROM Totals
==============================================================================
Total RO Size (Code + RO Data) 352 ( 0.35kB)
Total RW Size (RW Data + ZI Data) 432 ( 0.43kB)
Total ROM Size (Code + RO Data + RW Data) 376 ( 0.37kB)
==============================================================================

25
tools/test/memap/gcc.map Normal file
View File

@ -0,0 +1,25 @@
Archive member included to satisfy reference by file (symbol)
Linker script and memory map
.text 0x000000000001b000 0x11a30
.Vectors 0x000000000001b000 0x98 /common/path/irqs/irqs.o
0x000000000001b168 0x36 /common/path/main.o
0x000000000001b168 count5(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int)
0x000000000001b200 0xc0 /common/path/startup/startup.o
0x000000000001b200 startup()
0x0000000000024020 0x8 /usr/lib/gcc/arm-none-eabi/7.1.0/../../../../arm-none-eabi/lib/armv6-m/libd16M_tlf.a(__main.o)
.data 0x0000000020002ef8 0xac8 load address 0x000000000002ca38
0x0000000020002ef8 __data_start__ = .
*(vtable)
*(.data*)
0x0000000020002ef8 0x18 /common/path/data/data.o
0x0000000020002ef8 some_global_var
.bss 0x0000000020003a80 0x2050 load address 0x000000000002d5c0
0x0000000020003a80 . = ALIGN (0x4)
0x0000000020003a80 __bss_start__ = .
*(.bss*)
.bss.completed.8574
.bss.counter 0x0000000020003c08 0x198 /common/path/data.o
0x0000000020003c08 some_zero_init_var

86
tools/test/memap/iar.map Normal file
View File

@ -0,0 +1,86 @@
###############################################################################
#
# IAR ELF Linker V7.80.1.28/LNX for ARM 18/Sep/2017 14:26:09
# Copyright 2007-2016 IAR Systems AB.
#
# Output file =
# /common/path/project.elf
# Map file =
# /common/path/project.map
# Command line =
# -f
# /common/path/.link_files.txt
# (-o
# --map=/common/path/project.map
# /common/path/project.elf
# /common/path/main.o
# /common/path/startup/startup.o
# /common/path/irqs/irqs.o
# /common/path/data/data.o
#
###############################################################################
*******************************************************************************
*** RUNTIME MODEL ATTRIBUTES
***
CppFlavor = *
__CPP_Exceptions = Disabled
__CPP_Language = C++
__Heap_Handler = DLMalloc
__SystemLibrary = DLib
__dlib_dynamic_initialization = postponed
__dlib_has_iterator_debugging = 0
__dlib_jmp_buf_num_elements = 8
*******************************************************************************
*** PLACEMENT SUMMARY
***
"A0": place at 0x0001b000 { ro section .intvec };
"P1": place in [from 0x0001b0c0 to 0x0003ffff] { ro };
"P2": place in [from 0x20002ef8 to 0x20007fff] { rw, block HEAP, block CSTACK };
do not initialize { section .noinit };
initialize by copy { rw };
{ section .intvec };
Section Kind Address Size Object
------- ---- ------- ---- ------
"A0": 0xc0
.intvec ro code 0x0001b000 0xc0 startup.o [4]
- 0x0001b0c0 0xc0
"P1": 0x
.text ro code 0x0001c753 0x36 main.o [3]
.text ro code 0x0001cfff 0x98 irqs.o [5]
.text ro code 0x0001c778 0x8 __main.o [67]
"P2", part 1 of 2: 0x18
P2-1 0x20002ef8 0x18 <Init block>
.data inited 0x20002fa8 0x18 data.o [6]
"P2", part 2 of 2: 0x198
P2-2 0x20005388 0x198 <Init block>
.bss zero 0x20002fa8 0x198 data.o [6]
*******************************************************************************
*** INIT TABLE
***
*******************************************************************************
*** MODULE SUMMARY
***
d16M_tlf.a: [67]
__main.o 8
------------------------------------------------
Total: 8
Linker created
---------------------------------------------------
Grand Total:
*******************************************************************************
*** ENTRY LIST
***

View File

@ -0,0 +1,61 @@
import sys
from io import open
from os.path import isfile, join, dirname
import json
import pytest
from tools.memap import MemapParser
from copy import deepcopy
PARSED_ARM_DATA = {
"startup/startup.o": {".text": 0xc0},
"[lib]/c_p.l/__main.o": {".text": 8},
"irqs/irqs.o": {".text": 0x98},
"data/data.o": {".data": 0x18, ".bss": 0x198},
"main.o": {".text": 0x36},
}
def test_parse_armcc():
memap = MemapParser()
memap.parse_map_file_armcc(open(join(dirname(__file__), "arm.map")))
assert memap.modules == PARSED_ARM_DATA
PARSED_IAR_GCC_DATA = {
"startup/startup.o": {".text": 0xc0},
"[lib]/d16M_tlf.a/__main.o": {".text": 8},
"irqs/irqs.o": {".text": 0x98},
"data/data.o": {".data": 0x18, ".bss": 0x198},
"main.o": {".text": 0x36},
}
def test_parse_iar():
memap = MemapParser()
memap.parse_map_file_iar(open(join(dirname(__file__), "iar.map")))
assert memap.modules == PARSED_IAR_GCC_DATA
def test_parse_gcc():
memap = MemapParser()
memap.parse_map_file_gcc(open(join(dirname(__file__), "gcc.map")))
assert memap.modules == PARSED_IAR_GCC_DATA
def test_add_empty_module():
memap = MemapParser()
old_modules = deepcopy(memap.modules)
memap.module_add("", 8, ".data")
assert(old_modules == memap.modules)
memap.module_add("main.o", 0, ".text")
assert(old_modules == memap.modules)
memap.module_add("main.o", 8, "")
assert(old_modules == memap.modules)
def test_add_full_module():
memap = MemapParser()
old_modules = deepcopy(memap.modules)
memap.module_add("main.o", 8, ".data")
assert(old_modules != memap.modules)
assert("main.o" in memap.modules)
assert(".data" in memap.modules["main.o"])
assert(memap.modules["main.o"][".data"] == 8)

View File

@ -74,7 +74,7 @@ class ARM(mbedToolchain):
self.cc = [main_cc] + self.flags['common'] + self.flags['c'] self.cc = [main_cc] + self.flags['common'] + self.flags['c']
self.cppc = [main_cc] + self.flags['common'] + self.flags['c'] + self.flags['cxx'] self.cppc = [main_cc] + self.flags['common'] + self.flags['c'] + self.flags['cxx']
self.ld = [join(ARM_BIN, "armlink")] self.ld = [join(ARM_BIN, "armlink")] + self.flags['ld']
self.ar = join(ARM_BIN, "armar") self.ar = join(ARM_BIN, "armar")
self.elf2bin = join(ARM_BIN, "fromelf") self.elf2bin = join(ARM_BIN, "fromelf")