Skip to content

Instantly share code, notes, and snippets.

@prozacchiwawa
Last active November 17, 2024 08:18
Show Gist options
  • Save prozacchiwawa/b99b62a2fd3abfa4129267d5fa8d1e5c to your computer and use it in GitHub Desktop.
Save prozacchiwawa/b99b62a2fd3abfa4129267d5fa8d1e5c to your computer and use it in GitHub Desktop.
Given an elf file, show a hex dump of each section along with the relationships between symbols and relocations annotated below each line
import sys
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import Section, SymbolTableSection, Symbol
from elftools.elf.relocation import RelocationSection, Relocation
from elftools.elf.constants import SH_FLAGS
class RelocSource:
def __init__(self, target_section_number, symbol_section_number, r):
self.target_section_number = target_section_number
self.symbol_section_number = symbol_section_number
self.r = r
self.address = None
self.name = None
class RelocTarget:
def __init__(self, target_section_number, symbol_section_number, r):
self.target_section_number = target_section_number
self.symbol_section_number = symbol_section_number
self.r = r
self.address = None
self.name = None
def annotate_elf(f):
ef = ELFFile(f)
symbols = {}
def add_symbol(s):
target_section_number = s.entry.st_shndx
if type(target_section_number) == str:
return
target_section = ef.get_section(target_section_number)
key = (target_section.name, s.entry.st_value)
res = []
if key in symbols:
res = symbols[key]
res.append(s)
symbols[key] = res
def add_reloc_source(r):
target_section = ef.get_section(r.target_section_number)
target_symbol_section = ef.get_section(r.symbol_section_number)
target_symbol_number = r.r.entry['r_info'] >> 8
target_symbol = target_symbol_section.get_symbol(target_symbol_number)
if target_symbol.entry.st_shndx == 'SHN_UNDEF':
return
target_content_section = ef.get_section(target_symbol.entry.st_shndx)
r.address = r.r.entry['r_offset']
addend = r.r.entry['r_addend'] if 'r_addend' in r.r.entry else 0
r.name = '%s+%x' % (target_symbol.name, addend)
key = (target_section.name, r.address)
res = []
if key in symbols:
res = symbols[key]
res.append(r)
symbols[key] = res
def add_reloc_target(r):
target_section = ef.get_section(r.target_section_number)
target_symbol_section = ef.get_section(r.symbol_section_number)
target_symbol_number = r.r.entry['r_info'] >> 8
target_symbol = target_symbol_section.get_symbol(target_symbol_number)
if target_symbol.entry.st_shndx == 'SHN_UNDEF':
return
target_content_section = ef.get_section(target_symbol.entry.st_shndx)
addend = r.r.entry['r_addend'] if 'r_addend' in r.r.entry else 0
r.address = target_symbol.entry.st_value + addend
r.name = '%s+%x' % (target_symbol.name, addend)
key = (target_content_section.name, r.address)
res = []
if key in symbols:
res = symbols[key]
res.append(r)
symbols[key] = res
for sect in ef.iter_sections():
if isinstance(sect, SymbolTableSection):
for s in sect.iter_symbols():
add_symbol(s)
elif isinstance(sect, RelocationSection):
for r in sect.iter_relocations():
target_section_number = sect.header['sh_info']
symbol_section_number = sect.header['sh_link']
add_reloc_source(RelocSource(target_section_number, symbol_section_number, r))
add_reloc_target(RelocTarget(target_section_number, symbol_section_number, r))
for sect in ef.iter_sections():
if sect.header['sh_flags'] & SH_FLAGS.SHF_ALLOC or sect.header['sh_type'] == 'SHT_PROGBITS':
d = sect.data()
print(f'section {sect.name}')
off = 0
while off <= len(d):
symbols_this_line = []
sys.stdout.write('%08x:' % off)
for i in range(16):
if off + i >= len(d):
break
key = (sect.name, off + i)
if key in symbols:
symbols_this_line += symbols[key]
sys.stdout.write(' %02x' % d[off + i])
print('')
if len(symbols_this_line):
for s in symbols_this_line:
if isinstance(s, Symbol):
if len(s.name):
print('%08x %s' % (s.entry.st_value, s.name))
elif isinstance(s, RelocSource):
print('%08x <-%02x %s' % (s.address, s.r['r_info'] & 0xff, s.name))
else:
print('%08x %02x-> %s' % (s.address, s.r['r_info'] & 0xff, s.name))
off += 16
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('elffile')
args = parser.parse_args()
annotate_elf(open(args.elffile,'rb'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment