Add an x86_64 shared object linked at a non-zero base - #188
Conversation
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS Validation record for head What is here alreadyEvery ELF file in the repository at
"Relative relocation" means a type whose name ends in So nothing in this repository can distinguish a loader that adds the load bias The new file
How it was built
__attribute__((noinline)) static int alpha(void) { return 1; }
__attribute__((noinline)) static int beta(void) { return 2; }
__attribute__((noinline)) static int delta(void) { return 3; }
void *const table[] = {(void *)alpha, (void *)beta, (void *)delta};
Rebuilding from that recipe on a different toolchain reproduces the shape but What consumes it
The one that still passes is the third test, a control that maps the existing Full measurement of the loader defect, including its effect across 234,056 Rebased 2026-09-04. Re-keyed onto binaries master |
a93c271 to
612c425
Compare
|
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
import cle
ld = cle.Loader("tests/x86_64/relative_reloc_nonzero_base.so",
main_opts={"base_addr": 0x800000}, auto_load_libs=False)
m = ld.main_object
for r in m.relocs:
print(hex(r.rebased_addr), hex(m.memory.unpack_word(r.relative_addr)),
hex(r.addend - m.linked_base + m.mapped_base))Before — the object is not in the repository: angr/binaries masterAfter — the object loads, and because its linked base is with this change |
9f1de95 to
dd5ab9c
Compare
An ELF R_*_RELATIVE relocation writes the load bias plus its addend, and the bias is mapped_base - linked_base. Every shared object and PIE in this repository is linked at zero, so linked_base is zero throughout and the bias is indistinguishable from the mapped base. A loader that confuses the two is correct on all 304 of them. relative_reloc_nonzero_base.so is linked with -Wl,-Ttext-segment=0x400000, so its lowest PT_LOAD is at 0x400000 and its three relative relocations carry addends of 0x401000, 0x401010 and 0x401020. It is the shape Go's linker emits for a PIE, in 13 KB rather than 6 MB. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7394f29 to
7324318
Compare
THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS
Problem
Every ELF here that carries relative relocations is linked at zero, so an
object's load bias and its mapped base are the same number throughout and a
loader that confuses the two is correct on all of them. There is no input that
separates the two, and on master the path does not exist:
Root cause
ldlinks a shared object at zero unless it is told otherwise, and nothinghere asks it to, so the only
ET_DYNshapes in the repository are the oneswhere
linked_base == 0hides the distinction.Fix
Adds
tests/x86_64/relative_reloc_nonzero_base.so, anET_DYNwhose lowestPT_LOADsits at0x400000, carrying threeR_X86_64_RELATIVErelocationsthat fill a pointer table in
.data.rel.ro. That is what Go's linker emits fora PIE, in a few kilobytes.
tests_src/relative_reloc_nonzero_base.cholds thesource and the one-line gcc invocation that builds it.
Testing
Read back,
.rela.dynholds three type-8 entries atr_offset0x403ec0,0x403ec8,0x403ed0with addends0x401000,0x401010,0x401020. Loadedby cle at master with
base_addr=0x800000, the load bias is0x400000and thethree slots come back holding
0xc01000,0xc01010,0xc01020where thelinked value plus the bias is
0x801000,0x801010,0x801020— theconfusion the fixture separates. Used by
tests/test_relative_relocations.pyin angr/cle#773, which fixes it and cannot be tested without this file.
Validation: #188 (comment)
session: sharpen