summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-elf/powerpc
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2010-10-04 16:02:11 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2010-10-04 16:02:11 +0000
commit6a7d71b6f3e65a7aaea0b142a004d9168848530f (patch)
treecb30d90c0f4755f654750855956d3074e36ac6a3 /libexec/rtld-elf/powerpc
parent85d8a2efbbed46539957a8b4bf8153deec28c79d (diff)
downloadFreeBSD-src-6a7d71b6f3e65a7aaea0b142a004d9168848530f.zip
FreeBSD-src-6a7d71b6f3e65a7aaea0b142a004d9168848530f.tar.gz
Fix two subtle problems in PPC32 RTLD. The first is a concurrency issue
where long PLT calls in multi-threaded environments could end up with incorrect jmptab values. The second is that, after the addition of extended PLT support, I forgot to update the PLT icache synchronization code to cover the extended PLT instead of just the basic PLT. MFC after: 10 days
Diffstat (limited to 'libexec/rtld-elf/powerpc')
-rw-r--r--libexec/rtld-elf/powerpc/reloc.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c
index c90852f..84feff3 100644
--- a/libexec/rtld-elf/powerpc/reloc.c
+++ b/libexec/rtld-elf/powerpc/reloc.c
@@ -38,6 +38,7 @@
#include <string.h>
#include <unistd.h>
#include <machine/cpu.h>
+#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include "debug.h"
@@ -481,6 +482,7 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
jmptab = obj->pltgot + JMPTAB_BASE(N);
jmptab[reloff] = target;
+ powerpc_mb(); /* Order jmptab update before next changes */
if (reloff < PLT_EXTENDED_BEGIN) {
/* for extended PLT entries, we keep the old code */
@@ -489,7 +491,8 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
/* li r11,reloff */
/* b pltcall # use indirect pltcall routine */
- wherep[0] = 0x39600000 | reloff;
+
+ /* first instruction same as before */
wherep[1] = 0x48000000 | (distance & 0x03fffffc);
__syncicache(wherep, 8);
}
@@ -577,7 +580,7 @@ init_pltgot(Obj_Entry *obj)
* Sync the icache for the byte range represented by the
* trampoline routines and call slots.
*/
- __syncicache(pltcall, 72 + N * 8);
+ __syncicache(obj->pltgot, JMPTAB_BASE(N)*4);
}
void
OpenPOWER on IntegriCloud