(Note, with this patch, make READELF=llvm-readelf
qemu-system-x86_64 -boot menu=on,splash-time=15000 -bios out/bios.bin -nographic
seems working
)
readelf is generally better than objdump when dumping ELF section/symbol information.
objdump -h relies heavily on BFD internals and the output is difficult to emulate in llvm-objdump.
Signed-off-by: Fangrui Song <maskray(a)google.com>
---
Makefile | 18 +++---
scripts/checkrom.py | 2 +-
scripts/layoutrom.py | 146 +++++++++++++++++++++----------------------
3 files changed, 80 insertions(+), 86 deletions(-)
diff --git a/Makefile b/Makefile
index 5f7d537..7a16195 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ endif
AS=$(CROSS_PREFIX)as
LD=$(CROSS_PREFIX)ld
OBJCOPY=$(CROSS_PREFIX)objcopy
-OBJDUMP=$(CROSS_PREFIX)objdump
+READELF=$(CROSS_PREFIX)readelf
STRIP=$(CROSS_PREFIX)strip
PYTHON=python
CPP=cpp
@@ -161,14 +161,14 @@ $(OUT)romlayout.o: src/romlayout.S $(OUT)autoconf.h $(OUT)asm-offsets.h
$(OUT)romlayout16.lds: $(OUT)ccode32flat.o $(OUT)code32seg.o $(OUT)ccode16.o $(OUT)romlayout.o src/version.c scripts/layoutrom.py scripts/buildversion.py
@echo " Building ld scripts"
- $(Q)$(PYTHON) ./scripts/buildversion.py -e "$(EXTRAVERSION)" -t "$(CC);$(AS);$(LD);$(OBJCOPY);$(OBJDUMP);$(STRIP)" $(OUT)autoversion.h
+ $(Q)$(PYTHON) ./scripts/buildversion.py -e "$(EXTRAVERSION)" -t "$(CC);$(AS);$(LD);$(OBJCOPY);$(READELF);$(STRIP)" $(OUT)autoversion.h
$(Q)$(CC) $(CFLAGS32FLAT) -c src/version.c -o $(OUT)version.o
$(Q)$(LD) $(LD32BIT_FLAG) -r $(OUT)ccode32flat.o $(OUT)version.o -o $(OUT)code32flat.o
$(Q)$(LD) $(LD32BIT_FLAG) -r $(OUT)ccode16.o $(OUT)romlayout.o -o $(OUT)code16.o
- $(Q)$(OBJDUMP) -thr $(OUT)code32flat.o > $(OUT)code32flat.o.objdump
- $(Q)$(OBJDUMP) -thr $(OUT)code32seg.o > $(OUT)code32seg.o.objdump
- $(Q)$(OBJDUMP) -thr $(OUT)code16.o > $(OUT)code16.o.objdump
- $(Q)$(PYTHON) ./scripts/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32seg.o.objdump $(OUT)code32flat.o.objdump $(OUT)$(KCONFIG_AUTOHEADER) $(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds
+ $(Q)$(READELF) -WSrs $(OUT)code32flat.o > $(OUT)code32flat.o.readelf
+ $(Q)$(READELF) -WSrs $(OUT)code32seg.o > $(OUT)code32seg.o.readelf
+ $(Q)$(READELF) -WSrs $(OUT)code16.o > $(OUT)code16.o.readelf
+ $(Q)$(PYTHON) ./scripts/layoutrom.py $(OUT)code16.o.readelf $(OUT)code32seg.o.readelf $(OUT)code32flat.o.readelf $(OUT)$(KCONFIG_AUTOHEADER) $(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds
# These are actually built by scripts/layoutrom.py above, but by pulling them
# into an extra rule we prevent make -j from spawning layoutrom.py 4 times.
@@ -189,9 +189,9 @@ $(OUT)rom.o: $(OUT)rom16.strip.o $(OUT)rom32seg.strip.o $(OUT)code32flat.o $(OUT
$(OUT)bios.bin.prep: $(OUT)rom.o scripts/checkrom.py
@echo " Prepping $@"
$(Q)rm -f $(OUT)bios.bin $(OUT)Csm16.bin $(OUT)bios.bin.elf
- $(Q)$(OBJDUMP) -thr $< > $<.objdump
+ $(Q)$(READELF) -WSrs $< > $<.readelf
$(Q)$(OBJCOPY) -O binary $< $(OUT)bios.bin.raw
- $(Q)$(PYTHON) ./scripts/checkrom.py $<.objdump $(CONFIG_ROM_SIZE) $(OUT)bios.bin.raw $(OUT)bios.bin.prep
+ $(Q)$(PYTHON) ./scripts/checkrom.py $<.readelf $(CONFIG_ROM_SIZE) $(OUT)bios.bin.raw $(OUT)bios.bin.prep
$(OUT)bios.bin: $(OUT)bios.bin.prep
@echo " Creating $@"
@@ -233,7 +233,7 @@ $(OUT)vgaentry.o: vgasrc/vgaentry.S $(OUT)autoconf.h $(OUT)asm-offsets.h
$(OUT)vgarom.o: $(OUT)vgaccode16.o $(OUT)vgaentry.o $(OUT)vgasrc/vgalayout.lds vgasrc/vgaversion.c scripts/buildversion.py
@echo " Linking $@"
- $(Q)$(PYTHON) ./scripts/buildversion.py -e "$(EXTRAVERSION)" -t "$(CC);$(AS);$(LD);$(OBJCOPY);$(OBJDUMP);$(STRIP)" $(OUT)autovgaversion.h
+ $(Q)$(PYTHON) ./scripts/buildversion.py -e "$(EXTRAVERSION)" -t "$(CC);$(AS);$(LD);$(OBJCOPY);$(READELF);$(STRIP)" $(OUT)autovgaversion.h
$(Q)$(CC) $(CFLAGS16) -c vgasrc/vgaversion.c -o $(OUT)vgaversion.o
$(Q)$(LD) --gc-sections -T $(OUT)vgasrc/vgalayout.lds $(OUT)vgaccode16.o $(OUT)vgaentry.o $(OUT)vgaversion.o -o $@
diff --git a/scripts/checkrom.py b/scripts/checkrom.py
index aced5e2..721444d 100755
--- a/scripts/checkrom.py
+++ b/scripts/checkrom.py
@@ -23,7 +23,7 @@ def main():
# Read in symbols
objinfofile = open(objinfo, 'r')
- symbols = layoutrom.parseObjDump(objinfofile, 'in')[1]
+ symbols = layoutrom.parseReadElf(objinfofile, 'in')[1]
# Read in raw file
f = open(rawfile, 'rb')
diff --git a/scripts/layoutrom.py b/scripts/layoutrom.py
index 14e6ada..6cc9e04 100755
--- a/scripts/layoutrom.py
+++ b/scripts/layoutrom.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Script to analyze code and arrange ld sections.
#
# Copyright (C) 2008-2014 Kevin O'Connor <kevin(a)koconnor.net>
@@ -7,6 +7,7 @@
import operator
import sys
+from ipdb import set_trace as bp
# LD script headers/trailers
COMMONHEADER = """
@@ -544,87 +545,80 @@ class Reloc:
class Symbol:
name = offset = section = None
-# Read in output from objdump
-def parseObjDump(file, fileid):
+def parseReadElf(file, fileid):
# sections = [section, ...]
sections = []
sectionmap = {}
# symbols[symbolname] = symbol
symbols = {}
+ lines = file.readlines()
- state = None
- for line in file.readlines():
- line = line.rstrip()
- if line == 'Sections:':
- state = 'section'
- continue
- if line == 'SYMBOL TABLE:':
- state = 'symbol'
- continue
- if line.startswith('RELOCATION RECORDS FOR ['):
- sectionname = line[24:-2]
- if sectionname.startswith('.debug_'):
- # Skip debugging sections (to reduce parsing time)
- state = None
- continue
- state = 'reloc'
- relocsection = sectionmap[sectionname]
- continue
+ i = 0
+ while not lines[i].startswith('Section Headers'):
+ i += 1
+ i += 3 # Skip [Nr] and [ 0]
+ while ']' in lines[i]:
+ parts = lines[i][lines[i].find(']')+1:].split()
+ if len(parts) == 10:
+ name, _, _, _, size, _, _, _, _, align = parts
+ else: # not SHF_ALLOC
+ name, _, _, _, size, _, _, _, align = parts
+ section = Section()
+ section.name = name
+ section.size = int(size, 16)
+ section.align = int(align)
+ section.fileid = fileid
+ section.relocs = []
+ sections.append(section)
+ sectionmap[name] = section
+ i += 1
- if state == 'section':
- try:
- idx, name, size, vma, lma, fileoff, align = line.split()
- if align[:3] != '2**':
- continue
- section = Section()
- section.name = name
- section.size = int(size, 16)
- section.align = 2**int(align[3:])
- section.fileid = fileid
- section.relocs = []
- sections.append(section)
- sectionmap[name] = section
- except ValueError:
- pass
+ while not lines[i].startswith('Symbol table '):
+ i += 1
+ i += 3 # Skip Num: and 0:
+ while i < len(lines) and ':' in lines[i]:
+ colon = lines[i].find(':')
+ parts = lines[i].split()
+ try:
+ ndx = int(parts[6])
+ name = sections[ndx-1].name
+ except ValueError: # ABS or UND
+ ndx = 0
+ name = ''
+ if parts[3] != 'SECTION':
+ name = parts[7]
+ symbol = Symbol()
+ symbol.size = int(parts[2])
+ symbol.offset = int(parts[1], 16)
+ symbol.name = name
+ symbol.section = sections[ndx-1] if ndx > 0 else None
+ symbols[name] = symbol
+ i += 1
+
+ i = 0
+ while i < len(lines):
+ if not lines[i].startswith('Relocation section'):
+ i += 1
continue
- if state == 'symbol':
- try:
- parts = line[17:].split()
- if len(parts) == 3:
- sectionname, size, name = parts
- elif len(parts) == 4 and parts[2] == '.hidden':
- sectionname, size, hidden, name = parts
- else:
- continue
- symbol = Symbol()
- symbol.size = int(size, 16)
- symbol.offset = int(line[:8], 16)
- symbol.name = name
- symbol.section = sectionmap.get(sectionname)
- symbols[name] = symbol
- except ValueError:
- pass
+ rel_name = lines[i][20:lines[i].index("'", 20)]
+ i += 2
+ if rel_name.startswith('.rel.debug_'):
+ # Skip debugging sections (to reduce parsing time)
continue
- if state == 'reloc':
- try:
- off, type, symbolname = line.split()
- reloc = Reloc()
- reloc.offset = int(off, 16)
- reloc.type = type
- reloc.symbolname = symbolname
- reloc.symbol = symbols.get(symbolname)
- if reloc.symbol is None:
- # Some binutils (2.20.1) give section name instead
- # of a symbol - create a dummy symbol.
- reloc.symbol = symbol = Symbol()
- symbol.size = 0
- symbol.offset = 0
- symbol.name = symbolname
- symbol.section = sectionmap.get(symbolname)
- symbols[symbolname] = symbol
- relocsection.relocs.append(reloc)
- except ValueError:
- pass
+ assert rel_name.startswith('.rel')
+ relocated = sectionmap[rel_name[4:]]
+ while lines[i][0].isalnum():
+ line = lines[i]
+ off, _, typ, _, symbolname = line.split()
+ reloc = Reloc()
+ reloc.offset = int(off, 16)
+ reloc.type = typ
+ reloc.symbolname = symbolname
+ reloc.symbol = symbols.get(symbolname)
+ assert reloc.symbol is not None
+ relocated.relocs.append(reloc)
+ i += 1
+
return sections, symbols
# Parser for constants in simple C header files.
@@ -653,9 +647,9 @@ def main():
infile32flat = open(in32flat, 'r')
# infoX = (sections, symbols)
- info16 = parseObjDump(infile16, '16')
- info32seg = parseObjDump(infile32seg, '32seg')
- info32flat = parseObjDump(infile32flat, '32flat')
+ info16 = parseReadElf(infile16, '16')
+ info32seg = parseReadElf(infile32seg, '32seg')
+ info32flat = parseReadElf(infile32flat, '32flat')
# Read kconfig config file
config = scanconfig(cfgfile)
--
2.25.1