zephyr/scripts/check_link_map.py
Ulf Magnusson a449c98db2 scripts: Fix risky uses of non-raw regex strings in Python scripts
Fixes pylint warnings like this one:

    doc/conf.py:325:0: W1401: Anomalous backslash in string: '\s'.
    String constant might be missing an r prefix.
    (anomalous-backslash-in-string)

The reason for this warning is that backslash escapes are interpreted in
non-raw (non-r-prefixed) strings. For example, '\a' and r'\a' are not
the same string (first one has a single ASCII bell character, second one
has two characters).

It just happens that there's no \s (or \., or \/) escape for example,
and '\s' turns into two characters (as needed for a regex). It's risky
to rely on stuff like that regexes though. Best to make them raw strings
unless they're super trivial.

Also note that '\s' and '\\s' turn into the same string.

Another tip: A literal ' can be put into a string with "blah'blah"
instead of 'blah\'blah'.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
2019-03-28 14:41:32 -05:00

75 lines
2.6 KiB
Python
Executable file

#!/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