mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 19:03:15 +01:00
Previously python hex() would put an extra 'L' after printing out the value and this would be trimmed in readelf.py. Now it doesn't seem to do that so the lsd of the number was trimmed. This patch fixes that.
129 lines
4.9 KiB
Python
Executable File
129 lines
4.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from aistruct import AIStruct
|
|
import elf, sys
|
|
from optparse import OptionParser
|
|
from os import path
|
|
|
|
class AfterBurner(AIStruct):
|
|
def __init__(self, *args, **kwargs):
|
|
AIStruct.__init__(self, AIStruct.SIZE32)
|
|
self.setup(
|
|
('UINT32', 'addr')
|
|
)
|
|
|
|
def __str__(self):
|
|
return "0x%x" % self.ai.addr.get()
|
|
|
|
def main():
|
|
parser = OptionParser(add_help_option=False)
|
|
parser.add_option("-h", "--file-header",
|
|
action="store_true", dest="header", default=False,
|
|
help="Display the ELF file header")
|
|
parser.add_option("-l", "--program-headers",
|
|
action="store_true", dest="program_headers", default=False,
|
|
help="Display the program headers")
|
|
parser.add_option("-S", "--section-headers",
|
|
action="store_true", dest="section_headers", default=False,
|
|
help="Display the section headers")
|
|
parser.add_option("--afterburn",
|
|
action="store_true", dest="afterburn", default=False,
|
|
help="Display the afterburn relocations")
|
|
parser.add_option("--first-free-page",
|
|
action="store_true", dest="ffpage", default=False,
|
|
help="Prints out (in .lds format) the address of the first free physical" + \
|
|
"page after this image at load time. Using this information at link" + \
|
|
"time, images can be compiled and linked consecutively and loaded in" + \
|
|
"consecutive memory regions at load time.")
|
|
parser.add_option("--lma-start-end", action="store_true", dest="lma_boundary", default=False,
|
|
help="Prints out the start and end LMA boundaries of an image." + \
|
|
"This is useful for autogenerating a structure for the microkernel" + \
|
|
"to discover at run-time where svc tasks are loaded.")
|
|
(options, args) = parser.parse_args()
|
|
if len(args) != 1:
|
|
parser.print_help()
|
|
return
|
|
elffile = elf.ElfFile.from_file(args[0])
|
|
|
|
if options.header:
|
|
print elffile.header
|
|
if options.program_headers:
|
|
print elffile.pheaders
|
|
if options.section_headers:
|
|
print elffile.sheaders
|
|
if options.afterburn:
|
|
burnheader = elffile.sheaders[".afterburn"]
|
|
burns = burnheader.container(AfterBurner)
|
|
print "There are %d afterburn entry points" % len(burns)
|
|
print "Afterburn:"
|
|
for burn in burns:
|
|
print " ", burn
|
|
if options.lma_boundary:
|
|
paddr_first = 0
|
|
paddr_start = 0
|
|
paddr_end = 0
|
|
for pheader in elffile.pheaders:
|
|
x = pheader.ai
|
|
if str(x.p_type) != "LOAD":
|
|
continue
|
|
# First time assign the first p_paddr.
|
|
if paddr_first == 0:
|
|
paddr_first = 1
|
|
paddr_start = x.p_paddr.value
|
|
# Then if new paddr is lesser, reassign start.
|
|
if paddr_start > x.p_paddr.value:
|
|
paddr_start = x.p_paddr.value
|
|
# If end of segment is greater, reassign end.
|
|
if paddr_end < x.p_paddr + x.p_memsz:
|
|
paddr_end = x.p_paddr + x.p_memsz
|
|
rest, image_name = path.split(args[0])
|
|
if image_name[-4] == ".":
|
|
image_name = image_name[:-4]
|
|
print image_name
|
|
if hex(paddr_start)[-1] == "L":
|
|
print "image_start " + hex(paddr_start)[:-1]
|
|
else:
|
|
print "image_start " + hex(paddr_start)
|
|
if hex(paddr_end)[-1] == "L":
|
|
print "image_end " + hex(paddr_end)[:-1]
|
|
else:
|
|
print "image_end " + hex(paddr_end)
|
|
|
|
if options.ffpage:
|
|
paddr_max = 0
|
|
p_align = 0
|
|
for pheader in elffile.pheaders:
|
|
x = pheader.ai
|
|
if str(x.p_type) == "LOAD":
|
|
paddr = x.p_paddr + x.p_memsz
|
|
p_align = x.p_align
|
|
if paddr > paddr_max:
|
|
paddr_max = paddr
|
|
|
|
print "/*\n" + \
|
|
" * The next free p_align'ed LMA base address\n" + \
|
|
" *\n" + \
|
|
" * p_align = " + hex(p_align.value) + "\n" + \
|
|
" *\n" + \
|
|
" * Recap from ELF spec: p_align: Loadable process segments must have\n" + \
|
|
" * congruent values for p_vaddr and p_offset, modulo the page size. \n" + \
|
|
" * This member gives the value to which the segments are aligned in \n" + \
|
|
" * memory and in the file. Values 0 and 1 mean that no alignment is \n" + \
|
|
" * required. Otherwise, p_align should be a positive, integral power\n" + \
|
|
" * of 2, and p_addr should equal p_offset, modulo p_align. \n" + \
|
|
" * This essentially means next available address must be aligned at\n" + \
|
|
" * p_align, rather than the page_size, which one (well, I) would \n" + \
|
|
" * normally expect. \n" + \
|
|
" */\n"
|
|
paddr_aligned = paddr_max & ~(p_align.value - 1)
|
|
if paddr_max & (p_align.value - 1):
|
|
paddr_aligned += p_align.value
|
|
if hex(paddr_aligned)[-1] == "L":
|
|
print "physical_base = " + hex(paddr_aligned)[:-1] + ";"
|
|
else:
|
|
print "physical_base = " + hex(paddr_aligned) + ";"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|