From: Eli Bendersky Date: Thu, 22 Dec 2011 13:22:00 +0000 (+0200) Subject: documentation fixes + new examples X-Git-Tag: v0.10~16 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1a516a3eb2e159fba1f9ef05686f36de80c899cf;p=pyelftools.git documentation fixes + new examples --- diff --git a/elftools/elf/relocation.py b/elftools/elf/relocation.py index cc90032..acb2da2 100644 --- a/elftools/elf/relocation.py +++ b/elftools/elf/relocation.py @@ -44,6 +44,8 @@ class Relocation(object): class RelocationSection(Section): + """ ELF relocation section. Serves as a collection of Relocation entries. + """ def __init__(self, header, name, stream, elffile): super(RelocationSection, self).__init__(header, name, stream) self.elffile = elffile diff --git a/examples/dwarf_die_tree.py b/examples/dwarf_die_tree.py new file mode 100644 index 0000000..5633d59 --- /dev/null +++ b/examples/dwarf_die_tree.py @@ -0,0 +1,73 @@ +#------------------------------------------------------------------------------- +# elftools example: dwarf_die_tree.py +# +# In the .debug_info section, Dwarf Information Entries (DIEs) form a tree. +# pyelftools provides easy access to this tree, as demonstrated here. +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +from __future__ import print_function +import sys +from elftools.elf.elffile import ELFFile + + +def process_file(filename): + print('Processing file:', filename) + with open(filename) as f: + elffile = ELFFile(f) + + if not elffile.has_dwarf_info(): + print(' file has no DWARF info') + return + + # get_dwarf_info returns a DWARFInfo context object, which is the + # starting point for all DWARF-based processing in pyelftools. + dwarfinfo = elffile.get_dwarf_info() + + for CU in dwarfinfo.iter_CUs(): + # DWARFInfo allows to iterate over the compile units contained in + # the .debug_info section. CU is a CompileUnit object, with some + # computed attributes (such as its offset in the section) and + # a header which conforms to the DWARF standard. The access to + # header elements is, as usual, via item-lookup. + print(' Found a compile unit at offset %s, length %s' % ( + CU.cu_offset, CU['unit_length'])) + + # Start with the top DIE, the root for this CU's DIE tree + top_DIE = CU.get_top_DIE() + print(' Top DIE with tag=%s' % top_DIE.tag) + + # Each DIE holds an OrderedDict of attributes, mapping names to + # values. Values are represented by AttributeValue objects in + # elftools/dwarf/die.py + # We're interested in the DW_AT_name attribute. Note that its value + # is usually a string taken from the .debug_string section. This + # is done transparently by the library, and such a value will be + # simply given as a string. + name_attr = top_DIE.attributes['DW_AT_name'] + print(' name=%s' % name_attr.value) + + # Display DIEs recursively starting with top_DIE + die_info_rec(top_DIE) + + +def die_info_rec(die, indent_level=' '): + """ A recursive function for showing information about a DIE and its + children. + """ + print(indent_level + 'DIE tag=%s' % die.tag) + child_indent = indent_level + ' ' + for child in die.iter_children(): + die_info_rec(child, child_indent) + + +if __name__ == '__main__': + for filename in sys.argv[1:]: + process_file(filename) + + + + + + diff --git a/examples/elf_low_high_api.py b/examples/elf_low_high_api.py new file mode 100644 index 0000000..43f9880 --- /dev/null +++ b/examples/elf_low_high_api.py @@ -0,0 +1,74 @@ +#------------------------------------------------------------------------------- +# elftools example: elf_low_high_api.py +# +# A simple example that shows some usage of the low-level API pyelftools +# provides versus the high-level API. +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +from __future__ import print_function +import sys +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection + + +def process_file(filename): + print('Processing file:', filename) + with open(filename) as f: + section_info_lowlevel(f) + f.seek(0) + section_info_highlevel(f) + + +def section_info_lowlevel(stream): + print('Low level API...') + # We'll still be using the ELFFile context object. It's just too + # convenient to give up, even in the low-level API demonstation :-) + elffile = ELFFile(stream) + + # The e_shnum ELF header field says how many sections there are in a file + print(' %s sections' % elffile['e_shnum']) + + # We need section #40 + section_offset = elffile['e_shoff'] + 40 * elffile['e_shentsize'] + + # Parse the section header using structs.Elf_Shdr + stream.seek(section_offset) + section_header = elffile.structs.Elf_Shdr.parse_stream(stream) + + # Some details about the section. Note that the section name is a pointer + # to the object's string table, so it's only a number here. To get to the + # actual name one would need to parse the string table section and extract + # the name from there (or use the high-level API!) + print(' Section name: %s, type: %s' % ( + section_header['sh_name'], section_header['sh_type'])) + + +def section_info_highlevel(stream): + print('High level API...') + elffile = ELFFile(stream) + + # Just use the public methods of ELFFile to get what we need + print(' %s sections' % elffile.num_sections()) + section = elffile.get_section(40) + + # A section type is in its header, but the name was decoded and placed in + # a public attribute. + print(' Section name: %s, type: %s' %( + section.name, section['sh_type'])) + + # But there's more... If this section is a symbol table section (which is + # the case in the sample ELF file that comes with the examples), we can + # get some more information about it. + if isinstance(section, SymbolTableSection): + print(" It's a symbol section with %s symbols" % section.num_symbols()) + print(" The name of symbol #60 is: %s" % ( + section.get_symbol(60).name)) + + +if __name__ == '__main__': + for filename in sys.argv[1:]: + process_file(filename) + + diff --git a/examples/elf_relocations.py b/examples/elf_relocations.py new file mode 100644 index 0000000..a09f014 --- /dev/null +++ b/examples/elf_relocations.py @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------- +# elftools example: elf_relocations.py +# +# An example of obtaining a relocation section from an ELF file and examining +# the relocation entries it contains. +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +from __future__ import print_function +import sys +from elftools.elf.elffile import ELFFile +from elftools.elf.relocation import RelocationSection + + +def process_file(filename): + print('Processing file:', filename) + with open(filename) as f: + elffile = ELFFile(f) + + # Read the .rela.dyn section from the file, by explicitly asking + # ELFFile for this section + reladyn_name = '.rela.dyn' + reladyn = elffile.get_section_by_name(reladyn_name) + + if not isinstance(reladyn, RelocationSection): + print(' The file has no %s section' % reladyn_name) + + print(' %s section with %s relocations' % ( + reladyn_name, reladyn.num_relocations())) + + for reloc in reladyn.iter_relocations(): + # Use the Relocation's object ability to pretty-print itself to a + # string to examine it + print(' ', reloc) + + # Relocation entry attributes are available through item lookup + print(' offset = %s' % reloc['r_offset']) + + +if __name__ == '__main__': + for filename in sys.argv[1:]: + process_file(filename) + + + diff --git a/examples/elfclass_address_size.py b/examples/elfclass_address_size.py index e131496..21c839c 100644 --- a/examples/elfclass_address_size.py +++ b/examples/elfclass_address_size.py @@ -7,6 +7,7 @@ # Eli Bendersky (eliben@gmail.com) # This code is in the public domain #------------------------------------------------------------------------------- +from __future__ import print_function import sys from elftools.elf.elffile import ELFFile @@ -14,13 +15,17 @@ from elftools.elf.elffile import ELFFile def process_file(filename): with open(filename) as f: elffile = ELFFile(f) - print '%s: elfclass is %s' % (filename, elffile.elfclass) + # elfclass is a public attribute of ELFFile, read from its header + print('%s: elfclass is %s' % (filename, elffile.elfclass)) if elffile.has_dwarf_info(): dwarfinfo = elffile.get_dwarf_info() for CU in dwarfinfo.iter_CUs(): - print ' CU at offset 0x%x. address_size is %s' % ( - CU.cu_offset, CU['address_size']) + # cu_offset is a public attribute of CU + # address_size is part of the CU header + print(' CU at offset 0x%x. address_size is %s' % ( + CU.cu_offset, CU['address_size'])) + if __name__ == '__main__': for filename in sys.argv[1:]: diff --git a/examples/examine_dwarf_info.py b/examples/examine_dwarf_info.py new file mode 100644 index 0000000..ba712dd --- /dev/null +++ b/examples/examine_dwarf_info.py @@ -0,0 +1,57 @@ +#------------------------------------------------------------------------------- +# elftools example: examine_dwarf_info.py +# +# An example of examining information in the .debug_info section of an ELF file. +# +# Eli Bendersky (eliben@gmail.com) +# This code is in the public domain +#------------------------------------------------------------------------------- +from __future__ import print_function +import sys +from elftools.elf.elffile import ELFFile + + +def process_file(filename): + print('Processing file:', filename) + with open(filename) as f: + elffile = ELFFile(f) + + if not elffile.has_dwarf_info(): + print(' file has no DWARF info') + return + + # get_dwarf_info returns a DWARFInfo context object, which is the + # starting point for all DWARF-based processing in pyelftools. + dwarfinfo = elffile.get_dwarf_info() + + for CU in dwarfinfo.iter_CUs(): + # DWARFInfo allows to iterate over the compile units contained in + # the .debug_info section. CU is a CompileUnit object, with some + # computed attributes (such as its offset in the section) and + # a header which conforms to the DWARF standard. The access to + # header elements is, as usual, via item-lookup. + print(' Found a compile unit at offset %s, length %s' % ( + CU.cu_offset, CU['unit_length'])) + + # The first DIE in each compile unit describes it. + top_DIE = CU.get_top_DIE() + print(' Top DIE with tag=%s' % top_DIE.tag) + + # Each DIE holds an OrderedDict of attributes, mapping names to + # values. Values are represented by AttributeValue objects in + # elftools/dwarf/die.py + # We're interested in the DW_AT_name attribute. Note that its value + # is usually a string taken from the .debug_string section. This + # is done transparently by the library, and such a value will be + # simply given as a string. + name_attr = top_DIE.attributes['DW_AT_name'] + print(' name=%s' % name_attr.value) + +if __name__ == '__main__': + for filename in sys.argv[1:]: + process_file(filename) + + + + + diff --git a/examples/sample_exe64.elf b/examples/sample_exe64.elf new file mode 100644 index 0000000..ccfa6ae Binary files /dev/null and b/examples/sample_exe64.elf differ diff --git a/scripts/readelf.py b/scripts/readelf.py index 051a21a..c133d53 100755 --- a/scripts/readelf.py +++ b/scripts/readelf.py @@ -756,8 +756,10 @@ def main(stream=None): action='store', dest='show_string_dump', metavar='', help='Dump the contents of section as strings') optparser.add_option('--debug-dump', - action='store', dest='debug_dump_what', metavar='
', - help='Display the contents of DWARF debug sections') + action='store', dest='debug_dump_what', metavar='', + help=( + 'Display the contents of DWARF debug sections. can ' + + 'one of {info,decodedline,frames,frames-interp}')) options, args = optparser.parse_args()