Skip to content

Dynamic

Dynamic linking interface.

This module provides an interface to analyze various aspects of dynamically linked programs.

It also defines a hook that watches for changes to the link map communicated by ld.so, and exposes an event that other parts of pwndbg can tap into, but one that may have a somewhat obtuse beahvior, due to limitations in GDB. See r_debug_install_link_map_changed_hook for more information.

DYNAMIC_SECTION_ALLOW_MULTIPLE = {elf.DT_NEEDED} module-attribute

DYNAMIC_SECTION_REQUIRED_TAGS = {elf.DT_STRTAB, elf.DT_STRSZ, elf.DT_SYMTAB, elf.DT_SYMENT} module-attribute

CStruct

Utility class for reading fields off of C structs.

Without proper debug information it cannot be guaranteed that the calculated field offsets are correct, therefore, reasonable caution should be exercised when using this class. The assumptions made are: - Padding is added between fields so that all internal members are correctly aligned, as long as the struct itself is correctly aligned. - The alignment of the struct is the same as the alignment of its most strictly aligned member. - Padding is added to the end of the struct so that sequentially laid out instances are always correctly aligned. - Stuct sizes must be greater than or equal to 1 byte.

While these assumptions do not apply in all cases, they should be good enough for the structs in ld.so and in the ELF program images.

align = alignment class-attribute instance-attribute

converters: Dict[str, type] = {} class-attribute instance-attribute

offsets: Dict[str, int] = {} class-attribute instance-attribute

size = current_offset class-attribute instance-attribute

types: Dict[str, pwndbg.dbg_mod.Type] = {} class-attribute instance-attribute

__init__(fields)

elf32_sym() staticmethod

Creates a new instance describing the Elf32_Sym srtucture.

elf64_sym() staticmethod

Creates a new instance describing the Elf64_Sym structure.

elfNN_dyn() staticmethod

Creates a new instance describing the ElfNN_Dyn structure, suitable for the architecture of the inferior.

elfNN_rel() staticmethod

Creates a new instance describing the ElfNN_Rel structure, suitable for the architecture of the inferior.

elfNN_rela() staticmethod

Creates a new instance describing the ElfNN_Rela structure, suitable for the architecture of the inferior.

has_field(name)

Returns whether a field with the given name exists in this struct.

Creates a new instance describing the ABI-stable part of the link_map struct.

r_debug() staticmethod

Creates a new instance describing the ABI-stable part of the r_debug struct.

read(address, name)

Reads the field with the given name from the struct instance located at the given address.

DynamicSegment

Parser for the DYNAMIC segment present in a binary image.

address = address instance-attribute

elf_dyn = elf_dyn instance-attribute

entries = count instance-attribute

entries_by_tag: Dict[Any, Any] = sections class-attribute instance-attribute

has_jmprel = elf.DT_JMPREL in sections and elf.DT_PLTREL in sections and elf.DT_PLTRELSZ in sections class-attribute instance-attribute

has_rel = elf.DT_REL in sections and elf.DT_RELSZ in sections and elf.DT_RELENT in sections class-attribute instance-attribute

has_rela = elf.DT_RELA in sections and elf.DT_RELASZ in sections and elf.DT_RELAENT in sections class-attribute instance-attribute

jmprel_addr = 0 class-attribute instance-attribute

jmprel_elem = None class-attribute instance-attribute

jmprel_r_info_fn = None class-attribute instance-attribute

jmprel_r_sym = elf32_r_sym instance-attribute

jmprel_r_sym_fn = None class-attribute instance-attribute

jmprel_r_type = elf32_r_type instance-attribute

load_bias = load_bias instance-attribute

rel_addr = 0 class-attribute instance-attribute

rel_elem = None class-attribute instance-attribute

rel_r_info_fn = None class-attribute instance-attribute

rel_r_sym = elf32_r_sym instance-attribute

rel_r_sym_fn = None class-attribute instance-attribute

rel_r_type = elf32_r_type instance-attribute

rela_addr = 0 class-attribute instance-attribute

rela_elem = None class-attribute instance-attribute

rela_r_info_fn = None class-attribute instance-attribute

rela_r_sym = elf32_r_sym instance-attribute

rela_r_sym_fn = None class-attribute instance-attribute

rela_r_type = elf32_r_type instance-attribute

strtab_addr = self.dyn_array_read_tag_val(elf.DT_STRTAB) class-attribute instance-attribute

strtab_size = self.dyn_array_read_tag_val(elf.DT_STRSZ) class-attribute instance-attribute

symtab_addr = self.dyn_array_read_tag_val(elf.DT_SYMTAB) class-attribute instance-attribute

symtab_elem = None class-attribute instance-attribute

__init__(address, load_bias)

dyn_array_read(i, field)

Reads the requested field from the entry of given index in the dynamic array.

dyn_array_read_tag_val(tag)

Reads the d_un field from the entry of given tag in the dynamic array. Must not be a tag that allows multiple entries.

jmprel_entry_count()

Returns the number of JMPREL entries.

jmprel_has_addend()

Returns whether the r_addend field is available in entries of JMPREL.

jmprel_read(i, field)

Reads the requested field from the entry of the given index in JMPREL.

rel_entry_count()

Returns the number of REL entries.

rel_read(i, field)

Reads the requested field from the entry of the given index in REL.

rela_entry_count()

Returns the number of RELA entries.

rela_read(i, field)

Reads the requested field from the entry of the given index in RELA.

string(i)

Reads the string at index i from the string table.

symtab_read(i, field)

Reads the requested field from the entry of given index in the symbol table.

LinkMapEntry

An entry in the link map.

__init__(address)

__repr__()

dynamic()

The pointer to the memory mapped dynamic segment of the binary image.

load_bias()

The difference between the addresses in the data structures of the binary image and the actual location of the data being pointed to by them in the address space of the inferior. This number will never be negative.

Aditionally, for DYN images, such as PIE executables and shared libraries, this value is the same as the base load address of the image.

The term "load bias" comes from the ELF binary format loading procedure in the Linux Kernel.

name()

The name of the binary image this entry describes.

next()

The next entry in the chain, if any.

prev()

The previous entry in the chain, if any.

elf32_r_sym(r_info)

Returns the r_sym portion of the r_info relocation field for ELF32.

elf32_r_type(r_info)

Returns the r_type portion of the r_info relocation field for ELF32.

elf64_r_sym(r_info)

Returns the r_sym portion of the r_info relocation field for ELF64.

elf64_r_type(r_info)

Returns the r_type portion of the r_info relocation field for ELF64.

is_dynamic()

Returns whether the current inferior is dynamic.

Not all programs are dynamically linked, or even need the dynamic loader at all. Since this module is entirely reliant on at least the presence of the dynamic loader, and really only makes sense for dynamic programs, it should not be used at all with programs that don't participate in dynamic linkage, or when there is a dynamic linker, but we have no way to talk to it.

Iterator over all the entries in the link map.

Acquires a reference to the head entry of the link map.

Installs the r_debug-based hook to the change event of the link map.

This function is a bit tricky, because ideally we want it to be run as soon as possible, before even the dynamic linker runs, but after both it and the main binary have been mapped into the address space of the inferior. While doing this manually would be trivial - seeing as there is a command in GDB that gives the user control at the exact place we would like -, there does not seem to be a way of easily doing this from inside Python.

Because of this, parts of the code that rely on the hook should try calling this function and firing their own listeners manually at least once.

Install a callback to be called whenever r_debug signal of there being a change in the link map link map is triggered.

Keep in mind this function may be called before the hook that calls the listeners is installed, and, until it is installed, no listener callbacks will actually be triggered. See r_debug_install_link_map_changed_hook.

Hook that gets activated whenever the link map changes.

The r_debug structure, in addition to having a refence to the head of the link map, also has, in its ABI-stable part, a reference to an address that can have a breakpoint attached to it, such that whenever the contents of the link map change, that breakpoint will be triggered1.

We take advantage of that here, by installing our own breakpoint in that location, and watching for trigger events, so that we can notify other bits of pwndbg that the contents of the link_map() function will be different.

Removes a listener previously installed with r_debug_link_map_changed_add_listener().