about summary refs log tree commit diff
path: root/sysdeps/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/powerpc')
-rw-r--r--sysdeps/powerpc/dl-machine.h134
1 files changed, 67 insertions, 67 deletions
diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h
index 70a3f20b31..beabc1d4ff 100644
--- a/sysdeps/powerpc/dl-machine.h
+++ b/sysdeps/powerpc/dl-machine.h
@@ -197,8 +197,7 @@ _dl_runtime_resolve:
  # ...unwind the stack frame, and jump to the PLT entry we updated.
 	addi 1,1,48
 	bctr
-0:
-	.size	 _dl_runtime_resolve,0b-_dl_runtime_resolve
+	.size	 _dl_runtime_resolve,.-_dl_runtime_resolve
 
 	.align 2
 	.globl _dl_prof_resolve
@@ -395,10 +394,6 @@ static ElfW(Addr) _dl_preferred_address = 1
      _dl_preferred_address = mapstart;					      \
 } )
 
-/* We require the address of the PLT entry returned from fixup, not
-   the first word of the PLT entry. */
-#define ELF_FIXUP_RETURN_VALUE(map, result)  ((Elf32_Addr) &(result))
-
 /* Nonzero iff TYPE should not be allowed to resolve to one of
    the main executable's symbols, as for a COPY reloc.  */
 #define elf_machine_lookup_noexec_p(type) ((type) == R_PPC_COPY)
@@ -413,7 +408,7 @@ static ElfW(Addr) _dl_preferred_address = 1
 					  (type) == R_PPC_JMP_SLOT)
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
-#define ELF_MACHINE_RELOC_NOPLT	R_PPC_JMP_SLOT
+#define ELF_MACHINE_JMP_SLOT	R_PPC_JMP_SLOT
 
 /* Nonzero iff TYPE describes relocation of a PLT entry, so
    PLT entries should not be allowed to define the value.  */
@@ -554,6 +549,70 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
   /* elf_machine_runtime_setup handles this. */
 }
 
+static inline void
+elf_machine_fixup_plt(struct link_map *map, const Elf32_Rela *reloc,
+                      Elf32_Addr *reloc_addr, Elf32_Addr finaladdr)
+{
+  Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
+  if (delta << 6 >> 6 == delta)
+    *reloc_addr = OPCODE_B (delta);
+  else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
+    *reloc_addr = OPCODE_BA (finaladdr);
+  else
+    {
+      Elf32_Word *plt;
+      Elf32_Word index;
+
+      plt = (Elf32_Word *)((char *)map->l_addr
+			   + map->l_info[DT_PLTGOT]->d_un.d_val);
+      index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2;
+      if (index >= PLT_DOUBLE_SIZE)
+	{
+	  /* Slots greater than or equal to 2^13 have 4 words available
+	     instead of two.  */
+	  /* FIXME: There are some possible race conditions in this code,
+	     when called from 'fixup'.
+
+	     1) Suppose that a lazy PLT entry is executing, a context switch
+	     between threads (or a signal) occurs, and the new thread or
+	     signal handler calls the same lazy PLT entry.  Then the PLT entry
+	     would be changed while it's being run, which will cause a segfault
+	     (almost always).
+
+	     2) Suppose the reverse: that a lazy PLT entry is being updated,
+	     a context switch occurs, and the new code calls the lazy PLT
+	     entry that is being updated.  Then the half-fixed PLT entry will
+	     be executed, which will also almost always cause a segfault.
+
+	     These problems don't happen with the 2-word entries, because
+	     only one of the two instructions are changed when a lazy entry
+	     is retargeted at the actual PLT entry; the li instruction stays
+	     the same (we have to update it anyway, because we might not be
+	     updating a lazy PLT entry).  */
+
+	  reloc_addr[0] = OPCODE_LI (11, finaladdr);
+	  reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16);
+	  reloc_addr[2] = OPCODE_MTCTR (11);
+	  reloc_addr[3] = OPCODE_BCTR ();
+	}
+      else
+	{
+	  Elf32_Word num_plt_entries;
+
+	  num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
+			     / sizeof(Elf32_Rela));
+
+	  plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr;
+	  reloc_addr[0] = OPCODE_LI (11, index*4);
+	  reloc_addr[1] = OPCODE_B (-(4*(index*2
+					 + 1
+					 - PLT_LONGBRANCH_ENTRY_WORDS
+					 + PLT_INITIAL_ENTRY_WORDS)));
+	}
+    }
+  MODIFIED_CODE (reloc_addr);
+}
+
 #endif /* dl_machine_h */
 
 #ifdef RESOLVE
@@ -674,66 +733,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
     }
   else if (rinfo == R_PPC_JMP_SLOT)
     {
-      Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
-      if (delta << 6 >> 6 == delta)
-	*reloc_addr = OPCODE_B (delta);
-      else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
-	*reloc_addr = OPCODE_BA (finaladdr);
-      else
-	{
-	  Elf32_Word *plt;
-	  Elf32_Word index;
-
-	  plt = (Elf32_Word *)((char *)map->l_addr
-			       + map->l_info[DT_PLTGOT]->d_un.d_val);
-	  index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2;
-	  if (index >= PLT_DOUBLE_SIZE)
-	    {
-	      /* Slots greater than or equal to 2^13 have 4 words available
-		 instead of two.  */
-	      /* FIXME: There are some possible race conditions in this code,
-		 when called from 'fixup'.
-
-		 1) Suppose that a lazy PLT entry is executing, a
-		 context switch between threads (or a signal) occurs,
-		 and the new thread or signal handler calls the same
-		 lazy PLT entry.  Then the PLT entry would be changed
-		 while it's being run, which will cause a segfault
-		 (almost always).
-
-		 2) Suppose the reverse: that a lazy PLT entry is
-		 being updated, a context switch occurs, and the new
-		 code calls the lazy PLT entry that is being updated.
-		 Then the half-fixed PLT entry will be executed, which
-		 will also almost always cause a segfault.
-
-		 These problems don't happen with the 2-word entries, because
-		 only one of the two instructions are changed when a lazy
-		 entry is retargeted at the actual PLT entry; the li
-		 instruction stays the same (we have to update it anyway,
-		 because we might not be updating a lazy PLT entry).  */
-	      reloc_addr[0] = OPCODE_LI (11, finaladdr);
-	      reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16);
-	      reloc_addr[2] = OPCODE_MTCTR (11);
-	      reloc_addr[3] = OPCODE_BCTR ();
-	    }
-	  else
-	    {
-	      Elf32_Word num_plt_entries;
-
-	      num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
-				 / sizeof(Elf32_Rela));
-
-	      plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr;
-	      reloc_addr[0] = OPCODE_LI (11, index*4);
-	      reloc_addr[1] =
-		OPCODE_B (-(4*(index*2
-			       + 1
-			       - PLT_LONGBRANCH_ENTRY_WORDS
-			       + PLT_INITIAL_ENTRY_WORDS)));
-	    }
-	}
-      MODIFIED_CODE (reloc_addr);
+      elf_machine_fixup_plt (map, reloc, reloc_addr, finalvalue);
     }
   else
     {