blob: ab2082c72eaaaf015b721e1f6f716f879284d7d7 [file] [log] [blame]
David Brown8405ce12016-12-21 15:40:38 -07001#!/usr/bin/env python2
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
28 ' (0x[0-9a-f]+) \s+') # size
29
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
48 lmatch = load_addr_re.search(line.rstrip())
49 if lmatch:
50 lma = int(lmatch.group(1), 16)
51 else:
52 last_sec = None
53 continue
54
55 if last_sec != None:
56 dv = vma - last_vma
57 dl = lma - last_lma
58 if dv != dl:
59 sys.stderr.write("ERROR: section %s is %d bytes "
60 "in the virtual/runtime address space, "
61 "but only %d in the loaded/XIP section!\n"
62 % (last_sec, dv, dl))
63 sys.exit(1)
64
65 last_sec = sec
66 last_vma = vma
67 last_lma = lma