Skip to content

Commit

Permalink
Merge pull request #180 from iv-m/mips-fixes
Browse files Browse the repository at this point in the history
Fixes for MIPS binaries
  • Loading branch information
Mic92 authored Aug 11, 2021
2 parents 374c92a + bf73d6e commit 0121f5e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 6 deletions.
13 changes: 9 additions & 4 deletions src/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1574,9 +1574,10 @@ typedef struct

/* Legal values for p_type field of Elf32_Phdr. */

#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
#define PT_MIPS_OPTIONS 0x70000002
#define PT_MIPS_REGINFO 0x70000000 /* Register usage information. */
#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
#define PT_MIPS_OPTIONS 0x70000002
#define PT_MIPS_ABIFLAGS 0x70000003 /* FP mode requirement. */

/* Special program header types. */

Expand Down Expand Up @@ -1642,7 +1643,11 @@ typedef struct
PLT is writable. For a non-writable PLT, this is omitted or has a zero
value. */
#define DT_MIPS_RWPLT 0x70000034
#define DT_MIPS_NUM 0x35
/* An alternative description of the classic MIPS RLD_MAP that is usable
in a PIE as it stores a relative offset from the address of the tag
rather than an absolute address. */
#define DT_MIPS_RLD_MAP_REL 0x70000035
#define DT_MIPS_NUM 0x36

/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */

Expand Down
33 changes: 31 additions & 2 deletions src/patchelf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
}
}


Expand Down
1 change: 1 addition & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ src_TESTS = \
plain-fail.sh plain-run.sh shrink-rpath.sh set-interpreter-short.sh \
set-interpreter-long.sh set-rpath.sh add-rpath.sh no-rpath.sh big-dynstr.sh \
set-rpath-library.sh soname.sh shrink-rpath-with-allowed-prefixes.sh \
set-rpath-rel-map.sh \
force-rpath.sh \
plain-needed.sh \
output-flag.sh \
Expand Down
37 changes: 37 additions & 0 deletions tests/set-rpath-rel-map.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#! /bin/sh -e

if ! objdump -p main | grep -q MIPS_RLD_MAP_REL; then
echo "No MIPS_RLD_MAP_REL dynamic section entry, skipping"
exit 0
fi

SCRATCH=scratch/$(basename $0 .sh)

rm -rf ${SCRATCH}
mkdir -p ${SCRATCH}
mkdir -p ${SCRATCH}/libsA
mkdir -p ${SCRATCH}/libsB

cp main ${SCRATCH}/
cp libfoo.so ${SCRATCH}/libsA/
cp libbar.so ${SCRATCH}/libsB/

# break the main executable by removing .rld_map section
objcopy --remove-section .rld_map ${SCRATCH}/main

oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main)
if test -z "$oldRPath"; then oldRPath="/oops"; fi
../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main

if test "$(uname)" = FreeBSD; then
export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB
fi

exitCode=0

(cd ${SCRATCH} && ./main) || exitCode=$?

if test "$exitCode" != 46; then
echo "bad exit code!"
exit 1
fi

0 comments on commit 0121f5e

Please sign in to comment.