### 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 ``` -------------------------------- ### Install pyelftools Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Install the library using pip. Requires Python 3.10+. ```bash pip install pyelftools ``` -------------------------------- ### Get Full Path Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DIE.md Construct the full source path by combining DW_AT_comp_dir and DW_AT_name attributes. ```python cu_die = cu.get_top_DIE() path = cu_die.get_full_path() print(f"Source: {path}") ``` -------------------------------- ### get_ehabi_infos Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Get ARM exception handler index information. ```APIDOC ## get_ehabi_infos() ### Description Get ARM exception handler index information. Note: currently only supports non-relocatable files. ### Returns List of EHABIInfo objects, or None if no EHABI sections ### Raises - AssertionError: If file is a relocatable object file (ET_REL) ``` -------------------------------- ### Get machine architecture Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Retrieves a human-readable string representing the binary's machine architecture. ```python arch = elf.get_machine_arch() print(f"Binary for: {arch}") ``` -------------------------------- ### Printing ELF Header Fields Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Example of accessing and formatting specific ELF header fields for output. ```python print(f"Machine: {elf['e_machine']}") print(f"Entry: {elf['e_entry']:#x}") print(f"Type: {elf['e_type']}") ``` -------------------------------- ### Traverse DIE Tree in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DIE.md Recursively print the hierarchy of DIEs starting from a given node. ```python def print_die_tree(cu, die, depth=0): indent = " " * depth name_attr = die.attributes.get('DW_AT_name') name = f": {name_attr.value}" if name_attr else "" print(f"{indent}{die.tag}{name}") for child in cu.iter_DIE_children(die): print_die_tree(cu, child, depth + 1) cu = dwarfinfo.get_CU_at(0) top = cu.get_top_DIE() print_die_tree(cu, top) ``` -------------------------------- ### Get external DWARF link Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Reads the .gnu_debuglink section to identify external debug files. ```python link = elf.get_dwarf_link() if link: print(f"External debug file: {link.filename}") ``` -------------------------------- ### Get library name (soname) Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Dynamic.md Retrieves the DT_SONAME tag from the dynamic section. ```python dynamic = elf.get_section_by_name('.dynamic') if dynamic: for tag in dynamic.iter_tags(lambda t: t['d_tag'] == 'DT_SONAME'): print(f"SONAME: {tag.soname}") ``` -------------------------------- ### address_offsets Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Get file offsets corresponding to a memory address range. ```APIDOC ## address_offsets(start: int, size: int = 1) ### Description Get file offsets corresponding to a memory address range. Yields offsets for each PT_LOAD segment containing the address range. ### Parameters - **start** (int) - Required - Starting memory address (virtual address) - **size** (int) - Optional - Size of memory region in bytes ### Returns Iterator yielding file offset integers ``` -------------------------------- ### Get runtime library path Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Dynamic.md Checks for DT_RUNPATH or DT_RPATH tags within the dynamic section. ```python dynamic = elf.get_section_by_name('.dynamic') if dynamic: for tag in dynamic.iter_tags(): if tag['d_tag'] == 'DT_RUNPATH': print(f"Runtime path: {tag.runpath}") break elif tag['d_tag'] == 'DT_RPATH': print(f"RPATH: {tag.rpath}") break ``` -------------------------------- ### Map All Functions from CFI Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CallFrame.md Extract function address ranges from all FDEs and sort them by starting address. ```python cfi = dwarfinfo.get_callframe_info() functions = [] for fde in cfi.iter_FDEs(): functions.append({ 'start': fde.pc_begin, 'end': fde.pc_begin + fde.pc_range, 'size': fde.pc_range, }) # Sort by address functions.sort(key=lambda f: f['start']) print("Functions from CFI:") for func in functions: print(f" {func['start']:#x}-{func['end']:#x} ({func['size']} bytes)") ``` -------------------------------- ### Get address offsets Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Retrieves file offsets for a specific memory address range within PT_LOAD segments. ```python # Find file offsets for code at virtual address 0x1000 for offset in elf.address_offsets(0x1000, size=0x100): print(f"Found at file offset: {offset:#x}") ``` -------------------------------- ### Get entries for a specific line in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md Retrieve line program entries matching a specific filename and line number. ```python for entry in line_program.get_entries_for_line('main.c', 42): print(f"Line 42 maps to address {entry.state.address:#x}") ``` -------------------------------- ### 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 ``` -------------------------------- ### Initialize DWARFInfo Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Constructor for the DWARFInfo class. Typically invoked via ELFFile.get_dwarf_info() instead of direct instantiation. ```python def __init__( self, config: DwarfConfig, debug_info_sec: DebugSectionDescriptor | None, debug_aranges_sec: DebugSectionDescriptor | None, debug_abbrev_sec: DebugSectionDescriptor | None, debug_frame_sec: DebugSectionDescriptor | None, eh_frame_sec: DebugSectionDescriptor | None, debug_str_sec: DebugSectionDescriptor | None, debug_loc_sec: DebugSectionDescriptor | None, debug_ranges_sec: DebugSectionDescriptor | None, debug_line_sec: DebugSectionDescriptor | None, debug_pubtypes_sec: DebugSectionDescriptor | None, debug_pubnames_sec: DebugSectionDescriptor | None, debug_addr_sec: DebugSectionDescriptor | None, debug_str_offsets_sec: DebugSectionDescriptor | None, debug_line_str_sec: DebugSectionDescriptor | None, debug_loclists_sec: DebugSectionDescriptor | None, debug_rnglists_sec: DebugSectionDescriptor | None, debug_sup_sec: DebugSectionDescriptor | None, gnu_debugaltlink_sec: DebugSectionDescriptor | None, debug_types_sec: DebugSectionDescriptor | None, ) -> None ``` -------------------------------- ### Apply relocations to an ELF section Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Relocation.md Demonstrates initializing the handler and applying relocations from a section to a file stream. ```python handler = RelocationHandler(elf) reloc_section = elf.get_section_by_name('.rel.text') if reloc_section: # Get associated symbol table symtab_idx = reloc_section['sh_link'] symtab = elf.get_section(symtab_idx) # Apply relocations (modifies stream) with open(elf_file, 'r+b') as f: applied = handler.apply_relocations(reloc_section, symtab, f) print(f"Applied {len(applied)} relocations") ``` -------------------------------- ### Get Interpreter Path Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Segment.md Extract the interpreter path from a PT_INTERP segment. ```python for segment in elf.iter_segments(type='PT_INTERP'): interp = segment.get_interp_name() print(f"Interpreter: {interp}") ``` -------------------------------- ### DWARFInfo Constructor Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Initializes a new DWARFInfo instance. While it can be called directly, it is typically retrieved via ELFFile.get_dwarf_info(). ```APIDOC ## DWARFInfo.__init__ ### Description Creates a DWARFInfo object to manage access to DWARF debugging sections. This is usually invoked by the library when calling get_dwarf_info() on an ELFFile. ### Parameters - **config** (DwarfConfig) - Required - DWARF parser configuration object. - **debug_*_sec** (DebugSectionDescriptor | None) - Optional - Descriptors for specific debug sections (e.g., debug_info_sec, debug_line_sec). Pass None if the section is not present in the file. ### Returns - **DWARFInfo** - An instance of the DWARFInfo class. ``` -------------------------------- ### Catch DWARFError during processing Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Example of catching DWARFError when iterating over compilation units. ```python try: dwarfinfo = elf.get_dwarf_info() for CU in dwarfinfo.iter_CUs(): die = CU.get_top_DIE() except DWARFError as e: print(f"DWARF error: {e}") ``` -------------------------------- ### Perform basic ELF file operations Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/00-START-HERE.txt Demonstrates how to initialize an ELFFile object and retrieve specific sections or segments. ```python elf = ELFFile(open('binary', 'rb')) section = elf.get_section_by_name('.symtab') segment = elf.get_segment(0) ``` -------------------------------- ### Initialize Section object Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Constructor signature for creating a Section instance. ```python def __init__( self, header: Container, name: str, elffile: ELFFile ) -> 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 ``` -------------------------------- ### ELFFile Constructor Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Initializes an ELFFile object from a binary stream. This is the primary entry point for accessing ELF file information. ```APIDOC ## ELFFile(stream, stream_loader=None) ### Description Creates an ELFFile object that parses and provides access to an ELF file from a binary stream. ### Parameters - **stream** (IO[bytes]) - Required - A binary stream containing ELF file data. - **stream_loader** (Callable[[str], IO[bytes]] | None) - Optional - Callback function to load supplementary object files. ### Returns - **ELFFile** - An instance of the ELFFile class. ### Raises - **ELFError** - If the stream is not a valid ELF file. - **ELFParseError** - If the ELF header cannot be parsed. ``` -------------------------------- ### Initialize ELFFile from a binary stream Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Construct an ELFFile instance using a file-like object. The stream position is reset to 0 upon initialization. ```python from elftools.elf.elffile import ELFFile # Load an ELF file from a stream with open('myprogram', 'rb') as f: elf = ELFFile(f) print(f"Machine: {elf['e_machine']}") print(f"Type: {elf['e_type']}") print(f"Entry point: {elf['e_entry']:#x}") ``` -------------------------------- ### Retrieve section data alignment Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Access the data_alignment property to get the logical alignment requirement. ```python @property def data_alignment(self) -> int ``` -------------------------------- ### Load and Analyze an ELF File Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/INDEX.md Opens an ELF binary and iterates through its sections to display basic header information. ```python from elftools.elf.elffile import ELFFile with open('binary', 'rb') as f: elf = ELFFile(f) # Basic information print(f"Machine: {elf['e_machine']}") print(f"Type: {elf['e_type']}") # Iterate sections for section in elf.iter_sections(): print(f"Section: {section.name}") ``` -------------------------------- ### Safely Load ELF File Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Use a try-except block with ELFError to catch parsing issues during file initialization. ```python from elftools.common.exceptions import ELFError try: with open('binary', 'rb') as f: elf = ELFFile(f) except ELFError as e: print(f"Error: Cannot parse ELF file: {e}") exit(1) ``` -------------------------------- ### Load ELFFile from a filesystem path Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Use the class method to load an ELF file directly from a path, which automatically configures the stream loader. ```python elf = ELFFile.load_from_path('/usr/bin/ls') ``` -------------------------------- ### Get String from String Table Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Retrieves a specific string from the .strtab section using a byte offset. ```python strtab = elf.get_section_by_name('.strtab') if strtab: # strtab is a StringTableSection string = strtab.get_string(10) # Get string at offset 10 print(f"String: {string}") ``` -------------------------------- ### Retrieve section data size Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Access the data_size property to get the logical size of section data. ```python @property def data_size(self) -> int ``` ```python print(f"Logical size: {section.data_size} bytes") print(f"File size: {section['sh_size']} bytes") ``` -------------------------------- ### List ELF Dependencies Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Iterates through the .dynamic section to identify and print libraries required by the ELF file. ```python dynamic = elf.get_section_by_name('.dynamic') if dynamic: print("Dependencies:") for tag in dynamic.iter_tags(): if tag['d_tag'] == 'DT_NEEDED': # The library name is automatically decoded for DT_NEEDED print(f" {tag.needed}") ``` -------------------------------- ### List All Relocations in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Relocation.md Iterates through all ELF sections to identify and print details for SHT_REL and SHT_RELA relocation types. ```python from elftools.common.exceptions import ELFError for section in elf.iter_sections(): if section['sh_type'] in ('SHT_REL', 'SHT_RELA'): print(f"\n{section.name}:") reloc_type = section['sh_type'] for reloc in section.iter_relocations(): offset = reloc['r_offset'] r_info = reloc['r_info'] # Extract symbol index and type (varies by architecture) if elf.elfclass == 32: sym_idx = r_info >> 8 reloc_type_val = r_info & 0xff else: sym_idx = r_info >> 32 reloc_type_val = r_info & 0xffffffff print(f" {offset:#x}: sym={sym_idx}, type={reloc_type_val}") if reloc_type == 'SHT_RELA': print(f" addend={reloc['r_addend']}") ``` -------------------------------- ### Get Shared Object Name Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Extracts the DT_SONAME tag from the .dynamic section to identify the shared object name. ```python dynamic = elf.get_section_by_name('.dynamic') if dynamic: for tag in dynamic.iter_tags(): if tag['d_tag'] == 'DT_SONAME': print(f"SONAME: {tag.soname}") break ``` -------------------------------- ### get_machine_arch Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Return a human-readable machine architecture string. ```APIDOC ## get_machine_arch() ### Description Return a human-readable machine architecture string based on e_machine header field. ### Returns Architecture name (e.g., 'x86', 'x64', 'ARM') ``` -------------------------------- ### Get Symbol for Relocation in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Relocation.md Retrieves the symbol table associated with a specific relocation section and resolves symbol names for each entry. ```python reloc_section = elf.get_section_by_name('.rel.text') if reloc_section: # Get associated symbol table symtab_idx = reloc_section['sh_link'] symtab = elf.get_section(symtab_idx) for reloc in reloc_section.iter_relocations(): # Extract symbol index if elf.elfclass == 32: sym_idx = reloc['r_info'] >> 8 else: sym_idx = reloc['r_info'] >> 32 symbol = symtab.get_symbol(sym_idx) print(f"Symbol: {symbol.name} at {reloc['r_offset']:#x}") ``` -------------------------------- ### Load an ELF File Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/README.md Initializes an ELFFile object from a binary file stream to access header information. ```python from elftools.elf.elffile import ELFFile with open('binary', 'rb') as f: elf = ELFFile(f) print(f"Machine: {elf['e_machine']}") ``` -------------------------------- ### Initialize DynamicTag Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Dynamic.md Constructor for creating a DynamicTag instance, typically managed by DynamicSection. ```python def __init__( self, entry: Container, stringtable: _StringTable | None, ) -> None ``` -------------------------------- ### Define ELFHashTable and GNUHashTable symbol lookup methods Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Dynamic.md Method signatures for retrieving symbol indices by name from hash tables. ```python def get_symbols_by_name(self, name: str) -> list[int] ``` -------------------------------- ### Retrieve Machine Architecture Strings Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md List of possible machine architecture strings returned by the get_machine_arch() function. ```text 'x86', 'x64', 'ARM', 'ARM64', 'MIPS', 'PPC', 'PPC64', 'SPARC', 'SPARC64', 'S390', 'S390X', 'IA-64', 'HPPA', 'PA-RISC', 'ALPHA', 'RISC-V', 'Motorola 68000', 'Motorola 88000', 'Intel 80860', 'Intel 80960', 'PowerPC', 'MIPS-X', 'Motorola ColdFire', ... ``` -------------------------------- ### List all source files in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md Collect and print all unique source files referenced in the line program, excluding end-of-sequence markers. ```python cu = next(dwarfinfo.iter_CUs()) files = set() line_program = cu.get_top_DIE().dwarfinfo.get_line_program(cu) if line_program: for entry in line_program.iter_lines(): if not entry.state.end_sequence: files.add(entry.state.file) for f in sorted(files): print(f) ``` -------------------------------- ### get_full_path() Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DIE.md Constructs the full path for the DIE using DW_AT_comp_dir and DW_AT_name. ```APIDOC ## def get_full_path(self) -> str ### Description Get the full path for this DIE by joining DW_AT_comp_dir and DW_AT_name. ### Returns - **str** - Path string (may be empty if attributes are missing). ``` -------------------------------- ### Find Code, Data, and BSS Sections Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Iterates through ELF sections to categorize them based on type and flags. ```python # Code sections for section in elf.iter_sections(): if section['sh_type'] == 'SHT_PROGBITS' and section['sh_flags'] & 0x4: print(f"Code: {section.name}") # Data sections for section in elf.iter_sections(): if section['sh_type'] == 'SHT_PROGBITS' and not (section['sh_flags'] & 0x4): print(f"Data: {section.name}") # BSS sections for section in elf.iter_sections(): if section['sh_type'] == 'SHT_NOBITS': print(f"BSS: {section.name}") ``` -------------------------------- ### Initialize CompileUnit Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md Constructor for the CompileUnit object, typically invoked internally by DWARFInfo during iteration. ```python def __init__( self, header: Container, dwarfinfo: DWARFInfo, structs: DWARFStructs, cu_offset: int, cu_die_offset: int, ) -> None ``` -------------------------------- ### get_dwarf_link Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Read the .gnu_debuglink section if present. ```APIDOC ## get_dwarf_link() ### Description Read the .gnu_debuglink section if present. ### Returns Container with 'filename' (bytes) and 'checksum' (int) fields, or None ``` -------------------------------- ### load_from_path Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md A convenience class method to load an ELF file directly from a filesystem path. ```APIDOC ## load_from_path(path) ### Description Convenience method to load an ELF file from a filesystem path, automatically configuring the stream loader for relative path resolution. ### Parameters - **path** (str | bytes) - Required - Filesystem path to the ELF file. ### Returns - **ELFFile** - An instance of the ELFFile class. ``` -------------------------------- ### get_supplementary_dwarfinfo Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Load supplementary DWARF information from linked files. ```APIDOC ## get_supplementary_dwarfinfo(dwarfinfo: DWARFInfo) ### Description Load supplementary DWARF information from linked files (.debug_sup, .gnu_debugaltlink, .gnu_debuglink). ### Parameters - **dwarfinfo** (DWARFInfo) - Required - DWARFInfo object from the main file ### Returns DWARFInfo from supplementary file, or None ``` -------------------------------- ### List shared library dependencies Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Dynamic.md Iterates through DT_NEEDED tags in the .dynamic section to print library dependencies. ```python dynamic = elf.get_section_by_name('.dynamic') if dynamic: print("Dependencies:") for tag in dynamic.iter_tags(lambda t: t['d_tag'] == 'DT_NEEDED'): print(f" {tag.needed}") ``` -------------------------------- ### Import common pyelftools modules Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/00-START-HERE.txt Essential imports for interacting with ELF files and handling library-specific exceptions. ```python from elftools.elf.elffile import ELFFile from elftools.common.exceptions import ELFError, DWARFError ``` -------------------------------- ### Safe ELF Loading Pattern Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Standard pattern for initializing an ELFFile object while handling potential parsing errors. ```python from elftools.elf.elffile import ELFFile from elftools.common.exceptions import ELFError try: with open('binary', 'rb') as f: elf = ELFFile(f) except ELFError as e: print(f"Cannot parse ELF: {e}") exit(1) ``` -------------------------------- ### Iterate Sections Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md List all sections or retrieve a specific section by name. ```python # List all sections for section in elf.iter_sections(): print(f"{section.name:20} {section['sh_type']:15} {section['sh_size']:10d} {section['sh_offset']:#x}") # Get specific section by name symtab = elf.get_section_by_name('.text') if symtab: print(f"Found: {symtab.name}") ``` -------------------------------- ### List ELF Relocations Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Iterates through sections to find SHT_RELA types and prints relocation details including symbol names and addends. ```python for section in elf.iter_sections(): if section['sh_type'] == 'SHT_RELA': print(f"\n{section.name}:") # Get symbol table symtab = elf.get_section(section['sh_link']) for reloc in section.iter_relocations(): # Extract symbol index and type if elf.elfclass == 32: sym_idx = reloc['r_info'] >> 8 reloc_type = reloc['r_info'] & 0xff else: # 64-bit sym_idx = reloc['r_info'] >> 32 reloc_type = reloc['r_info'] & 0xffffffff symbol = symtab.get_symbol(sym_idx) offset = reloc['r_offset'] addend = reloc.get('r_addend', 0) print(f" {offset:#10x} -> {symbol.name:20} (type={reloc_type}, addend={addend:#x})") ``` -------------------------------- ### get_sunw_syminfo() Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Dynamic.md Retrieves the Solaris symbol info section if it exists. ```APIDOC ### Method `get_sunw_syminfo() -> SUNWSyminfoTableSection | None` ### Returns - **SUNWSyminfoTableSection | None** - The Solaris symbol info section if present, otherwise None ``` -------------------------------- ### Extract Function Information in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DIE.md Identify subprogram DIEs and calculate their address ranges based on DW_AT_low_pc and DW_AT_high_pc attributes. ```python cu = next(dwarfinfo.iter_CUs()) for die in cu.iter_DIEs(): if die.tag == 'DW_TAG_subprogram': # Function name name = die.attributes.get('DW_AT_name') func_name = name.value if name else 'unknown' # Function address and size lowpc = die.attributes.get('DW_AT_low_pc') highpc = die.attributes.get('DW_AT_high_pc') if lowpc and highpc: start = lowpc.value # highpc can be absolute address or size depending on form if highpc.form == 'DW_FORM_addr': end = highpc.value else: end = start + highpc.value print(f"{func_name}: {start:#x}-{end:#x}") ``` -------------------------------- ### dwarf_format Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md Returns the DWARF format version (32 or 64-bit). ```APIDOC ## dwarf_format ### Description Get the DWARF format for this CU (32 or 64-bit). ### Returns - **int** - 32 or 64 ``` -------------------------------- ### Apply Relocations to Loaded Code in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Relocation.md Uses the RelocationHandler to apply SHT_RELA relocations to a binary buffer, handling potential errors during the process. ```python from elftools.elf.relocation import RelocationHandler handler = RelocationHandler(elf) # Find all relocation sections for section in elf.iter_sections(): if section['sh_type'] == 'SHT_RELA': # Get associated symbol table symtab = elf.get_section(section['sh_link']) # Apply relocations to a buffer data = section.data() errors = [] with open(elf_file, 'rb') as f: try: applied = handler.apply_relocations( section, symtab, f, errors=errors ) print(f"Applied {len(applied)} relocations") if errors: for err in errors: print(f" Warning: {err}") except ELFRelocationError as e: print(f"Relocation failed: {e}") ``` -------------------------------- ### Find Functions in DWARF Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Scans DWARF debugging information to locate subprogram tags and calculate their address ranges. ```python if elf.has_dwarf_info(): dwarfinfo = elf.get_dwarf_info() for cu in dwarfinfo.iter_CUs(): print(f"\nCompile unit {cu.cu_offset:#x}:") for die in cu.iter_DIEs(): if die.tag == 'DW_TAG_subprogram': func_name = die.attributes.get('DW_AT_name') lowpc = die.attributes.get('DW_AT_low_pc') highpc = die.attributes.get('DW_AT_high_pc') if func_name and lowpc: start = lowpc.value # highpc can be absolute address or size if highpc: if highpc.form == 'DW_FORM_addr': end = highpc.value else: end = start + highpc.value print(f" {func_name.value}: {start:#x}-{end:#x}") else: print(f" {func_name.value}: {start:#x}") ``` -------------------------------- ### Analyze dynamic relocations Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Dynamic.md Iterates through the .rela.plt section to inspect dynamic relocation entries. ```python dynamic = elf.get_section_by_name('.dynamic') if dynamic: # Get relocation tables from dynamic section rela_section = elf.get_section_by_name('.rela.plt') if rela_section: for reloc in rela_section.iter_relocations(): print(f"Relocation at {reloc['r_offset']:#x}") ``` -------------------------------- ### Accessing ELF Header and Section Fields Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/INDEX.md Demonstrates accessing structured data fields using the library's dictionary-like container interface. ```python # Access header fields value = elf['e_machine'] value = section['sh_type'] value = symbol['st_value'] ``` -------------------------------- ### Map function to source lines in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md Identify a function by its DIE attributes and map its address range to corresponding source code lines. ```python cu = next(dwarfinfo.iter_CUs()) # Find a function DIE for die in cu.iter_DIEs(): if die.tag == 'DW_TAG_subprogram': lowpc = die.attributes.get('DW_AT_low_pc') highpc = die.attributes.get('DW_AT_high_pc') name = die.attributes.get('DW_AT_name') if lowpc and highpc and name: func_start = lowpc.value if highpc.form == 'DW_FORM_addr': func_end = highpc.value else: func_end = func_start + highpc.value print(f"Function: {name.value} ({func_start:#x}-{func_end:#x})") line_program = cu.get_top_DIE().dwarfinfo.get_line_program(cu) if line_program: for entry in line_program.iter_lines(): if func_start <= entry.state.address < func_end and not entry.state.end_sequence: print(f" {entry.state.file}:{entry.state.line}") ``` -------------------------------- ### Analyze Symbol Binding Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Map symbol binding information to human-readable names. ```python symtab = elf.get_section_by_name('.symtab') if symtab: for symbol in symtab.iter_symbols(): binding = symbol['st_info'] >> 4 # Upper 4 bits binding_names = { 0: 'LOCAL', 1: 'GLOBAL', 2: 'WEAK', 3: 'GNU_UNIQUE', } name = binding_names.get(binding, 'UNKNOWN') print(f"{symbol.name:20} {name:10}") ``` -------------------------------- ### Iterate DWARF Compile Units Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Accesses DWARF information to iterate through compilation units and retrieve their names and languages. ```python if elf.has_dwarf_info(): dwarfinfo = elf.get_dwarf_info() for cu in dwarfinfo.iter_CUs(): top_die = cu.get_top_DIE() # Get compilation unit attributes cu_name = top_die.attributes.get('DW_AT_name') cu_lang = top_die.attributes.get('DW_AT_language') if cu_name: print(f"Compiled from: {cu_name.value}") if cu_lang: print(f"Language: {cu_lang.value}") ``` -------------------------------- ### Iterate ELF Notes Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Traverse notes within a NoteSection. ```python notes = elf.get_section_by_name('.note.gnu.build-id') if notes: for note in notes.iter_notes(): print(f"Note type: {note['n_type']}") ``` -------------------------------- ### size Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md Returns the total size of the compilation unit in bytes. ```APIDOC ## size ### Description Returns the total size of this CU including the header. ### Returns - **int** - Size in bytes ``` -------------------------------- ### SUNWSyminfoTableSection Methods Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Methods for accessing symbol information in a SUNWSyminfoTableSection. ```APIDOC ## SUNWSyminfoTableSection.num_symbols ### Description Get the total number of symbols in the table, excluding the version entry. ### Method num_symbols(self) -> int ### Returns - int: Number of symbols ## SUNWSyminfoTableSection.get_symbol ### Description Retrieve symbol information at a specific index. ### Method get_symbol(self, n: int) -> Symbol ### Parameters - **n** (int) - Required - Symbol index (1-based) ### Returns - Symbol object ## SUNWSyminfoTableSection.iter_symbols ### Description Iterate over all symbol info entries. ### Method iter_symbols(self) -> Iterator[Symbol] ### Returns - Iterator yielding Symbol objects ``` -------------------------------- ### get_CU_at Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves a specific compile unit at a given offset. ```APIDOC ## get_CU_at ### Description Get a specific compile unit at a given offset. ### Parameters - **offset** (int) - Required - Offset into .debug_info section ### Returns - **CompileUnit** - CompileUnit object ### Errors - **DWARFError** - If offset is invalid ``` -------------------------------- ### Analyze Compilation Unit Metadata Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md Accesses header information and source attributes from a compilation unit. ```python cu = next(dwarfinfo.iter_CUs()) # Header information print(f"Version: {cu['version']}") print(f"Address size: {cu['address_size']}") print(f"DWARF format: {cu.dwarf_format()}-bit") # CU source information top_die = cu.get_top_DIE() source_file = top_die.attributes.get('DW_AT_name') comp_dir = top_die.attributes.get('DW_AT_comp_dir') if source_file: print(f"Source: {source_file.value}") if comp_dir: print(f"Compile dir: {comp_dir.value}") ``` -------------------------------- ### Retrieve section by name Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Access a section directly using its string name. ```python symtab = elf.get_section_by_name('.symtab') if symtab: print(f"Found symbol table with {symtab.num_symbols()} symbols") else: print("No symbol table found") ``` -------------------------------- ### Define DwarfConfig Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Configuration structure for DWARF parsing, specifying machine architecture and address size. ```python class DwarfConfig(NamedTuple): little_endian: bool machine_arch: str default_address_size: int ``` -------------------------------- ### Check Binary Compilation Attributes Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Extracts compiler and language information from DWARF debug information if available. ```python if elf.has_dwarf_info(): dwarfinfo = elf.get_dwarf_info() cu = next(dwarfinfo.iter_CUs()) top_die = cu.get_top_DIE() # Producer (compiler) producer = top_die.attributes.get('DW_AT_producer') if producer: print(f"Built with: {producer.value}") # Language language = top_die.attributes.get('DW_AT_language') if language: print(f"Language: {language.value}") ``` -------------------------------- ### Access ELF Section Fields in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/types.md Demonstrates how to retrieve specific attributes from an ELF section object using dictionary-style access. ```python section_type = section['sh_type'] section_size = section['sh_size'] section_addr = section['sh_addr'] ``` -------------------------------- ### List All Symbols Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Iterate through the symbol table and extract symbol details. ```python symtab = elf.get_section_by_name('.symtab') if symtab: print(f"Total symbols: {symtab.num_symbols()}") for symbol in symtab.iter_symbols(): # Skip empty symbols if symbol['st_name'] == 0: continue binding = 'global' if (symbol['st_info'] >> 4) == 1 else 'local' sym_type = symbol['st_info'] & 0xf print(f"{symbol.name:30} {symbol['st_value']:#10x} {binding:10} {sym_type:5d}") ``` -------------------------------- ### Retrieve sections by index and type Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Access specific sections using their index, with optional type validation to ensure the section matches expected criteria. ```python # Get section by index section = elf.get_section(1) # Get with type validation symtab = elf.get_section(5, type={'SHT_SYMTAB'}) ``` -------------------------------- ### Retrieve a DIE by reference address Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Fetch a DIE using its absolute offset within the .debug_info section. ```python die = dwarfinfo.get_DIE_from_refaddr(0x100) ``` -------------------------------- ### Find Symbols by Name Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Search for symbols by name, which may return multiple matches. ```python syms = symtab.get_symbol_by_name('main') if syms: for sym in syms: print(f"main at {sym['st_value']:#x}") ``` -------------------------------- ### Use has_section() for Existence Checks Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Prefer has_section() over get_section_by_name() for existence checks to avoid unnecessary parsing overhead. ```python # Good: just checks existence if elf.has_section('.symtab'): symtab = elf.get_section_by_name('.symtab') # Less efficient: parses section even if you don't use it symtab = elf.get_section_by_name('.symtab') if symtab: pass ``` -------------------------------- ### Handle ELFError exceptions Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Catch errors occurring during ELF file initialization. ```python try: elf = ELFFile(f) except ELFError as e: print(f"Invalid ELF file: {e}") ``` -------------------------------- ### has_ehabi_info Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Check if ARM exception handler index information is present. ```APIDOC ## has_ehabi_info() ### Description Check if ARM exception handler index information is present (.ARM.exidx section). ### Returns True if EHABI info exists ``` -------------------------------- ### Check CFA Register Rules Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CallFrame.md Inspect the initial CFA state and iterate through instructions to track modifications to the frame rule. ```python fde = cfi.get_FDE_at(0x400580) if fde: cie = fde.cie # CFA is at (register + offset) # Instructions modify this rule as we traverse cfa_reg = cie.return_address_register cfa_offset = 0 print(f"Initial CFA: r{cfa_reg} + {cfa_offset}") # Process instructions to get CFA rule at specific offset for instr in fde.instructions: # Instructions modify cfa_reg and cfa_offset print(f" {instr}") ``` -------------------------------- ### Section.__getitem__(name) Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Section.md Provides dictionary-like access to section header fields. ```APIDOC ## Section.__getitem__(name) ### Description Accesses specific fields within the section header using their string names. ### Parameters - **name** (str) - Required - The name of the header field (e.g., 'sh_type', 'sh_offset'). ### Returns - **Any** - The value of the requested header field. ``` -------------------------------- ### Check for DWARF info Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Verifies the presence of DWARF debugging information in the ELF file. ```python if elf.has_dwarf_info(): dwarf = elf.get_dwarf_info() # process debug info ``` -------------------------------- ### Testing conditions to avoid exceptions Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Perform validation checks before accessing sections or DWARF information to prevent common runtime errors. ```python # Instead of catching ELFError if elf.has_section('.symtab'): symtab = elf.get_section_by_name('.symtab') # Safe to use symtab # Instead of catching DWARFError if elf.has_dwarf_info(): dwarfinfo = elf.get_dwarf_info() # Safe to use dwarfinfo # Check DIE reference validity if 'DW_AT_type' in die.attributes: try: type_die = die.get_DIE_from_attribute('DW_AT_type') except DWARFError: # Handle missing or invalid type reference pass ``` -------------------------------- ### Access Library Information Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/README.md Iterates through the dynamic section tags to identify library dependencies marked with DT_NEEDED. ```python dynamic = elf.get_section_by_name('.dynamic') for tag in dynamic.iter_tags(): if tag['d_tag'] == 'DT_NEEDED': print(f"Depends on: {tag.needed}") ``` -------------------------------- ### Iterate over sections by index Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Use the total section count to iterate through all sections in the ELF file. ```python count = elf.num_sections() for i in range(count): section = elf.get_section(i) ``` -------------------------------- ### get_dwarf_info Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Extract and parse DWARF debug information from the file. ```APIDOC ## get_dwarf_info(relocate_dwarf_sections: bool = True, follow_links: bool = True) ### Description Extract and parse DWARF debug information from the file. ### Parameters - **relocate_dwarf_sections** (bool) - Optional - If True, apply relocations to DWARF sections - **follow_links** (bool) - Optional - If True, load external/supplementary debug files ### Returns DWARFInfo object ### Raises - ELFError: If file has no DWARF info or external debug link is invalid - DWARFError: If DWARF sections cannot be parsed ``` -------------------------------- ### Analyze Relocation Type Distribution in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Relocation.md Counts the occurrences of different relocation types across all relocation sections using a Counter. ```python from collections import Counter reloc_types = Counter() for section in elf.iter_sections(): if section['sh_type'] in ('SHT_REL', 'SHT_RELA'): for reloc in section.iter_relocations(): r_info = reloc['r_info'] if elf.elfclass == 32: reloc_type = r_info & 0xff else: reloc_type = r_info & 0xffffffff reloc_types[reloc_type] += 1 print("Relocation type distribution:") for reloc_type, count in reloc_types.most_common(): print(f" Type {reloc_type}: {count}") ``` -------------------------------- ### Access relocation fields and info Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Relocation.md Extracts the symbol index and relocation type from the r_info field, accounting for 32-bit or 64-bit ELF classes. ```python for reloc in reloc_section.iter_relocations(): offset = reloc['r_offset'] r_info = reloc['r_info'] # Extract symbol index and type if reloc_section.elffile.elfclass == 32: sym_idx = r_info >> 8 reloc_type = r_info & 0xff else: # 64-bit sym_idx = r_info >> 32 reloc_type = r_info & 0xffffffff print(f"Offset: {offset:#x}, Symbol: {sym_idx}, Type: {reloc_type}") ``` -------------------------------- ### Retrieve DWARF format Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CompileUnit.md Determine whether the compilation unit uses 32-bit or 64-bit DWARF format. ```python fmt = cu.dwarf_format() print(f"DWARF format: {fmt}-bit") ``` -------------------------------- ### get_CLIEs Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves all Common Information Entries. ```APIDOC ## get_CLIEs ### Description Get all Common Information Entries (CIEs). ### Returns - **list[ZERO]** - List of CIE objects ``` -------------------------------- ### Check for section existence Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Efficiently verify if a section exists in the ELF file without retrieving the full object. ```python if elf.has_section('.debug_info'): print("File contains debug information") ``` -------------------------------- ### get_entries_for_line(filename, lineno) Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md Retrieves line program entries associated with a specific source file and line number. ```APIDOC ## get_entries_for_line(filename, lineno) ### Description Get line program entries for a specific source file and line number. ### Parameters - **filename** (str | bytes) - Required - Source filename to match - **lineno** (int) - Required - Line number ### Returns - **Iterator** - Yields matching LineProgramEntry objects. ``` -------------------------------- ### Determine If Binary Is Position Independent (PIE) Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/GETTING_STARTED.md Checks the ELF header type and inspects relocation sections for relative relocation entries to identify PIE binaries. ```python # Check e_type and relocations is_pie = elf['e_type'] in ('ET_DYN', 'ET_EXEC') # More definitive: check for RELATIVE relocations for section in elf.iter_sections(): if section['sh_type'] == 'SHT_RELA': for reloc in section.iter_relocations(): # Look for R_*_RELATIVE or R_*_IRELATIVE pass ``` -------------------------------- ### Check for DWARF debug information Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Verify if the DWARF information contains actual debug sections rather than just .eh_frame. ```python dwarfinfo = elf.get_dwarf_info() if dwarfinfo.has_debug_info: print("Contains DWARF debug information") ``` -------------------------------- ### DIE Constructor Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DIE.md Initializes a DIE instance by parsing data from a stream. This is generally handled internally by CompileUnit or TypeUnit. ```python def __init__( self, cu: CompileUnit | TypeUnit, stream: IO[bytes], offset: int ) -> None ``` -------------------------------- ### Safe Section Access Pattern Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/errors.md Pattern for accessing ELF sections safely by name. ```python try: section = elf.get_section_by_name('.text') if section: data = section.data() except ELFError as e: print(f"Section error: {e}") ``` -------------------------------- ### Iterate over relocation entries Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Relocation.md Iterates through all relocations in a section and checks if they contain an addend. ```python for reloc in reloc_section.iter_relocations(): symbol = reloc.is_RELA() and 'with addend' or 'without addend' print(f"Reloc at {reloc['r_offset']:#x} {symbol}") ``` -------------------------------- ### Access DWARF debug information Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/00-START-HERE.txt Iterates through compilation units and debugging information entries if DWARF info is present in the ELF file. ```python if elf.has_dwarf_info(): dwarf = elf.get_dwarf_info() for cu in dwarf.iter_CUs(): for die in cu.iter_DIEs(): ... ``` -------------------------------- ### Retrieve FDE for a specific address in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/CallFrame.md Find the Frame Description Entry that covers a specific machine code address. ```python fde = cfi.get_FDE_at(0x400580) if fde: print(f"Address in function at {fde.pc_begin:#x}") ``` -------------------------------- ### Access Dynamic Section Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/INDEX.md Retrieves the .dynamic section and iterates through tags to identify library dependencies. ```python dynamic = elf.get_section_by_name('.dynamic') if dynamic: # List dependencies for tag in dynamic.iter_tags(lambda t: t['d_tag'] == 'DT_NEEDED'): print(f"Depends on: {tag.needed}") ``` -------------------------------- ### Find source location for an address in Python Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/LineProgram.md Iterate through compilation units and line programs to find the source file and line corresponding to a specific memory address. ```python dwarfinfo = elf.get_dwarf_info() # Address to look up target_addr = 0x400580 # Find all source locations for this address for cu in dwarfinfo.iter_CUs(): line_program = cu.get_top_DIE().dwarfinfo.get_line_program(cu) if line_program: for entry in line_program.iter_lines(): if entry.state.address == target_addr and not entry.state.end_sequence: print(f"{entry.state.file}:{entry.state.line}") ``` -------------------------------- ### get_callframe_info Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/DWARFInfo.md Retrieves call frame information. ```APIDOC ## get_callframe_info ### Description Get call frame information (.debug_frame or .eh_frame section). ### Returns - **CallFrameInfo** - CallFrameInfo object for frame unwinding data ``` -------------------------------- ### Create a relative path stream loader Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/ELFFile.md Generate a loader function to resolve supplementary files relative to a specified base directory. ```python loader = ELFFile.make_relative_loader('/path/to/binary') elf = ELFFile(stream, loader) ``` -------------------------------- ### Segment.__getitem__() Source: https://github.com/eliben/pyelftools/blob/main/_autodocs/api-reference/Segment.md Provides dictionary-like access to the program header fields of the segment. ```APIDOC ## __getitem__(name) ### Description Accesses specific program header fields by name. ### Parameters - **name** (str) - Required - The name of the header field (e.g., 'p_type', 'p_vaddr', 'p_filesz'). ### Returns - **Any** - The value of the requested header field. ```