forked from eliben/pyelftools
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
264 additions
and
5 deletions.
There are no files selected for viewing
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
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
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) | ||
|
||
|
||
|
||
|
||
|
||
|
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
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) | ||
|
||
|
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
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) | ||
|
||
|
||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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:]: | ||
|
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
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 not shown.
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