about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2010-02-20 13:39:58 -0800
committerDavid S. Miller <davem@davemloft.net>2010-02-20 13:48:05 -0800
commit1d204bf2945617be272f88ee233adbceeffd5315 (patch)
tree53434b857b2568fe20a535a8d8abd854ea379b55
parent199428c19774c12b3c4b6e6486ea9d4a021288af (diff)
downloadglibc-1d204bf2945617be272f88ee233adbceeffd5315.tar.gz
glibc-1d204bf2945617be272f88ee233adbceeffd5315.tar.xz
glibc-1d204bf2945617be272f88ee233adbceeffd5315.zip
Fix PLT rewrite when prelinking fails on 64-bit sparc.
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.
-rw-r--r--ChangeLog5
-rw-r--r--sysdeps/sparc/sparc64/dl-machine.h25
2 files changed, 19 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 1044b4de65..85327329ff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-02-20  Joseph Myers  <joseph@codesourcery.com>
+
+	* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_runtime_setup):
+	Adjust rela->r_offset by l->l_addr when rewriting PLT.
+
 2010-02-19  Carl Fredrik Hammar  <hammy.lite@gmail.com>
 
 	* hurd/hurdioctl.c (tiocsctty): Call `do_tiocsctty' instead of
diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h
index b4f43e9cf5..4c915eb586 100644
--- a/sysdeps/sparc/sparc64/dl-machine.h
+++ b/sysdeps/sparc/sparc64/dl-machine.h
@@ -1,6 +1,6 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  Sparc64 version.
    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-	2010 Free Software Foundation, Inc.
+	2009, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -227,7 +227,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	    {
 	      if (__builtin_expect (rela->r_addend, 0) != 0)
 		{
-                  Elf64_Addr slot = ((rela->r_offset + 0x400
+		  Elf64_Addr slot = ((rela->r_offset + l->l_addr + 0x400
 				      - (Elf64_Addr) plt)
 				     / 0x1400) * 0x1400
 				    + (Elf64_Addr) plt - 0x400;
@@ -235,20 +235,23 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 		  unsigned int first_ldx = *(unsigned int *)(slot + 12);
 		  Elf64_Addr ptr = slot + (first_ldx & 0xfff) + 4;
 
-		  *(Elf64_Addr *) rela->r_offset
+		  *(Elf64_Addr *) (rela->r_offset + l->l_addr)
 		    = (Elf64_Addr) plt
-		      - (slot + ((rela->r_offset - ptr) / 8) * 24 + 4);
+		      - (slot + ((rela->r_offset + l->l_addr - ptr) / 8) * 24
+			 + 4);
 		  ++rela;
 		  continue;
 		}
 
-	      *(unsigned int *) rela->r_offset
-		= 0x03000000 | (rela->r_offset - (Elf64_Addr) plt);
-	      *(unsigned int *) (rela->r_offset + 4)
-		= 0x30680000 | ((((Elf64_Addr) plt + 32
-				  - rela->r_offset - 4) >> 2) & 0x7ffff);
-	      __asm __volatile ("flush %0" : : "r" (rela->r_offset));
-	      __asm __volatile ("flush %0+4" : : "r" (rela->r_offset));
+	      *(unsigned int *) (rela->r_offset + l->l_addr)
+		= 0x03000000 | (rela->r_offset + l->l_addr - (Elf64_Addr) plt);
+	      *(unsigned int *) (rela->r_offset + l->l_addr + 4)
+		= 0x30680000 | ((((Elf64_Addr) plt + 32 - rela->r_offset
+				  - l->l_addr - 4) >> 2) & 0x7ffff);
+	      __asm __volatile ("flush %0" : : "r" (rela->r_offset
+						    + l->l_addr));
+	      __asm __volatile ("flush %0+4" : : "r" (rela->r_offset
+						      + l->l_addr));
 	      ++rela;
 	    }
 	}