#!/usr/bin/env python3 """Extract the loadable bytes of an overlay-app ELF as a flat binary. objcopy -O binary is the normal tool; this reads the ELF itself. Allocated *sections* are used rather than program headers, because lld maps the ELF header and program header table as a LOAD of its own (52 + 4x32 = 180 bytes at the image base) with no section content in it -- following the program headers puts a phantom 180-byte region below the overlay VMA and makes the image start at the wrong address. """ import argparse import struct import sys SHT_SYMTAB, SHT_NOBITS = 2, 8 SHF_ALLOC, SHF_WRITE, SHF_EXECINSTR = 0x2, 0x1, 0x4 def sections(blob: bytes): if len(blob) < 52 or blob[0] != 0x7F or blob[1:4] != b"ELF" or blob[4] != 1 or blob[5] != 1: raise SystemExit("not a 32-bit little-endian ELF") e_shoff, = struct.unpack_from(" %s: %d bytes at 0x%08X (%d allocated section(s), %d of them with content)" % (name(args.elf), name(args.bin), len(out), base, len(secs), sum(1 for s in secs if s[2]))) if len(out) > 0x1000 and args.min == 0x20000280: print("WARNING: %d bytes exceeds the 4096-byte overlay budget" % len(out), file=sys.stderr) return 0 if __name__ == "__main__": sys.exit(main())