mirror of
https://github.com/NixOS/patchelf.git
synced 2025-10-23 09:47:51 +08:00
Merge branch 'cdugz-master'
This commit is contained in:
108
src/patchelf.cc
108
src/patchelf.cc
@@ -144,6 +144,10 @@ public:
|
||||
|
||||
string getInterpreter();
|
||||
|
||||
string getSoname();
|
||||
|
||||
void setSoname(const string & newSoname);
|
||||
|
||||
void setInterpreter(const string & newInterpreter);
|
||||
|
||||
typedef enum { rpPrint, rpShrink, rpSet } RPathOp;
|
||||
@@ -871,6 +875,89 @@ string ElfFile<ElfFileParamNames>::getInterpreter()
|
||||
return string((char *) contents + rdi(shdr.sh_offset), rdi(shdr.sh_size));
|
||||
}
|
||||
|
||||
template<ElfFileParams>
|
||||
string ElfFile<ElfFileParamNames>::getSoname()
|
||||
{
|
||||
Elf_Shdr & shdrDynamic = findSection(".dynamic");
|
||||
Elf_Shdr & shdrDynStr = findSection(".dynstr");
|
||||
char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset);
|
||||
|
||||
/* Find the DT_STRTAB entry in the dynamic section. */
|
||||
Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset));
|
||||
Elf_Addr strTabAddr = 0;
|
||||
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++)
|
||||
if (rdi(dyn->d_tag) == DT_STRTAB) strTabAddr = rdi(dyn->d_un.d_ptr);
|
||||
if (!strTabAddr) error("strange: no string table");
|
||||
|
||||
/* We assume that the virtual address in the DT_STRTAB entry
|
||||
of the dynamic section corresponds to the .dynstr section. */
|
||||
assert(strTabAddr == rdi(shdrDynStr.sh_addr));
|
||||
|
||||
Elf_Dyn * dynSoname = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset));
|
||||
char * soname = 0;
|
||||
for ( ; rdi(dynSoname->d_tag) != DT_NULL; dynSoname++) {
|
||||
if (rdi(dynSoname->d_tag) == DT_SONAME) {
|
||||
soname = strTab + rdi(dynSoname->d_un.d_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rdi(dynSoname->d_tag) == DT_NULL) {
|
||||
error("Specified ELF file does not contain any DT_SONAME entry in .dynamic section!");
|
||||
}
|
||||
else {
|
||||
return soname;
|
||||
}
|
||||
}
|
||||
|
||||
template<ElfFileParams>
|
||||
void ElfFile<ElfFileParamNames>::setSoname(const string & newSoname)
|
||||
{
|
||||
Elf_Shdr & shdrDynamic = findSection(".dynamic");
|
||||
Elf_Shdr & shdrDynStr = findSection(".dynstr");
|
||||
char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset);
|
||||
|
||||
/* Find the DT_STRTAB entry in the dynamic section. */
|
||||
Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset));
|
||||
Elf_Addr strTabAddr = 0;
|
||||
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++)
|
||||
if (rdi(dyn->d_tag) == DT_STRTAB) strTabAddr = rdi(dyn->d_un.d_ptr);
|
||||
if (!strTabAddr) error("strange: no string table");
|
||||
|
||||
/* We assume that the virtual address in the DT_STRTAB entry
|
||||
of the dynamic section corresponds to the .dynstr section. */
|
||||
assert(strTabAddr == rdi(shdrDynStr.sh_addr));
|
||||
|
||||
Elf_Dyn * dynSoname = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset));
|
||||
char * soname = 0;
|
||||
for ( ; rdi(dynSoname->d_tag) != DT_NULL; dynSoname++) {
|
||||
if (rdi(dynSoname->d_tag) == DT_SONAME) {
|
||||
soname = strTab + rdi(dynSoname->d_un.d_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rdi(dynSoname->d_tag) == DT_NULL)
|
||||
error("Specified ELF file does not contain any DT_SONAME entry in .dynamic section!");
|
||||
|
||||
if (newSoname.size() <= strlen(soname)) {
|
||||
debug("old soname: `%s', new soname: `%s'\n", soname, newSoname.c_str());
|
||||
strcpy(soname, newSoname.c_str());
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
/* Grow the .dynstr section to make room for the new DT_SONAME */
|
||||
debug("new soname is too long, resizing .dynstr section...\n");
|
||||
|
||||
string & newDynStr = replaceSection(".dynstr",
|
||||
rdi(shdrDynStr.sh_size) + newSoname.size() + 1);
|
||||
setSubstr(newDynStr, rdi(shdrDynStr.sh_size), newSoname + '\0');
|
||||
/* Update the DT_SONAME entry, if any */
|
||||
if (dynSoname) {
|
||||
debug("old soname: `%s', new soname: `%s'\n", soname, newSoname.c_str());
|
||||
dynSoname->d_un.d_val = shdrDynStr.sh_size;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<ElfFileParams>
|
||||
void ElfFile<ElfFileParamNames>::setInterpreter(const string & newInterpreter)
|
||||
@@ -1090,6 +1177,9 @@ void ElfFile<ElfFileParamNames>::removeNeeded(set<string> libs)
|
||||
|
||||
|
||||
static bool printInterpreter = false;
|
||||
static bool printSoname = false;
|
||||
static bool setSoname = false;
|
||||
static string newSoname;
|
||||
static string newInterpreter;
|
||||
|
||||
static bool shrinkRPath = false;
|
||||
@@ -1107,6 +1197,12 @@ static void patchElf2(ElfFile & elfFile, mode_t fileMode)
|
||||
if (printInterpreter)
|
||||
printf("%s\n", elfFile.getInterpreter().c_str());
|
||||
|
||||
if (printSoname)
|
||||
printf("%s\n", elfFile.getSoname().c_str());
|
||||
|
||||
if (setSoname)
|
||||
elfFile.setSoname(newSoname);
|
||||
|
||||
if (newInterpreter != "")
|
||||
elfFile.setInterpreter(newInterpreter);
|
||||
|
||||
@@ -1129,7 +1225,7 @@ static void patchElf2(ElfFile & elfFile, mode_t fileMode)
|
||||
|
||||
static void patchElf()
|
||||
{
|
||||
if (!printInterpreter && !printRPath)
|
||||
if (!printInterpreter && !printRPath && !printSoname)
|
||||
debug("patching ELF file `%s'\n", fileName.c_str());
|
||||
|
||||
mode_t fileMode;
|
||||
@@ -1166,6 +1262,8 @@ void showHelp(const string & progName)
|
||||
fprintf(stderr, "syntax: %s\n\
|
||||
[--set-interpreter FILENAME]\n\
|
||||
[--print-interpreter]\n\
|
||||
[--print-soname]\t\tPrints 'DT_SONAME' entry of .dynamic section. Raises an error if DT_SONAME doesn't exist\n\
|
||||
[--set-soname SONAME]\t\tSets 'DT_SONAME' entry to SONAME. Raises an error if DT_SONAME doesn't exist\n\
|
||||
[--set-rpath RPATH]\n\
|
||||
[--shrink-rpath]\n\
|
||||
[--print-rpath]\n\
|
||||
@@ -1196,6 +1294,14 @@ int main(int argc, char * * argv)
|
||||
else if (arg == "--print-interpreter") {
|
||||
printInterpreter = true;
|
||||
}
|
||||
else if (arg == "--print-soname") {
|
||||
printSoname = true;
|
||||
}
|
||||
else if (arg == "--set-soname") {
|
||||
if (++i == argc) error("missing argument");
|
||||
setSoname = true;
|
||||
newSoname = argv[i];
|
||||
}
|
||||
else if (arg == "--shrink-rpath") {
|
||||
shrinkRPath = true;
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ check_PROGRAMS = simple main main-scoped big-dynstr
|
||||
|
||||
TESTS = plain-fail.sh plain-run.sh shrink-rpath.sh set-interpreter-short.sh \
|
||||
set-interpreter-long.sh set-rpath.sh no-rpath.sh big-dynstr.sh \
|
||||
set-rpath-library.sh
|
||||
set-rpath-library.sh soname.sh
|
||||
EXTRA_DIST = no-rpath $(TESTS)
|
||||
|
||||
TESTS_ENVIRONMENT = PATCHELF_DEBUG=1
|
||||
@@ -44,7 +44,7 @@ big_dynstr_LDFLAGS = $(LDFLAGS_local)
|
||||
# - without libtool, only archives (static libraries) can be built by automake
|
||||
# - with libtool, it is difficult to control options
|
||||
# - with libtool, it is not possible to compile convenience *dynamic* libraries :-(
|
||||
check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so
|
||||
check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so
|
||||
|
||||
libfoo_so_SOURCES = foo.c
|
||||
libfoo_so_LDADD = -lbar $(AM_LDADD)
|
||||
@@ -62,3 +62,5 @@ libbar_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-rpath,`pwd`/no-such-path
|
||||
libbar_scoped_so_SOURCES = bar.c
|
||||
libbar_scoped_so_LDFLAGS = $(LDFLAGS_sharedlib)
|
||||
|
||||
libsimple_so_SOURCES = simple.c
|
||||
libsimple_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-soname,libsimple.so.1.0
|
||||
|
21
tests/soname.sh
Executable file
21
tests/soname.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#! /bin/sh -e
|
||||
SCRATCH=scratch/$(basename $0 .sh)
|
||||
|
||||
rm -rf ${SCRATCH}
|
||||
mkdir -p ${SCRATCH}
|
||||
|
||||
cp libsimple.so ${SCRATCH}/
|
||||
|
||||
# print and set DT_SONAME
|
||||
soname=$(../src/patchelf --print-soname ${SCRATCH}/libsimple.so)
|
||||
if test "$soname" != libsimple.so.1.0; then
|
||||
echo "failed --print-soname test. Expected soname: libsimple.so.1.0, got: $soname"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
../src/patchelf --set-soname libsimple.so.1.1 ${SCRATCH}/libsimple.so
|
||||
newSoname=$(../src/patchelf --print-soname ${SCRATCH}/libsimple.so)
|
||||
if test "$newSoname" != libsimple.so.1.1; then
|
||||
echo "failed --set-soname test. Expected newSoname: libsimple.so.1.1, got: $newSoname"
|
||||
exit 1
|
||||
fi
|
Reference in New Issue
Block a user