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