Fix PLT rewrite when prelinking fails on 32-bit sparc.
authorDavid S. Miller <davem@davemloft.net>
Sat, 20 Feb 2010 21:40:59 +0000 (13:40 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 20 Feb 2010 21:48:06 +0000 (13:48 -0800)
When prelinking fails we have to rewrite the PLT, but the code
doing so forgets to adjust all rela->r_offset addresses by the
location of where the object was actually mapped.

ChangeLog
sysdeps/sparc/sparc32/dl-machine.h

index 8532732..cd1be57 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-02-20  David S. Miller  <davem@davemloft.net>
+
+       * sysdeps/sparc/sparc32/dl-machine.h (elf_machine_runtime_setup):
+       Adjust rela->r_offset by l->l_addr when rewriting PLT.
+
 2009-02-20  Joseph Myers  <joseph@codesourcery.com>
 
        * sysdeps/sparc/sparc64/dl-machine.h (elf_machine_runtime_setup):
index e1385f7..5325710 100644 (file)
@@ -166,15 +166,19 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
             in .rela.plt.  */
          while (rela < relaend)
            {
-             *(unsigned int *) rela->r_offset
-               = OPCODE_SETHI_G1 | (rela->r_offset - (Elf32_Addr) plt);
-             *(unsigned int *) (rela->r_offset + 4)
+             *(unsigned int *) (rela->r_offset + l->l_addr)
+               = OPCODE_SETHI_G1 | (rela->r_offset + l->l_addr
+                                    - (Elf32_Addr) plt);
+             *(unsigned int *) (rela->r_offset + l->l_addr + 4)
                = OPCODE_BA | ((((Elf32_Addr) plt
-                                - rela->r_offset - 4) >> 2) & 0x3fffff);
+                                - rela->r_offset - l->l_addr - 4) >> 2)
+                              & 0x3fffff);
              if (do_flush)
                {
-                 __asm __volatile ("flush %0" : : "r"(rela->r_offset));
-                 __asm __volatile ("flush %0+4" : : "r"(rela->r_offset));
+                 __asm __volatile ("flush %0" : : "r" (rela->r_offset
+                                                       + l->l_addr));
+                 __asm __volatile ("flush %0+4" : : "r" (rela->r_offset
+                                                         + l->l_addr));
                }
              ++rela;
            }