Skip to content

Commit

Permalink
Replace $(OBJDUMP) -thr with $(READELF) -WSrs
Browse files Browse the repository at this point in the history
objdump -h relies heavily on BFD internals and the BFD flags. The output
is difficult to emulate in llvm-objdump. (llvm-objdump -h has a
different output https://reviews.llvm.org/D57146 .) Switch to READELF,
so that llvm-readelf can be used as an alternative.

readelf is generally better than objdump when dumping ELF section/symbol
information.

Signed-off-by: Fangrui Song <maskray@google.com>
  • Loading branch information
MaskRay committed Jul 14, 2022
1 parent 48a651e commit 39ee69b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 87 deletions.
18 changes: 9 additions & 9 deletions Makefile
Expand Up @@ -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
Expand Down Expand Up @@ -165,14 +165,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.
Expand All @@ -193,9 +193,9 @@ $(OUT)rom.o: $(OUT)rom16.noexec.o $(OUT)rom32seg.noexec.o $(OUT)code32flat.o $(O
$(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 $@"
Expand Down Expand Up @@ -237,7 +237,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 $@

Expand Down
2 changes: 1 addition & 1 deletion scripts/checkrom.py
Expand Up @@ -21,7 +21,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')
Expand Down
147 changes: 70 additions & 77 deletions scripts/layoutrom.py
Expand Up @@ -541,87 +541,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 = {}

state = None
for line in file.readlines():
line = line.rstrip()
if line == 'Sections:':
state = 'section'
continue
if line == 'SYMBOL TABLE:':
state = 'symbol'
lines = file.readlines()

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

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 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]
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
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

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
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
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
return sections, symbols

# Parser for constants in simple C header files.
Expand All @@ -644,15 +637,15 @@ def main():
# Get output name
in16, in32seg, in32flat, cfgfile, out16, out32seg, out32flat = sys.argv[1:]

# Read in the objdump information
# Read in the readelf information
infile16 = open(in16, 'r')
infile32seg = open(in32seg, 'r')
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)
Expand Down

0 comments on commit 39ee69b

Please sign in to comment.