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