* Add some basic heap heuristics support for riscv and powerpc
Use the relocation section to find the main_arena address if possible
* Refactor the code we used to get the field offset
# TODO: We should have some cache mechanism or something at `pndbg.gdblib.file.get_file()` in the future to avoid downloading the same file multiple times when we are debugging a remote process
# .relr.dyn and .rel.dyn need to read the data from r_offset
# .rela.dyn has the addend in the entry
ifsection_name!=".rela.dyn":
addend=int.from_bytes(
data_section_data[
r_offset
-data_section_offset:r_offset
-data_section_offset
+pwndbg.gdblib.arch.ptrsize
],
pwndbg.gdblib.arch.endian,
)
else:
addend=relocation.entry.r_addend
# If addend is the offset of main_arena, then r_offset should be the offset of main_arena.next
ifr_offset-next_field_offset==addend:
# Check if we can construct the default main_arena struct we expect
tmp=data_section_data[
addend
-data_section_offset:addend
-data_section_offset
+malloc_state_size
]
# Note: Although RELA relocations have r_addend, some compiler will still put the addend in the location of r_offset, so we still need to check both cases
found=False
expected.next=addend
found|=bytes(expected)==tmp
ifnotfound:
expected.next=0
found|=bytes(expected)==tmp
iffound:
# This might be a false positive, but it is very unlikely, so should be fine :)
self._main_arena_addr=(
data_section_address+addend-data_section_offset
)
break
# If we are still not able to find the main_arena, probably we are debugging a binary with statically linked libc and no PIE enabled
ifnotself._main_arena_addr:
# Try to find the default main_arena struct in the .data section