Last active
November 17, 2024 08:18
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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