pyelftools
pyelftools is a Python library for parsing and analyzing ELF files and DWARF debugging information. It provides a low-level interface to the structures within these binary formats, making it suitable for security research, reverse engineering, and compiler development. The current stable version is 0.32, with new features and bug fixes released periodically.
Warnings
- breaking The exception hierarchy was refactored in version 0.30.0. The general `elftools.common.exceptions.ELFError` was removed and split into more specific exceptions (e.g., `ELFParseError`, `ELFEndianError`, `ELFRelocationError`). Catching the old `ELFError` will now fail.
- breaking For DWARF debugging information, the `DIE.get_form_attribute()` method was removed in version 0.31.0. This method was considered old and unused.
- breaking In version 0.29.0, the `location` attribute of `DW_AT_location` is now always a `LocationExpr` object. It no longer directly holds the raw data or a simple offset.
- gotcha When opening ELF files, ensure they are always opened in binary read mode (`'rb'`). Opening in text mode (`'r'`) or binary write mode will lead to errors or corrupted data.
- gotcha While `pyelftools` provides detailed DWARF parsing, interpreting the full complexity of DWARF information (e.g., location expressions, type graphs) often requires additional logic or domain-specific knowledge beyond what the library directly provides as high-level abstractions.
Install
-
pip install pyelftools
Imports
- ELFFile
from elftools.elf.elffile import ELFFile
- DWARFInfo
from elftools.dwarf.dwarfinfo import DWARFInfo
- ET_CORE
from elftools.elf.elffile import ET_CORE
Quickstart
import os
from elftools.elf.elffile import ELFFile
def analyze_elf(filepath):
if not os.path.exists(filepath):
print(f"Error: File not found at {filepath}")
return
try:
with open(filepath, 'rb') as f:
elf_file = ELFFile(f)
print(f"\nAnalyzing ELF: {filepath}")
print(f" Class: {elf_file.elfclass} ({'64-bit' if elf_file.elfclass == 64 else '32-bit'})")
print(f" Endianness: {'Little' if elf_file.little_endian else 'Big'}")
print(f" Machine Arch: {elf_file.get_machine_arch()}")
print(f" Entry Point: 0x{elf_file.header['e_entry']:x}")
# Example: Iterate through sections
print(" Sections:")
for section in elf_file.iter_sections():
print(f" - {section.name} (type: {section['sh_type']})")
if elf_file.has_dwarf_info():
print(" Contains DWARF info.")
except Exception as e:
print(f"Error processing ELF file: {e}")
# Example usage: Replace with a path to a real ELF binary on your system
# For demonstration, let's assume '/bin/ls' or a similar common binary exists.
# On Windows, you might need a WSL path or a Linux VM for native ELF binaries.
# For a true cross-platform example, you'd need to create a dummy ELF.
# For this quickstart, assume a /bin/ls exists (common on Linux/macOS).
if os.path.exists('/bin/ls'):
analyze_elf('/bin/ls')
elif os.name == 'posix':
print("'/bin/ls' not found. Please provide a path to an ELF binary on your system to run this example.")
else:
print("This quickstart needs an ELF binary (like '/bin/ls') to run. Not applicable on Windows without WSL.")