check_link_map: rewrite in python
Oops, turns out that we don't require perl in all our build
environments. Rewrite this script (it's tiny) in Python. Exactly the
same logic.
Change-Id: Icbf4b36ef0b18fca94d54fc7fe5e47343c55c669
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
diff --git a/scripts/check_link_map.py b/scripts/check_link_map.py
new file mode 100755
index 0000000..dcc45ce
--- /dev/null
+++ b/scripts/check_link_map.py
@@ -0,0 +1,67 @@
+#!/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('(?x)' # (allow whitespace)
+ '^([a-zA-Z0-9_\.]+) \s+' # name
+ ' (0x[0-9a-f]+) \s+' # addr
+ ' (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)
+
+ lmatch = load_addr_re.search(line.rstrip())
+ if lmatch:
+ lma = int(lmatch.group(1), 16)
+ else:
+ last_sec = None
+ continue
+
+ if last_sec != 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