1#------------------------------------------------------------------------------- 2# elftools example: dwarf_pubnames_types.py 3# 4# Dump the contents of .debug_pubnames and .debug_pubtypes sections from the 5# ELF file. 6# 7# Note: sample_exe64.elf doesn't have a .debug_pubtypes section. 8# 9# Vijay Ramasami (rvijayc@gmail.com) 10# This code is in the public domain 11#------------------------------------------------------------------------------- 12from __future__ import print_function 13import sys 14 15# If pyelftools is not installed, the example can also run from the root or 16# examples/ dir of the source distribution. 17sys.path[0:0] = ['.', '..'] 18 19from elftools.elf.elffile import ELFFile 20from elftools.common.py3compat import bytes2str 21 22def process_file(filename): 23 print('Processing file:', filename) 24 with open(filename, 'rb') as f: 25 elffile = ELFFile(f) 26 27 if not elffile.has_dwarf_info(): 28 print(' file has no DWARF info') 29 return 30 31 # get_dwarf_info returns a DWARFInfo context object, which is the 32 # starting point for all DWARF-based processing in pyelftools. 33 dwarfinfo = elffile.get_dwarf_info() 34 35 # get .debug_pubtypes section. 36 pubnames = dwarfinfo.get_pubnames() 37 if pubnames is None: 38 print('ERROR: No .debug_pubnames section found in ELF.') 39 else: 40 print('%d entries found in .debug_pubnames' % len(pubnames)) 41 42 print('Trying pubnames example ...') 43 for name, entry in pubnames.items(): 44 print('%s: cu_ofs = %d, die_ofs = %d' % 45 (name, entry.cu_ofs, entry.die_ofs)) 46 47 # get the actual CU/DIE that has this information. 48 print('Fetching the actual die for %s ...' % name) 49 for cu in dwarfinfo.iter_CUs(): 50 if cu.cu_offset == entry.cu_ofs: 51 for die in cu.iter_DIEs(): 52 if die.offset == entry.die_ofs: 53 print('Die Name: %s' % 54 bytes2str(die.attributes['DW_AT_name'].value)) 55 56 # dump all entries in .debug_pubnames section. 57 print('Dumping .debug_pubnames table ...') 58 print('-' * 66) 59 print('%50s%8s%8s' % ('Symbol', 'CU_OFS', 'DIE_OFS')) 60 print('-' * 66) 61 for (name, entry) in pubnames.items(): 62 print('%50s%8d%8d' % (name, entry.cu_ofs, entry.die_ofs)) 63 print('-' * 66) 64 65 # get .debug_pubtypes section. 66 pubtypes = dwarfinfo.get_pubtypes() 67 if pubtypes is None: 68 print('ERROR: No .debug_pubtypes section found in ELF') 69 else: 70 print('%d entries found in .debug_pubtypes' % len(pubtypes)) 71 72 for name, entry in pubtypes.items(): 73 print('%s: cu_ofs = %d, die_ofs = %d' % 74 (name, entry.cu_ofs, entry.die_ofs)) 75 76 # get the actual CU/DIE that has this information. 77 print('Fetching the actual die for %s ...' % name) 78 for cu in dwarfinfo.iter_CUs(): 79 if cu.cu_offset == entry.cu_ofs: 80 for die in cu.iter_DIEs(): 81 if die.offset == entry.die_ofs: 82 print('Die Name: %s' % 83 bytes2str(die.attributes['DW_AT_name'].value)) 84 die_info_rec(die) 85 86 # dump all entries in .debug_pubtypes section. 87 print('Dumping .debug_pubtypes table ...') 88 print('-' * 66) 89 print('%50s%8s%8s' % ('Symbol', 'CU_OFS', 'DIE_OFS')) 90 print('-' * 66) 91 for (name, entry) in pubtypes.items(): 92 print('%50s%8d%8d' % (name, entry.cu_ofs, entry.die_ofs)) 93 print('-' * 66) 94 95 96def die_info_rec(die, indent_level=' '): 97 """ A recursive function for showing information about a DIE and its 98 children. 99 """ 100 print(indent_level + 'DIE tag=%s, attrs=' % die.tag) 101 for name, val in die.attributes.items(): 102 print(indent_level + ' %s = %s' % (name, val)) 103 child_indent = indent_level + ' ' 104 for child in die.iter_children(): 105 die_info_rec(child, child_indent) 106 107 108if __name__ == '__main__': 109 if sys.argv[1] == '--test': 110 process_file(sys.argv[2]) 111 sys.exit(0) 112 113 if len(sys.argv) < 2: 114 print('Expected usage: {0} <executable>'.format(sys.argv[0])) 115 sys.exit(1) 116 process_file(sys.argv[1]) 117