forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheck_link_map.py
executable file
·74 lines (64 loc) · 2.59 KB
/
check_link_map.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env python3
import fileinput
import re
import sys
# Linker address generation validity checker. By default, GNU ld is
# broken when faced with sections where the load address (i.e. the
# spot in the XIP program binary where initialized data lives) differs
# from the virtual address (i.e. the location in RAM where that data
# will live at runtime. We need to be sure we're using the
# ALIGN_WITH_INPUT feature correctly everywhere, which is hard --
# especially so given that many of these bugs are semi-invisible at
# runtime (most initialized data is still a bunch of zeros and often
# "works" even if it's wrong).
#
# This quick test just checks the offsets between sequential segments
# with separate VMA/LMA addresses and verifies that the size deltas
# are identical.
#
# Note that this is assuming that the address generation is always
# in-order and that there is only one "ROM" LMA block. It's possible
# to write a valid linker script that will fail this script, but we
# don't have such a use case and one isn't forseen.
section_re = re.compile(r'(?x)' # (allow whitespace)
r'^([a-zA-Z0-9_\.]+) \s+' # name
r' (0x[0-9a-f]+) \s+' # addr
r' (0x[0-9a-f]+)\s*') # size
load_addr_re = re.compile('load address (0x[0-9a-f]+)')
in_prologue = True
lma = 0
last_sec = None
for line in fileinput.input():
# Skip the header junk
if line.find("Linker script and memory map") >= 0:
in_prologue = False
continue
match = section_re.match(line.rstrip())
if match:
sec = match.group(1)
vma = int(match.group(2), 16)
size = int(match.group(3), 16)
if sec == "bss":
# Make sure we don't compare the last section of kernel data
# with the first section of application data, the kernel's bss
# and noinit are in between.
last_sec = None
continue
lmatch = load_addr_re.search(line.rstrip())
if lmatch:
lma = int(lmatch.group(1), 16)
else:
last_sec = None
continue
if last_sec is not None:
dv = vma - last_vma
dl = lma - last_lma
if dv != dl:
sys.stderr.write("ERROR: section %s is %d bytes "
"in the virtual/runtime address space, "
"but only %d in the loaded/XIP section!\n"
% (last_sec, dv, dl))
sys.exit(1)
last_sec = sec
last_vma = vma
last_lma = lma