Skip to content

Commit

Permalink
documentation fixes + new examples
Browse files Browse the repository at this point in the history
  • Loading branch information
eliben committed Dec 22, 2011
1 parent eb87001 commit 1a516a3
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 5 deletions.
2 changes: 2 additions & 0 deletions elftools/elf/relocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ def __str__(self):


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
Expand Down
73 changes: 73 additions & 0 deletions examples/dwarf_die_tree.py
Original file line number Diff line number Diff line change
@@ -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 ([email protected])
# 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)






74 changes: 74 additions & 0 deletions examples/elf_low_high_api.py
Original file line number Diff line number Diff line change
@@ -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 ([email protected])
# 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)


46 changes: 46 additions & 0 deletions examples/elf_relocations.py
Original file line number Diff line number Diff line change
@@ -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 ([email protected])
# 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)



11 changes: 8 additions & 3 deletions examples/elfclass_address_size.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,25 @@
# Eli Bendersky ([email protected])
# This code is in the public domain
#-------------------------------------------------------------------------------
from __future__ import print_function
import sys
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:]:
Expand Down
57 changes: 57 additions & 0 deletions examples/examine_dwarf_info.py
Original file line number Diff line number Diff line change
@@ -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 ([email protected])
# 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)





Binary file added examples/sample_exe64.elf
Binary file not shown.
6 changes: 4 additions & 2 deletions scripts/readelf.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,8 +756,10 @@ def main(stream=None):
action='store', dest='show_string_dump', metavar='<number|name>',
help='Dump the contents of section <number|name> as strings')
optparser.add_option('--debug-dump',
action='store', dest='debug_dump_what', metavar='<section>',
help='Display the contents of DWARF debug sections')
action='store', dest='debug_dump_what', metavar='<what>',
help=(
'Display the contents of DWARF debug sections. <what> can ' +
'one of {info,decodedline,frames,frames-interp}'))

options, args = optparser.parse_args()

Expand Down

0 comments on commit 1a516a3

Please sign in to comment.