elfloader/shoehorn: handle gaps between loadable elf segments

Correct the calculated memory needed to load an elf image. Using only
the p_memsz value ignores gaps between segments; instead calculate the
first+last addresses using p_vaddr & p_memsz.

Change-Id: Iba77d1bf8f051eca32d5aedd601d25d2ec84a0d6
diff --git a/cmake-tool/helpers/elf_sift.py b/cmake-tool/helpers/elf_sift.py
index a06575b..fe48880 100755
--- a/cmake-tool/helpers/elf_sift.py
+++ b/cmake-tool/helpers/elf_sift.py
@@ -33,16 +33,26 @@
     the ELF object file `elf_file`.
     """
 
-    total: int = 0
     elf = elftools.elf.elffile.ELFFile(elf_file)
 
     # We only care about loadable segments (p_type is "PT_LOAD"), and we
     # want the size in memory of those segments (p_memsz), which can be
     # greater than the size in the file (p_filesz).  This is especially
     # important for the BSS section.  See elf(5).
-    total = sum([seg['p_memsz'] for seg in elf.iter_segments()
-                 if seg['p_type'] == 'PT_LOAD'])
 
+    # There may be gaps between segments; use the min+max vaddr of
+    # the loaded segments to calculate total usage.
+    min_vaddr = None
+    max_vaddr: int = 0
+    for seg in elf.iter_segments():
+        if seg['p_type'] == 'PT_LOAD':
+            if min_vaddr is None:
+                min_vaddr = seg['p_vaddr']
+            else:
+                min_vaddr = min(seg['p_vaddr'], min_vaddr)
+            max_vaddr = max(seg['p_vaddr'] + seg['p_memsz'], max_vaddr)
+
+    total: int = max_vaddr - min_vaddr
     return get_aligned_size(total) if align else total