summaryrefslogtreecommitdiff
path: root/src/patchelf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/patchelf.cc')
-rw-r--r--src/patchelf.cc33
1 files changed, 31 insertions, 2 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc
index d02bc49..1080e6b 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -766,6 +766,18 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
}
}
+ /* If there is .MIPS.abiflags section, then the PT_MIPS_ABIFLAGS
+ segment must be sync'ed with it. */
+ if (sectionName == ".MIPS.abiflags") {
+ for (auto & phdr : phdrs) {
+ if (rdi(phdr.p_type) == PT_MIPS_ABIFLAGS) {
+ phdr.p_offset = shdr.sh_offset;
+ phdr.p_vaddr = phdr.p_paddr = shdr.sh_addr;
+ phdr.p_filesz = phdr.p_memsz = shdr.sh_size;
+ }
+ }
+ }
+
curOff += roundUp(i.second.size(), sectionAlignment);
}
@@ -1098,9 +1110,9 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
(e.g., those produced by klibc's klcc). */
auto shdrDynamic = findSection2(".dynamic");
if (shdrDynamic) {
- auto dyn = (Elf_Dyn *)(contents + rdi(shdrDynamic->sh_offset));
+ auto dyn_table = (Elf_Dyn *) (contents + rdi(shdrDynamic->sh_offset));
unsigned int d_tag;
- for ( ; (d_tag = rdi(dyn->d_tag)) != DT_NULL; dyn++)
+ for (auto dyn = dyn_table; (d_tag = rdi(dyn->d_tag)) != DT_NULL; dyn++)
if (d_tag == DT_STRTAB)
dyn->d_un.d_ptr = findSection(".dynstr").sh_addr;
else if (d_tag == DT_STRSZ)
@@ -1142,6 +1154,23 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
dyn->d_un.d_ptr = findSection(".gnu.version_r").sh_addr;
else if (d_tag == DT_VERSYM)
dyn->d_un.d_ptr = findSection(".gnu.version").sh_addr;
+ else if (d_tag == DT_MIPS_RLD_MAP_REL) {
+ /* the MIPS_RLD_MAP_REL tag stores the offset to the debug
+ pointer, relative to the address of the tag */
+ auto shdr = findSection2(".rld_map");
+ if (shdr) {
+ auto rld_map_addr = findSection(".rld_map").sh_addr;
+ auto dyn_offset = ((char*)dyn) - ((char*)dyn_table);
+ dyn->d_un.d_ptr = rld_map_addr + dyn_offset - shdrDynamic->sh_addr;
+ } else {
+ /* ELF file with DT_MIPS_RLD_MAP_REL but without .rld_map
+ is broken, and it's not our job to fix it; yet, we have
+ to find some location for dynamic loader to write the
+ debug pointer to; well, let's write it right here */
+ fprintf(stderr, "warning: DT_MIPS_RLD_MAP_REL entry is present, but .rld_map section is not\n");
+ dyn->d_un.d_ptr = 0;
+ }
+ }
}