about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-05-18 16:51:54 -0400
committerRich Felker <dalias@aerifal.cx>2015-05-18 16:51:54 -0400
commitc093e2e8201524db0d638920e76bcb6b1d925f3a (patch)
tree7849aea9b175f2fe1d74e2c35e136199e8a9fb75 /src
parent43e9f652bf4b2195b04fc14c93db591b30a7b790 (diff)
downloadmusl-c093e2e8201524db0d638920e76bcb6b1d925f3a.tar.gz
musl-c093e2e8201524db0d638920e76bcb6b1d925f3a.tar.xz
musl-c093e2e8201524db0d638920e76bcb6b1d925f3a.zip
reprocess libc/ldso RELA relocations in stage 3 of dynamic linking
this fixes a regression on powerpc that was introduced in commit
f3ddd173806fd5c60b3f034528ca24542aecc5b9. global data accesses on
powerpc seem to be using a translation-unit-local GOT filled via
R_PPC_ADDR32 relocations rather than R_PPC_GLOB_DAT. being a non-GOT
relocation type, these were not reprocessed after adding the main
application and its libraries to the chain, causing libc code not to
see copy relocations in the main program, and therefore to use the
pre-copy-relocation addresses for global data objects (like environ).

the motivation for the dynamic linker only reprocessing GOT/PLT
relocation types in stage 3 is that these types always have a zero
addend, making them safe to process again even if the storage for the
addend has been clobbered. other relocation types which can be used
for address constants in initialized data objects may have non-zero
addends which will be clobbered during the first pass of relocation
processing if they're stored inline (REL form) rather than out-of-line
(RELA form).

powerpc generally uses only RELA, so this patch is sufficient to fix
the regression in practice, but is not fully general, and would not
suffice if an alternate toolchain generated REL for powerpc.
Diffstat (limited to 'src')
-rw-r--r--src/ldso/dynlink.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 7c92ef6c..93595a0f 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -281,7 +281,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
 		}
 
 		int gotplt = (type == REL_GOT || type == REL_PLT);
-		if (dso->rel_update_got && !gotplt) continue;
+		if (dso->rel_update_got && !gotplt && stride==2) continue;
 
 		addend = stride>2 ? rel[2]
 			: gotplt || type==REL_COPY ? 0