summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-09-30 23:59:40 (GMT)
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-09-30 23:59:40 (GMT)
commit2369d8b2def0775b0666350fd266bdc0abb07b0d (patch)
tree363548878e4e56e2cb1c0e8dcfbd30b164a8760a
parent58ec67927fb649a8325c016f04e050d17f787d66 (diff)
downloadpatchelf-2369d8b2def0775b0666350fd266bdc0abb07b0d.zip
patchelf-2369d8b2def0775b0666350fd266bdc0abb07b0d.tar.gz
patchelf-2369d8b2def0775b0666350fd266bdc0abb07b0d.tar.bz2
* Handle `--set-rpath' for the growing case.
-rw-r--r--src/patchelf.cc51
-rw-r--r--tests/Makefile.am6
-rwxr-xr-xtests/set-rpath.sh15
-rwxr-xr-xtests/shrink.sh8
4 files changed, 58 insertions, 22 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc
index a5b804b..f93e89d 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -185,7 +185,7 @@ static void rewriteSections()
for (ReplacedSections::iterator i = replacedSections.begin();
i != replacedSections.end(); ++i)
- fprintf(stderr, "replacing section `%s' with size `%d', content `%s'\n",
+ fprintf(stderr, "replacing section `%s' with size %d, content `%s'\n",
i->first.c_str(), i->second.size(), i->second.c_str());
@@ -215,7 +215,8 @@ static void rewriteSections()
string sectionName = getSectionName(shdr);
fprintf(stderr, "looking at section `%s'\n", sectionName.c_str());
if (replacedSections.find(sectionName) != replacedSections.end()) continue;
- if (shdr.sh_type == SHT_PROGBITS && sectionName != ".interp") {
+ if (true /* XXX shdr.sh_type == SHT_PROGBITS && sectionName !=
+ ".interp" */) {
startOffset = shdr.sh_offset;
startAddr = shdr.sh_addr;
lastReplaced = i - 1;
@@ -288,13 +289,25 @@ static void rewriteSections()
shdr.sh_addralign = 4;
/* If this is the .interp section, then the PT_INTERP segment
- has to be synced with it. */
- for (int j = 0; j < phdrs.size(); ++j)
- if (phdrs[j].p_type == PT_INTERP) {
- phdrs[j].p_offset = shdr.sh_offset;
- phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
- phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
- }
+ has to be sync'ed with it. */
+ if (i->first == ".interp") {
+ for (int j = 0; j < phdrs.size(); ++j)
+ if (phdrs[j].p_type == PT_INTERP) {
+ phdrs[j].p_offset = shdr.sh_offset;
+ phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr;
+ phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size;
+ }
+ }
+
+ /* If this is the .dynstr section, then the .dynamic section
+ has to be sync'ed with it. */
+ if (i->first == ".dynstr") {
+ Elf32_Shdr & shdrDynamic = findSection(".dynamic");
+ Elf32_Dyn * dyn = (Elf32_Dyn *) (contents + shdrDynamic.sh_offset);
+ for ( ; dyn->d_tag != DT_NULL; dyn++)
+ if (dyn->d_tag == DT_STRTAB)
+ dyn->d_un.d_ptr = shdr.sh_addr;
+ }
curOff += roundUp(i->second.size(), 4);
}
@@ -369,10 +382,12 @@ static void modifyRPath(RPathOp op, string newRPath)
/* Walk through the dynamic section, look for the RPATH entry. */
static vector<string> neededLibs;
dyn = (Elf32_Dyn *) (contents + shdrDynamic.sh_offset);
+ Elf32_Dyn * dynRPath = 0;
Elf32_Dyn * rpathEntry = 0;
char * rpath = 0;
for ( ; dyn->d_tag != DT_NULL; dyn++) {
if (dyn->d_tag == DT_RPATH) {
+ dynRPath = dyn;
rpathEntry = dyn;
rpath = strTab + dyn->d_un.d_val;
}
@@ -437,14 +452,17 @@ static void modifyRPath(RPathOp op, string newRPath)
}
- if (string(rpath) == newRPath) return;
+ if (string(rpath ? rpath : "") == newRPath) return;
changed = true;
/* Zero out the previous rpath to prevent retained
dependencies in Nix. */
- unsigned int rpathSize = strlen(rpath);
- memset(rpath, 0, rpathSize);
+ unsigned int rpathSize = 0;
+ if (rpath) {
+ rpathSize = strlen(rpath);
+ memset(rpath, 'X', rpathSize);
+ }
fprintf(stderr, "new rpath is `%s'\n", newRPath.c_str());
@@ -453,7 +471,16 @@ static void modifyRPath(RPathOp op, string newRPath)
return;
}
+ /* Grow the .dynstr section to make room for the new RPATH. */
fprintf(stderr, "rpath is too long, resizing...\n");
+
+ string & newDynStr = replaceSection(".dynstr",
+ shdrDynStr.sh_size + newRPath.size() + 1);
+ setSubstr(newDynStr, shdrDynStr.sh_size, newRPath + '\0');
+
+ /* Update the DT_RPATH entry. */
+ assert(dynRPath != 0);
+ dynRPath->d_un.d_val = shdrDynStr.sh_size;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ccd86dd..3d6a726 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -10,19 +10,19 @@ simple_SOURCES = simple.c
main: main.o libfoo.so
- LD_LIBRARY_PATH=. $(CC) -o main main.o -L . -lfoo
+ LD_LIBRARY_PATH=. gcc -o main main.o -L . -lfoo
main.o: main.c
$(CC) -fpic -o main.o -c main.c
libfoo.so: foo.o libbar.so
- $(CC) -shared -o libfoo.so foo.o -L . -lbar -Wl,-rpath,`pwd`/no-such-path
+ $(CC) -shared -o libfoo.so foo.o -L . -lbar
foo.o: foo.c
$(CC) -fpic -o foo.o -c foo.c
libbar.so: bar.o
- $(CC) -shared -o libbar.so bar.o -L .
+ NIX_DONT_SET_RPATH=1 $(CC) -shared -o libbar.so bar.o -L . -Wl,-rpath,`pwd`/no-such-path
bar.o: bar.c
$(CC) -fpic -o bar.o -c bar.c
diff --git a/tests/set-rpath.sh b/tests/set-rpath.sh
index 6446395..cbe1006 100755
--- a/tests/set-rpath.sh
+++ b/tests/set-rpath.sh
@@ -9,11 +9,20 @@ cp main scratch/
cp libfoo.so scratch/libsA/
cp libbar.so scratch/libsB/
-../src/patchelf --set-rpath $(pwd)/scratch/libsA scratch/main
-../src/patchelf --set-rpath $(pwd)/scratch/libsB scratch/libsA/libfoo.so
+oldRPath=$(../src/patchelf --print-rpath scratch/main)
+if test -z "$oldRPath"; then oldRPath="/oops"; fi
+../src/patchelf --set-rpath $oldRPath:$(pwd)/scratch/libsA:$(pwd)/scratch/libsB scratch/main
+
+#oldRPath=$(../src/patchelf --print-rpath scratch/libsA/libfoo.so)
+#if test -z "$oldRPath"; then oldRPath="/oops"; fi
+#../src/patchelf --set-rpath $oldRPath:$(pwd)/scratch/libsB scratch/libsA/libfoo.so
+
+#oldRPath=$(../src/patchelf --print-rpath scratch/libsB/libbar.so)
+#if test -z "$oldRPath"; then oldRPath="/oops"; fi
+#../src/patchelf --set-rpath $oldRPath:$(pwd)/scratch/libsC scratch/libsB/libbar.so
exitCode=0
-scratch/main || exitCode=$?
+cd scratch && ./main || exitCode=$?
if test "$exitCode" != 46; then
echo "bad exit code!"
diff --git a/tests/shrink.sh b/tests/shrink.sh
index 563270f..bbbf4d6 100755
--- a/tests/shrink.sh
+++ b/tests/shrink.sh
@@ -1,6 +1,6 @@
#! /bin/sh -e
-rpath=$(../src/patchelf --print-rpath ./libfoo.so)
+rpath=$(../src/patchelf --print-rpath ./libbar.so)
echo "RPATH before: $rpath"
if ! echo "$rpath" | grep -q /no-such-path; then
echo "incomplete RPATH"
@@ -9,10 +9,10 @@ fi
rm -rf scratch
mkdir -p scratch
-cp libfoo.so scratch/
-../src/patchelf --shrink-rpath scratch/libfoo.so
+cp libbar.so scratch/
+../src/patchelf --shrink-rpath scratch/libbar.so
-rpath=$(../src/patchelf --print-rpath scratch/libfoo.so)
+rpath=$(../src/patchelf --print-rpath scratch/libbar.so)
echo "RPATH after: $rpath"
if echo "$rpath" | grep -q /no-such-path; then
echo "RPATH not shrunk"