Fix MIPS segfaults relating to DT_MIPS_RLD_MAP_REL and RPath removal
This is my attempt at fixing the issue I described in this Debian bug report: https://bugs.debian.org/820334
There is a comment in the code which describes why we need to do this on MIPS:
// Background: debuggers need to know the "linker map" which contains
// the addresses each dynamic object is loaded at. Most arches use
// the DT_DEBUG tag which the dynamic linker writes to (directly) and
// contain the location of the linker map, however on MIPS the
// .dynamic section is always read-only so this is not possible. MIPS
// objects instead contain a DT_MIPS_RLD_MAP tag which contains the
// address where the dyanmic linker will write to (an indirect
// version of DT_DEBUG). Since this doesn't work when using PIE, a
// relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this
// version contains a relative offset, moving it changes the
// calculated address. This may cause the dyanmic linker to write
// into memory it should not be changing.
//
// To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If
// we move it up by n bytes, we add n bytes to the value of this tag.
The other 4 commits do some refactoring around the cmELF
API to make it possible to implement this. I decided to add a DynamicEntryList
type to allow cmELF
callers to read the entire .dynamic
section from the ELF, manipulate it, and then re-encode it. This seemed like the best abstraction to me since it keeps all the endian/bitness issues inside cmELF
.
Instead of adding DT_MIPS_RLD_MAP_REL
to the ByteSwap(ELF_Dyn& dyn)
method, I simply removed the switch from it. In both ELF32 and ELF64, sizeof(dyn.d_un.d_val) == sizeof(dyn.d_un.d_ptr)
so there is no need to distinguish between them when fixing the endianness.