Author: nwhitehorn
Date: Mon Oct  4 16:02:11 2010
New Revision: 213406
URL: http://svn.freebsd.org/changeset/base/213406

Log:
  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

Modified:
  head/libexec/rtld-elf/powerpc/reloc.c

Modified: head/libexec/rtld-elf/powerpc/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc/reloc.c       Mon Oct  4 15:48:03 2010        
(r213405)
+++ head/libexec/rtld-elf/powerpc/reloc.c       Mon Oct  4 16:02:11 2010        
(r213406)
@@ -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
 
                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
 
                        /* 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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to