### Run pyelftools Examples Source: https://github.com/eliben/pyelftools/blob/main/doc/user-guide.md Execute pyelftools examples by specifying the path to the examples directory and an ELF filename. Ensure pyelftools is installed. ```text > python /examples/ --test ``` -------------------------------- ### Retrieve Source File List Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md This example shows how to get the list of source files referenced by a LineProgram and print their names. File index 1 is the first file, with index 0 being undefined. ```python files = lineprogram.get_file_list() for idx, file_entry in enumerate(files): print(f"File {idx}: {file_entry.name}") ``` -------------------------------- ### Example: Looking up a symbol with GNUHashTable Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Hash.md Demonstrates how to obtain a GNUHashTable and use its get_symbol method to find a symbol by name, then print its value. ```python gnu_hash = dynamic_segment.get_hash_table(elffile) if isinstance(gnu_hash, GNUHashTable): sym = gnu_hash.get_symbol('malloc') print(f"malloc at {hex(sym['st_value'])}") ``` -------------------------------- ### Iterating and Printing Line Program States Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Example of iterating through line program entries and printing the state information for entries that have a state. ```python for entry in lineprogram.get_entries(): if entry.state: state = entry.state print(f"{state.file}:{state.line}:{state.column} @ {hex(state.address)}") ``` -------------------------------- ### Instantiating DWARFInfo via ELFFile Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md This example shows how to obtain a DWARFInfo object by opening an ELF file and calling the get_dwarf_info() method. This is the recommended way to create a DWARFInfo instance. ```python from elftools.elf.elffile import ELFFile with open('program.elf', 'rb') as f: elffile = ELFFile(f) dwarfinfo = elffile.get_dwarf_info() ``` -------------------------------- ### Get Machine Architecture Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Retrieves a human-readable name for the machine architecture based on the e_machine field in the ELF header. Examples include 'x86', 'x64', 'ARM', and 'MIPS'. ```python def get_machine_arch(self) -> str: ``` -------------------------------- ### Custom Stream Loader Example Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Implement a custom loader function that takes a relative path and returns a binary stream. This is useful for `ELFFile.stream_loader` when loading supplementary files. ```python def my_loader(relative_path: str) -> IO[bytes]: return open(relative_path, 'rb') elffile = ELFFile(stream, stream_loader=my_loader) ``` -------------------------------- ### Example Usage of DebugSectionDescriptor Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Instantiate DebugSectionDescriptor with section data, name, offset, size, and address to represent a DWARF debug section. ```python from elftools.dwarf.dwarfinfo import DebugSectionDescriptor from io import BytesIO debug_sec = DebugSectionDescriptor( stream=BytesIO(data), name='.debug_info', global_offset=0x1000, size=len(data), address=0 ) ``` -------------------------------- ### Container Access Examples Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Demonstrates accessing fields within a container object using both bracket and dot notation. Containers are dictionary-like objects returned by construct parsing. ```python container['field_name'] # Bracket notation container.field_name # Dot notation (if field_name is valid identifier) ``` ```python header = container print(header['e_type']) # Bracket access print(header.e_type) # Dot access (same thing) for key in header: print(f"{key}: {header[key]}") ``` -------------------------------- ### GNUHashTable Constructor Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Hash.md Initializes a GNUHashTable object. Requires the ELF file object, the starting offset of the hash table, and the symbol table. ```python def __init__( self, elffile: ELFFile, start_offset: int, symboltable: _SymbolTable, ) -> None: ``` -------------------------------- ### Iterate and Print Relocation Details Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Dynamic.md An example demonstrating how to iterate through relocation entries in a relocation table and print their offset, type, symbol index, and addend if available. This showcases the usage of dictionary-like access and the `is_RELA` method. ```python for reloc in reloc_table.iter_relocations(): print(f"Offset: {hex(reloc['r_offset'])}") print(f"Type: {reloc['r_info']['type']}") print(f"Symbol: {reloc['r_info']['sym_value']}") if reloc.is_RELA(): print(f"Addend: {reloc['r_addend']}") ``` -------------------------------- ### Iterating through Compile Units Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md This example shows how to iterate through all compilation units (CUs) in a DWARFInfo object and retrieve the top-level DIE for each CU. It then prints the full path of the top DIE. ```python for CU in dwarfinfo.iter_CUs(): top_die = CU.get_top_DIE() print(f"CU: {top_die.get_full_path()}") ``` -------------------------------- ### Accessing Compile Unit Header Fields Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md This example shows how to access individual fields of the Compile Unit header using dictionary-like access. It retrieves the DWARF version, unit length, and debug abbrev offset. ```python cu_version = CU['version'] cu_length = CU['unit_length'] abbrev_offset = CU['debug_abbrev_offset'] ``` -------------------------------- ### DWARFInfo Caching Example Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/configuration.md Demonstrates how DWARFInfo internally caches various components like compile units, abbreviation tables, line programs, and type units. Caches are created on-demand and cleared upon object destruction. ```python dwarfinfo = elffile.get_dwarf_info() # These operations use caching: # - CU lookup and iteration (parsed CUs cached) # - Abbreviation table lookups (cached by offset) # - Line program lookups (cached by offset) # - Type unit lookups (indexed by signature) ``` -------------------------------- ### Handle ELF Relocation Errors Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Example of catching `ELFRelocationError` when issues arise during the retrieval or processing of relocation entries in an ELF file. ```python from elftools.elf.relocation import RelocationHandler try: handler = RelocationHandler(elffile) relocations = handler.get_relocations_at_offset(0x1000) except ELFRelocationError as e: print(f"Relocation error: {e}") ``` -------------------------------- ### Section Caching Example Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/configuration.md Illustrates that sections parsed from headers are cached. Subsequent calls to get_section with the same index will return the same section object. ```python # Sections parsed from headers are cached: section = elffile.get_section(0) section_again = elffile.get_section(0) # Same object returned ``` -------------------------------- ### GNUHashTable Constructor Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Hash.md Creates a GNU hash table object. It requires the ELF file object, the starting offset of the hash table within the file, and the symbol table. ```APIDOC ## GNUHashTable Constructor ### Description Creates a GNU hash table object. ### Parameters #### Path Parameters - **elffile** (ELFFile) - Required - The ELF file. - **start_offset** (int) - Required - File offset where hash table begins. - **symboltable** (_SymbolTable) - Required - Symbol table with get_symbol(index) method. ``` -------------------------------- ### Get Symbol by Name using ELFHashTable Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Hash.md Demonstrates how to retrieve a symbol by its name using the get_symbol method of an ELFHashTable. This is more efficient than a linear search. Ensure the hash table is obtained from the DynamicSegment. ```python from elftools.elf.hash import ELFHashTable # Using hash table from DynamicSegment hash_table = dynamic_segment.get_hash_table(elffile) if hash_table: symbol = hash_table.get_symbol('printf') if symbol: print(f"Found printf at {hex(symbol['st_value'])}") ``` -------------------------------- ### Handle General ELF File Errors Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Example of catching a general `ELFError` when opening or parsing an ELF file. This is useful for validating the basic integrity of an ELF file. ```python from elftools.common.exceptions import ELFError try: with open('file.elf', 'rb') as f: elffile = ELFFile(f) except ELFError as e: print(f"Invalid ELF file: {e}") ``` -------------------------------- ### line_program_for_CU Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves the line program for a given compile unit, which maps source file locations to instruction addresses. Includes an example of iterating through line program entries. ```APIDOC ## line_program_for_CU ### Description Retrieves the line program for a compile unit, which maps between source file locations and instruction addresses. ### Method `line_program_for_CU(self, CU: CompileUnit) -> LineProgram | None` ### Parameters #### Path Parameters - **CU** (CompileUnit) - Required - The compile unit to get line program for ### Returns - **LineProgram | None** - LineProgram object, or None if CU doesn't point to a line program. ### Example ```python for CU in dwarfinfo.iter_CUs(): lineprogram = dwarfinfo.line_program_for_CU(CU) if lineprogram: for entry in lineprogram.get_entries(): if entry.state: print(f"File {entry.state.file}: Line {entry.state.line}") ``` ``` -------------------------------- ### Get DWARFInfo Skipping Relocation Application Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/configuration.md Retrieve DWARF information, skipping the relocation processing step. This can speed up parsing if sections are already relocated or if relocation is not needed. ```python # For pre-relocated sections or to speed up parsing dwarfinfo = elffile.get_dwarf_info( relocate_dwarf_sections=False, # Skip relocation processing follow_links=True ) ``` -------------------------------- ### Get DWARFInfo Without Following External Links Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/configuration.md Retrieve DWARF information from the ELF file, explicitly disabling the loading of external DWARF files via links like .gnu_debuglink. Relocation processing is enabled by default. ```python # Get DWARF without following external links dwarfinfo = elffile.get_dwarf_info( relocate_dwarf_sections=True, follow_links=False # Ignore external DWARF ) ``` -------------------------------- ### Get String from .debug_line_str Table (DWARF 5) Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Access null-terminated strings from the .debug_line_str section (introduced in DWARF 5) with get_string_from_linetable. Specify the byte offset. Returns bytes or None for invalid offsets. ```python def get_string_from_linetable(self, offset: int) -> bytes | None ``` -------------------------------- ### Build readelf from Binutils Git Source: https://github.com/eliben/pyelftools/blob/main/test/external_tools/README.txt Instructions for building the readelf utility from the Binutils Git repository. Ensure you are on a 64-bit Ubuntu machine and follow the configure and make steps. ```bash git fetch --all --tags git checkout binutils--release Run configure, then make ``` -------------------------------- ### Get Section Index by Name Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Gets the zero-based index of a section by name. Returns None if the section is not found. ```python def get_section_index(self, section_name: str) -> int | None: ``` -------------------------------- ### Accessing DW_AT_name Attribute Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Example of how to access and print details of the DW_AT_name attribute from a DIE. ```python attr = die.attributes['DW_AT_name'] print(attr.name) # 'DW_AT_name' print(attr.form) # 'DW_FORM_strp' print(attr.value) # The actual name string print(attr.raw_value) # Offset into .debug_str print(attr.offset) # Position in .debug_info ``` -------------------------------- ### Load ELF with Full Configuration and External DWARF Support Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/configuration.md This snippet demonstrates how to load an ELF file with full configuration, enabling stream loading for supplementary files and external DWARF support. It checks basic ELF properties and processes DWARF information if available. ```python from elftools.elf.elffile import ELFFile import os def load_elf_fully(path): """Load ELF with full configuration and external DWARF support.""" # Create stream loader for supplementary files base_dir = os.path.dirname(os.path.abspath(path)) def stream_loader(rel_path): full_path = os.path.join(base_dir, rel_path) return open(full_path, 'rb') # Open ELF with stream loader with open(path, 'rb') as f: elffile = ELFFile(f, stream_loader=stream_loader) # Check basic ELF properties print(f"ELF Class: {elffile.elfclass}-bit") print(f"Endianness: {'Little' if elffile.little_endian else 'Big'}") print(f"Type: {elffile['e_type']}") # Get DWARF with all options if elffile.has_dwarf_info(): dwarfinfo = elffile.get_dwarf_info( relocate_dwarf_sections=True, # Apply relocations follow_links=True # Load external DWARF ) print(f"DWARF Info: Available") # Process DWARF cu_count = 0 for CU in dwarfinfo.iter_CUs(): cu_count += 1 print(f"Compile Units: {cu_count}") else: print("DWARF Info: Not available") # Usage load_elf_fully('/usr/bin/ls') ``` -------------------------------- ### Get Address Ranges Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves address ranges from the .debug_aranges section. This enables address-to-CU (Compilation Unit) lookups. ```python def get_aranges(self) -> ARanges | None: # Returns address ranges from .debug_aranges section, enabling address-to-CU lookup. # **Returns**: ARanges object, or None if section doesn't exist. ``` -------------------------------- ### Get Abbreviation Table Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves an abbreviation table from the .debug_abbrev section using its byte offset. Tables are cached internally. ```python def get_abbrev_table(self, offset: int) -> AbbrevTable ``` -------------------------------- ### Get Extended Section Index for Symbol Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Retrieves the extended section index for a given symbol index 'n' in a SymbolTableIndexSection. ```python def get_section_index(self, n: int) -> int: ``` -------------------------------- ### Initialize ELFFile with Stream Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/configuration.md Instantiate ELFFile with a binary stream. The stream_loader parameter is optional and used for loading supplementary DWARF files. ```python from elftools.elf.elffile import ELFFile elffile = ELFFile( stream=open('file.elf', 'rb'), stream_loader=None # Optional ) ``` -------------------------------- ### Symbol Lookup Optimization with Hash Table Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/configuration.md Demonstrates how to optimize symbol lookup in stripped binaries by using the hash table provided by the DynamicSegment, which offers O(1) lookup time. ```python from elftools.elf.dynamic import DynamicSegment dwarfinfo = elffile.get_dwarf_info() # Use hash table if available (O(1) lookup) for segment in elffile.iter_segments(type='PT_DYNAMIC'): if isinstance(segment, DynamicSegment): hash_table = segment.get_hash_table(elffile) if hash_table: symbol = hash_table.get_symbol('printf') # Fast break ``` -------------------------------- ### Get Segment Data Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Segment.md Retrieve the raw byte data for a specific ELF segment. Requires an existing Segment object. ```python segment = elffile.get_segment(0) segment_bytes = segment.data() ``` -------------------------------- ### DWARFInfo Constructor Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Initializes a DWARFInfo context object. This constructor is usually called internally by ELFFile.get_dwarf_info() and not directly by users. ```APIDOC ## DWARFInfo Constructor ### Description Creates a DWARFInfo context. Typically called by ELFFile.get_dwarf_info() rather than directly. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **config** (DwarfConfig) - Required - Configuration with endianness, machine architecture, and address size - **debug_info_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_info section - **debug_aranges_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_aranges section - **debug_abbrev_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_abbrev section - **debug_frame_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_frame section - **eh_frame_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .eh_frame section - **debug_str_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_str section - **debug_loc_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_loc section - **debug_ranges_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_ranges section - **debug_line_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_line section - **debug_pubtypes_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_pubtypes section - **debug_pubnames_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_pubnames section - **debug_addr_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_addr section - **debug_str_offsets_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_str_offsets section - **debug_line_str_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_line_str section - **debug_loclists_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_loclists section - **debug_rnglists_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_rnglists section - **debug_sup_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_sup section - **gnu_debugaltlink_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .gnu.debugaltlink section - **debug_types_sec** (DebugSectionDescriptor | None) - Optional - Descriptor for the .debug_types section ### Request Example ```python from elftools.elf.elffile import ELFFile with open('program.elf', 'rb') as f: elffile = ELFFile(f) dwarfinfo = elffile.get_dwarf_info() ``` ### Response #### Success Response (200) None #### Response Example None ``` -------------------------------- ### Build llvm-dwarfdump with CMake Source: https://github.com/eliben/pyelftools/blob/main/test/external_tools/README.txt Steps to build the llvm-dwarfdump utility using CMake. This process involves cloning the LLVM project, configuring the build with specific CMake options, and then building the target. ```bash git clone https://github.com/llvm/llvm-project.git llvm cd llvm cmake -S llvm -B build -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release cmake --build build -- llvm-dwarfdump ``` -------------------------------- ### Build Address-to-Line Map Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md Builds a dictionary mapping memory addresses to their corresponding source code locations (file, line, column). This is useful for debugging and code analysis. Requires an ELF file with DWARF information. ```python from elftools.elf.elffile import ELFFile def build_address_to_line_map(elfpath): """Build a dictionary mapping addresses to source locations.""" mapping = {} with open(elfpath, 'rb') as f: elffile = ELFFile(f) if not elffile.has_dwarf_info(): return mapping dwarfinfo = elffile.get_dwarf_info() for CU in dwarfinfo.iter_CUs(): lineprogram = dwarfinfo.line_program_for_CU(CU) if not lineprogram: continue files = lineprogram.get_file_list() dirs = lineprogram.get_directory_list() for entry in lineprogram.get_entries(): if entry.state and not entry.state.end_sequence: state = entry.state # Get file and directory if 0 < state.file <= len(files): file_entry = files[state.file - 1] file_name = file_entry.name dir_idx = file_entry.dir_index if dir_idx > 0 and dir_idx <= len(dirs): dir_name = dirs[dir_idx - 1] else: dir_name = dirs[0] # Compilation directory else: continue address = state.address line = state.line column = state.column mapping[address] = { 'file': file_name, 'dir': dir_name, 'line': line, 'column': column, } return mapping # Usage mapping = build_address_to_line_map('program') if 0x400550 in mapping: loc = mapping[0x400550] print(f"{loc['dir']}/{loc['file']}:{loc['line']}:{loc['column']}") ``` -------------------------------- ### Handle ELF Parsing Errors Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Example of catching `ELFParseError` when a specific section within an ELF file is found to be corrupted or invalid. ```python try: section = elffile.get_section(0) except ELFParseError as e: print(f"Corrupted section: {e}") ``` -------------------------------- ### Get Public Types Lookup Table Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves a lookup table for type information from the .debug_pubtypes section. Useful for type-specific lookups. ```python def get_pubtypes(self) -> NameLUT | None: # Returns a lookup table from the .debug_pubtypes section for type lookups. # **Returns**: NameLUT object, or None if section doesn't exist. ``` -------------------------------- ### Get Number of Sections Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Returns the number of sections in the ELF file. Handles the special case where section count exceeds 0xff00. ```python def num_sections(self) -> int: ``` -------------------------------- ### Create ELFFile from Stream Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Instantiate ELFFile by providing a binary stream containing ELF data. Ensure the stream is seekable. This constructor can also accept an optional stream_loader for handling external DWARF links. ```python from elftools.elf.elffile import ELFFile with open('program.elf', 'rb') as f: elffile = ELFFile(f) print(f"ELF class: {elffile.elfclass}-bit") print(f"Little endian: {elffile.little_endian}") ``` -------------------------------- ### Get Interpreter Name from Segment Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Segment.md Extract the interpreter path string from a PT_INTERP segment. This is typically the dynamic linker's path. ```python for segment in elffile.iter_segments(type='PT_INTERP'): assert isinstance(segment, InterpSegment) interp = segment.get_interp_name() print(f"Interpreter: {interp}") ``` -------------------------------- ### ELFFile.load_from_path Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Creates an ELFFile instance from a local filesystem path. This method automatically sets up a stream_loader for resolving external DWARF files. ```APIDOC ## ELFFile.load_from_path ### Description Creates an ELFFile instance from a local filesystem path. This method automatically sets up a stream_loader for resolving external DWARF files. ### Method `load_from_path` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **path** (str | bytes) - Required - Local filesystem path to the ELF file ### Returns ELFFile instance with stream_loader configured. ### Example ```python elffile = ELFFile.load_from_path('/usr/bin/ls') ``` ``` -------------------------------- ### Get Public Names Lookup Table Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves a lookup table for globally-scoped names from the .debug_pubnames section. Use this for fast name-based lookups. ```python def get_pubnames(self) -> NameLUT | None: # Returns a lookup table from the .debug_pubnames section, allowing fast name-based lookup of globally-scoped names. # **Returns**: NameLUT object mapping names to CU/DIE offsets, or None if section doesn't exist. ``` -------------------------------- ### Get Exception Handling CFI Entries Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves all exception handling CFI entries from the .eh_frame section. Throws DWARFError if the section does not exist. ```python def EH_CFI_entries(self) -> list[CFIEntry | ZERO] ``` -------------------------------- ### Create ELFFile from Path Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Use the class method load_from_path to create an ELFFile instance directly from a filesystem path. This method automatically configures a stream_loader for resolving external DWARF files. ```python elffile = ELFFile.load_from_path('/usr/bin/ls') ``` -------------------------------- ### Get Full Path of DIE Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md Retrieves the fully-qualified name of a DIE by combining DW_AT_name attributes up the tree. This is particularly useful for identifying files and functions. ```python for die in CU.iter_DIEs(): if die.tag == 'DW_TAG_variable': print(f"Variable: {die.get_full_path()}") ``` -------------------------------- ### Initialize SymbolTableSection Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Constructor for SymbolTableSection, used for sections of type SHT_SYMTAB or SHT_DYNSYM. Requires the section header, name, parent ELF file, and an associated string table for symbol names. ```python def __init__( self, header: Container, name: str, elffile: ELFFile, stringtable: StringTableSection, ) -> None: ``` -------------------------------- ### Iterate and Print Relocation Details Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Iterates through relocations in a section and prints their offset, type, and symbol value. Requires the elffile object and a section name. ```python for reloc in elffile.get_section_by_name('.rel.text').iter_relocations(): print(f"Offset: {hex(reloc['r_offset'])}") print(f"Type: {reloc['r_info']['type']}") print(f"Symbol: {reloc['r_info']['sym_value']}") ``` -------------------------------- ### Get Number of Relocations Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Retrieves the total count of relocation entries within a relocation section. This method is useful for understanding the size of the relocation data. ```python def num_relocations(self) -> int: return self.num_relocations() ``` -------------------------------- ### get_ehabi_infos Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Retrieves ARM exception handling information from all .ARM.exidx sections within the ELF file. It returns a list of EHABIInfo objects. ```APIDOC ## get_ehabi_infos ### Description Retrieves ARM exception handling information from all .ARM.exidx sections. ### Method ```python def get_ehabi_infos(self) -> list[EHABIInfo] | None ``` ### Returns - list[EHABIInfo] | None: List of EHABIInfo objects, or None if no EHABI sections found. ### Throws - AssertionError: If the file is relocatable (ET_REL), as these are not currently supported. ``` -------------------------------- ### Get String from StringTableSection Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Retrieves a null-terminated string at a specific byte offset within a string table section. Ensure the section is of type SHT_STRTAB. ```python strtab = elffile.get_section_by_name('.strtab') name = strtab.get_string(12) # Get string at offset 12 ``` -------------------------------- ### Handle DWARF Parsing Errors Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Example of catching DWARFError during DWARF information parsing. Use when .debug_info or .debug_abbrev sections might be corrupted or references are invalid. ```python from elftools.common.exceptions import DWARFError try: dwarfinfo = elffile.get_dwarf_info() for CU in dwarfinfo.iter_CUs(): top_die = CU.get_top_DIE() except DWARFError as e: print(f"DWARF parsing error: {e}") ``` -------------------------------- ### Get Specific Relocation Entry Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Retrieves a single relocation entry from the section by its zero-based index. Use this when you need to access a particular relocation without iterating through all of them. ```python def get_relocation(self, n: int) -> Relocation: return self.get_relocation(n) ``` -------------------------------- ### Get Symbol Count from SymbolTableSection Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Returns the total number of symbol entries present in the symbol table section. Useful for iterating or accessing symbols by index. ```python symtab = elffile.get_section_by_name('.symtab') print(f"Symbol count: {symtab.num_symbols()}") ``` -------------------------------- ### ARangeEntry Structure Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ARanges.md Defines the structure of an ARangeEntry, which holds information about a single address range, including its start address, length, and associated compile unit details. ```python class ARangeEntry(NamedTuple): begin_addr: int # Starting address of the range length: int # Length of the range in bytes info_offset: int # Offset of corresponding CU in .debug_info unit_length: int # Total size of the CU version: int # ARANGE version address_size: int # Address size in bytes (4 or 8) segment_size: int # Segment size in bytes (usually 0) ``` -------------------------------- ### Iterate Through Line Program Entries Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md This snippet demonstrates how to iterate through all entries in a LineProgram object and print the file, line, and address for each state change. Ensure you have a valid DWARF information object and a compilation unit. ```python lineprogram = dwarfinfo.line_program_for_CU(cu) if lineprogram: for entry in lineprogram.get_entries(): if entry.state: state = entry.state print(f"File {state.file} Line {state.line}: {hex(state.address)}") ``` -------------------------------- ### Iterating Over ELF Sections and Symbols Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/README.md Shows how to iterate over collections like ELF sections and symbols efficiently. The iteration process parses elements one at a time, avoiding the need to load the entire collection into memory. ```python for section in elffile.iter_sections(): # Sections parsed one at a time for symbol in symtab.iter_symbols(): # Symbols parsed one at a time for die in cu.iter_DIEs(): # DIEs parsed one at a time ``` -------------------------------- ### Iterating Through ARanges Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ARanges.md Demonstrates how to retrieve and iterate through ARange entries from DWARF information to print address range details and compile unit offsets. ```python aranges = dwarfinfo.get_aranges() for entry in aranges.entries: print(f"Range: {hex(entry.begin_addr)}-{hex(entry.begin_addr + entry.length)}") print(f" CU offset: {hex(entry.info_offset)}") print(f" CU size: {entry.unit_length}") ``` -------------------------------- ### Retrieve ARM EHABI Information Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Fetches ARM exception handling details from all .ARM.exidx sections. Returns a list of EHABIInfo objects or None if no such sections exist. Note that relocatable files (ET_REL) are not supported and will raise an AssertionError. ```python def get_ehabi_infos(self) -> list[EHABIInfo] | None: ``` -------------------------------- ### ELFFile Constructor Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Creates an ELFFile object from a binary stream. This is the primary way to parse ELF data directly from an open file or byte stream. ```APIDOC ## ELFFile Constructor ### Description Creates an ELFFile object from a binary stream. This is the primary way to parse ELF data directly from an open file or byte stream. ### Method `__init__` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **stream** (IO[bytes]) - Required - Binary stream containing ELF file data (must be seekable) - **stream_loader** (Callable[[str], IO[bytes]] | None) - Optional - Function that takes a relative path string and returns a stream for loading supplementary object files (used for external DWARF links) ### Throws `ELFError`, `ELFParseError` if the stream does not contain valid ELF data. ### Example ```python from elftools.elf.elffile import ELFFile with open('program.elf', 'rb') as f: elffile = ELFFile(f) print(f"ELF class: {elffile.elfclass}-bit") print(f"Little endian: {elffile.little_endian}") ``` ``` -------------------------------- ### Retrieve DIE from Lookup Table Entry Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Use get_DIE_from_lut_entry to get a DIE referenced by an entry from a pubnames or pubtypes lookup table. The lut_entry parameter should be a NameLUTEntry object. ```python def get_DIE_from_lut_entry(self, lut_entry: NameLUTEntry) -> DIE ``` -------------------------------- ### Dictionary-like Access to ELF and DWARF Data Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/README.md Illustrates how ELF structures and DWARF Debugging Information Entries (DIEs) support dictionary-like bracket notation for accessing fields and attributes. This provides a convenient way to retrieve specific data points. ```python elf_type = elffile['e_type'] section_type = section['sh_type'] attribute_value = die.attributes['DW_AT_name'].value ``` -------------------------------- ### Get DIE from Attribute Reference Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md Fetches the DIE referenced by a reference-class attribute, handling various reference forms. This is essential for resolving relationships between DIEs, such as variable types. ```python if 'DW_AT_type' in die.attributes: type_die = die.get_DIE_from_attribute('DW_AT_type') print(f"Variable type: {type_die.tag}") ``` -------------------------------- ### Create Relative File Loader Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Returns a function that resolves relative paths against a base directory and opens files, with security checks to prevent path traversal attacks. Use this to safely load files relative to a known directory. ```python @staticmethod def make_relative_loader(base_path: str) -> Callable[[str], IO[bytes]] ``` -------------------------------- ### Recover from Missing External DWARF File Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Handles ELFError when an external DWARF file referenced by follow_links=True is not found. Falls back to using local DWARF information. ```python try: dwarfinfo = elffile.get_dwarf_info(follow_links=True) except ELFError: # Fall back to local DWARF only dwarfinfo = elffile.get_dwarf_info(follow_links=False) ``` -------------------------------- ### __getitem__ Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Provides dictionary-like access to ELF header fields. This allows direct retrieval of header values using their field names as keys. ```APIDOC ## __getitem__ (Dictionary-like Access) ### Description Allows accessing ELF header fields directly via dictionary syntax. Maps to header field values. ### Method ```python def __getitem__(self, name: str) -> Any ``` ### Parameters #### Path Parameters - **name** (str) - Required - The name of the ELF header field to access (e.g., 'e_type', 'e_machine', 'e_entry'). ### Example ```python elf_type = elffile['e_type'] # 'ET_EXEC', 'ET_DYN', etc. machine = elffile['e_machine'] # 'EM_X86_64', 'EM_ARM', etc. entry_point = elffile['e_entry'] # Entry point address ``` ``` -------------------------------- ### DwarfConfig Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Configuration for DWARF parsing, specifying endianness, machine architecture, and default address size. ```APIDOC ## DwarfConfig ### Description Configuration for DWARF parsing. ### Fields - **little_endian** (bool) - Target uses little-endian byte order - **machine_arch** (str) - Machine architecture string (e.g., 'x86', 'x64', 'ARM') - **default_address_size** (int) - Default address size in bytes (4 or 8) ``` -------------------------------- ### Get Call Frame Information Entries Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves all Call Frame Information (CFI) entries from the .debug_frame section, used for stack unwinding. Throws DWARFError if the section does not exist. ```python def CFI_entries(self) -> list[CFIEntry | ZERO] ``` -------------------------------- ### Access ELF Header Fields via Dictionary Syntax Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Allows direct access to ELF header fields using dictionary-like syntax. This is useful for quickly retrieving specific header values such as the ELF type, machine type, or entry point address. ```python def __getitem__(self, name: str) -> Any: ``` ```python elf_type = elffile['e_type'] # 'ET_EXEC', 'ET_DYN', etc. machine = elffile['e_machine'] # 'EM_X86_64', 'EM_ARM', etc. entry_point = elffile['e_entry'] # Entry point address ``` -------------------------------- ### Get String from .debug_str Table Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieve a null-terminated string from the .debug_str section using get_string_from_table. Provide the byte offset into the section. Returns bytes or None if the offset is invalid. ```python def get_string_from_table(self, offset: int) -> bytes | None ``` -------------------------------- ### Get Symbol by Index from SymbolTableSection Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Retrieves a specific symbol object from the symbol table using its zero-based index. This is useful for direct access when the symbol's position is known. ```python symbol = symtab.get_symbol(5) print(f"Symbol: {symbol.name} at {hex(symbol['st_value'])}") ``` -------------------------------- ### get_prologue_length Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md Returns the size of the line program's prologue in bytes, which contains metadata before the main sequence of line number instructions. ```APIDOC ## get_prologue_length ### Description Returns the size of the line program prologue in bytes. ### Method ```python def get_prologue_length(self) -> int ``` ### Returns Prologue size. ``` -------------------------------- ### Iterate and Print Line Program Entries Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Iterates through compile units, retrieves their line programs, and prints file and line information for each entry with state. ```python for CU in dwarfinfo.iter_CUs(): lineprogram = dwarfinfo.line_program_for_CU(CU) if lineprogram: for entry in lineprogram.get_entries(): if entry.state: print(f"File {entry.state.file}: Line {entry.state.line}") ``` -------------------------------- ### Handle ELF Section Decompression Errors Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Example of catching `ELFCompressionError` when a section's data cannot be decompressed, which might happen if the section is marked as compressed but the data is corrupted or the compression type is unsupported. ```python try: data = section.data() # Automatically decompresses if needed except ELFCompressionError as e: print(f"Failed to decompress section: {e}") ``` -------------------------------- ### Read External DWARF Link Section Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Reads the .gnu_debuglink section, returning its filename and checksum if present. Returns None if the section does not exist. ```python debuglink_data = elffile.get_dwarf_link() if debuglink_data: print(f"Filename: {debuglink_data.filename.decode()}, Checksum: {debuglink_data.checksum}") ``` -------------------------------- ### Accessing Symbol Properties Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Demonstrates how to access various properties of a symbol object, including its name, value, size, and binding type. Requires a pre-existing symbol table and a symbol retrieved by index. ```python symbol = symtab.get_symbol(0) print(f"Name: {symbol.name}") print(f"Value: {hex(symbol['st_value'])}") print(f"Size: {symbol['st_size']}") print(f"Binding: {symbol['st_info']['bind']}") print(f"Type: {symbol['st_info']['type']}") ``` -------------------------------- ### Get Line Program for Compile Unit Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves the line program for a given compile unit, which maps source locations to instruction addresses. Returns None if the compile unit does not point to a line program. ```python def line_program_for_CU(self, CU: CompileUnit) -> LineProgram | None ``` -------------------------------- ### get_file_list Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md Fetches the list of source files referenced by the line program, allowing lookup of file names by index. ```APIDOC ## get_file_list ### Description Returns the list of source files referenced by this line program. File index 1 is the first file, 0 is undefined. ### Method ```python def get_file_list(self) -> list[LineProgramFile] ``` ### Returns List of LineProgramFile objects with 'name' and optional 'dir_index' fields. ### Example ```python files = lineprogram.get_file_list() for idx, file_entry in enumerate(files): print(f"File {idx}: {file_entry.name}") ``` ``` -------------------------------- ### Get Section Data - pyelftools Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Retrieve the complete data for an ELF section. Handles decompression automatically if the section is compressed. For SHT_NOBITS sections, it returns zero-filled bytes. Ensure the section is valid before calling. ```python section = elffile.get_section_by_name('.text') code_bytes = section.data() ``` -------------------------------- ### Create Stream Loader for Supplementary DWARF Files Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/configuration.md A stream loader function can be created to resolve and open supplementary DWARF files based on a base directory. This is used when the ELFFile is initialized with a stream_loader. ```python import os def make_stream_loader(base_dir): """Create a stream loader for resolving supplementary files.""" def loader(rel_path): full_path = os.path.join(base_dir, rel_path) return open(full_path, 'rb') return loader base_dir = os.path.dirname('path/to/program') with open('path/to/program', 'rb') as f: elffile = ELFFile(f, stream_loader=make_stream_loader(base_dir)) if elffile.has_dwarf_info(): dwarfinfo = elffile.get_dwarf_info(follow_links=True) ``` -------------------------------- ### Load Supplementary DWARF Information Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Loads supplementary DWARF information from external files referenced by specific sections. Requires an existing DWARFInfo object. ```python supplementary_dwarfinfo = elffile.get_supplementary_dwarfinfo(dwarfinfo) ``` -------------------------------- ### Get Compilation Unit Offset by Address Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ARanges.md Use `cu_offset_at_addr` to find the offset of the compilation unit containing a specific instruction address. This is useful for locating debug information associated with a given memory location. ```python dwarfinfo = elffile.get_dwarf_info() aranges = dwarfinfo.get_aranges() if aranges: # Find which CU contains address 0x400550 cu_offset = aranges.cu_offset_at_addr(0x400550) if cu_offset is not None: cu = dwarfinfo.get_CU_at(cu_offset) top_die = cu.get_top_DIE() print(f"Address is in CU: {top_die['DW_AT_name'].value}") ``` -------------------------------- ### Basic ELF File Analysis Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/README.md Access ELF header information, iterate through sections, and list segments of an ELF file. Requires opening the ELF file in binary read mode. ```python from elftools.elf.elffile import ELFFile with open('program.elf', 'rb') as f: elffile = ELFFile(f) # Access ELF header print(f"Entry point: {hex(elffile['e_entry'])}") print(f"Class: {elffile.elfclass}-bit") # Iterate sections for section in elffile.iter_sections(): print(f"Section: {section.name} ({section['sh_type']})") # Iterate segments for segment in elffile.iter_segments(): print(f"Segment: {segment['p_type']} at {hex(segment['p_vaddr'])}") ``` -------------------------------- ### Properties Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Hash.md Provides access to the parameters of the hash table. ```APIDOC ## Properties ### params - **params** (Container) - Hash table parameters. ``` -------------------------------- ### Catching Specific ELF and DWARF Errors Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Demonstrates how to catch specific exceptions like ELFParseError, DWARFError, and the general ELFError when parsing ELF files and their DWARF information. This allows for targeted error handling. ```python from elftools.elf.elffile import ELFFile from elftools.common.exceptions import ELFError, DWARFError with open('file.elf', 'rb') as f: try: elffile = ELFFile(f) if elffile.has_dwarf_info(): dwarfinfo = elffile.get_dwarf_info() for CU in dwarfinfo.iter_CUs(): top_die = CU.get_top_DIE() except ELFParseError as e: print(f"ELF structure error: {e}") except DWARFError as e: print(f"DWARF parsing error: {e}") except ELFError as e: print(f"Other ELF error: {e}") ``` -------------------------------- ### Accessing ELF and DWARF Enums in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Demonstrates how to import and use ELF enums like `ENUM_E_TYPE` and `ENUM_SH_TYPE` from `elftools.elf.enums`. It shows how to perform both forward (name to integer) and reverse (integer to name) lookups using these enum objects. ```python from elftools.elf.enums import ENUM_E_TYPE, ENUM_SH_TYPE elf_types = ENUM_E_TYPE # Maps int values to type names section_types = ENUM_SH_TYPE # Maps int values to section type names # Enums support both forward and reverse lookup print(section_types['SHT_PROGBITS']) # Get numeric value print(section_types[1]) # Get name string ``` -------------------------------- ### Accessing ARanges via DWARFInfo Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ARanges.md Retrieve the ARanges table from DWARFInfo and find the compilation unit associated with a given address. This snippet demonstrates how to get the CU offset and the CU object itself, or fall back to manually iterating CUs if ARanges are not available. ```python dwarfinfo = elffile.get_dwarf_info() aranges = dwarfinfo.get_aranges() if aranges: cu_offset = aranges.cu_offset_at_addr(addr) cu = dwarfinfo.get_CU_at(cu_offset) # Now have the CU containing the address else: # No aranges available # Iterate CUs and check ranges manually cu = dwarfinfo.get_CU_containing(addr) ```