This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch master updated. glibc-2.16-ports-merge-438-gfb228a2


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  fb228a2d94a130eda38c8794b0f264aa9f0e4714 (commit)
      from  53cea63e99264bf81b278546581d6c2efc2c3fc5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fb228a2d94a130eda38c8794b0f264aa9f0e4714

commit fb228a2d94a130eda38c8794b0f264aa9f0e4714
Author: Roland McGrath <roland@hack.frob.com>
Date:   Fri Oct 5 09:39:23 2012 -0700

    Clean up R_ARM_PC24 handling.

diff --git a/ports/ChangeLog.arm b/ports/ChangeLog.arm
index cbbec9b..678b2ab 100644
--- a/ports/ChangeLog.arm
+++ b/ports/ChangeLog.arm
@@ -1,3 +1,9 @@
+2012-10-05  Roland McGrath  <roland@hack.frob.com>
+
+	* sysdeps/arm/dl-machine.h (fix_bad_pc24): Rewritten, replaced with ...
+	(relocate_pc24): ... this new function.
+	(elf_machine_rel, elf_machine_rela): Update callers.
+
 2012-10-02  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	* sysdeps/unix/sysv/linux/arm/nptl/lowlevellock.h: Fix clone
diff --git a/ports/sysdeps/arm/dl-machine.h b/ports/sysdeps/arm/dl-machine.h
index 343a83e..3b25e0f 100644
--- a/ports/sysdeps/arm/dl-machine.h
+++ b/ports/sysdeps/arm/dl-machine.h
@@ -302,36 +302,56 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
 #define ARCH_LA_PLTEXIT arm_gnu_pltexit
 
 #ifdef RESOLVE_MAP
-
-/* Deal with an out-of-range PC24 reloc.  */
-auto Elf32_Addr
-fix_bad_pc24 (Elf32_Addr *const reloc_addr, Elf32_Addr value)
+/* Handle a PC24 reloc, including the out-of-range case.  */
+auto void
+relocate_pc24 (struct link_map *map, Elf32_Addr value,
+               Elf32_Addr *const reloc_addr, Elf32_Sword addend)
 {
-  static void *fix_page;
-  static unsigned int fix_offset;
-  static size_t pagesize;
-  Elf32_Word *fix_address;
+  Elf32_Addr new_value;
+
+  /* Set NEW_VALUE based on V, and return true iff it overflows 24 bits.  */
+  inline bool set_new_value (Elf32_Addr v)
+  {
+    new_value = v + addend - (Elf32_Addr) reloc_addr;
+    Elf32_Addr topbits = new_value & 0xfe000000;
+    return topbits != 0xfe000000 && topbits != 0x00000000;
+  }
 
-  if (! fix_page)
+  if (set_new_value (value))
     {
-      if (! pagesize)
-	pagesize = getpagesize ();
-      fix_page = mmap (NULL, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC,
-		       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-      if (! fix_page)
-	assert (! "could not map page for fixup");
-      fix_offset = 0;
+      /* The PC-relative address doesn't fit in 24 bits!  */
+
+      static void *fix_page;
+      static size_t fix_offset;
+      if (fix_page == NULL)
+        {
+          void *new_page = __mmap (NULL, GLRO(dl_pagesize),
+                                   PROT_READ | PROT_WRITE | PROT_EXEC,
+                                   MAP_PRIVATE | MAP_ANON, -1, 0);
+          if (new_page == MAP_FAILED)
+            _dl_signal_error (0, map->l_name, NULL,
+                              "could not map page for fixup");
+          fix_page = new_page;
+          assert (fix_offset == 0);
+        }
+
+      Elf32_Word *fix_address = fix_page + fix_offset;
+      fix_address[0] = 0xe51ff004;	/* ldr pc, [pc, #-4] */
+      fix_address[1] = value;
+
+      fix_offset += sizeof fix_address[0] * 2;
+      if (fix_offset >= GLRO(dl_pagesize))
+        {
+          fix_page = NULL;
+          fix_offset = 0;
+        }
+
+      if (set_new_value ((Elf32_Addr) fix_address))
+        _dl_signal_error (0, map->l_name, NULL,
+                          "R_ARM_PC24 relocation out of range");
     }
 
-  fix_address = (Elf32_Word *)(fix_page + fix_offset);
-  fix_address[0] = 0xe51ff004;	/* ldr pc, [pc, #-4] */
-  fix_address[1] = value;
-
-  fix_offset += 8;
-  if (fix_offset >= pagesize)
-    fix_page = NULL;
-
-  return (Elf32_Addr)fix_address;
+  *reloc_addr = (*reloc_addr & 0xff000000) | ((new_value >> 2) & 0x00ffffff);
 }
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
@@ -473,30 +493,11 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	    }
 	    break;
 	case R_ARM_PC24:
-	  {
-	     Elf32_Sword addend;
-	     Elf32_Addr newvalue, topbits;
-
-	     addend = *reloc_addr & 0x00ffffff;
-	     if (addend & 0x00800000) addend |= 0xff000000;
-
-	     newvalue = value - (Elf32_Addr)reloc_addr + (addend << 2);
-	     topbits = newvalue & 0xfe000000;
-	     if (topbits != 0xfe000000 && topbits != 0x00000000)
-	       {
-		 newvalue = fix_bad_pc24(reloc_addr, value)
-		   - (Elf32_Addr)reloc_addr + (addend << 2);
-		 topbits = newvalue & 0xfe000000;
-		 if (topbits != 0xfe000000 && topbits != 0x00000000)
-		   {
-		     _dl_signal_error (0, map->l_name, NULL,
-				       "R_ARM_PC24 relocation out of range");
-		   }
-	       }
-	     newvalue >>= 2;
-	     value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
-	     *reloc_addr = value;
-	  }
+          relocate_pc24 (map, value, reloc_addr,
+                         /* Sign-extend the 24-bit addend in the
+                            instruction (which counts instructions), and
+                            then shift it up two so as to count bytes.  */
+                         (((Elf32_Sword) *reloc_addr << 8) >> 8) << 2);
 	  break;
 #if !defined RTLD_BOOTSTRAP
 	case R_ARM_TLS_DTPMOD32:
@@ -589,26 +590,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 	  *reloc_addr = value + reloc->r_addend;
 	  break;
 	case R_ARM_PC24:
-	  {
-	     Elf32_Addr newvalue, topbits;
-
-	     newvalue = value + reloc->r_addend - (Elf32_Addr)reloc_addr;
-	     topbits = newvalue & 0xfe000000;
-	     if (topbits != 0xfe000000 && topbits != 0x00000000)
-	       {
-		 newvalue = fix_bad_pc24(reloc_addr, value)
-		   - (Elf32_Addr)reloc_addr + (reloc->r_addend << 2);
-		 topbits = newvalue & 0xfe000000;
-		 if (topbits != 0xfe000000 && topbits != 0x00000000)
-		   {
-		     _dl_signal_error (0, map->l_name, NULL,
-				       "R_ARM_PC24 relocation out of range");
-		   }
-	       }
-	     newvalue >>= 2;
-	     value = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
-	     *reloc_addr = value;
-	  }
+          relocate_pc24 (map, value, reloc_addr, reloc->r_addend);
 	  break;
 #if !defined RTLD_BOOTSTRAP
 	case R_ARM_TLS_DTPMOD32:

-----------------------------------------------------------------------

Summary of changes:
 ports/ChangeLog.arm            |    6 ++
 ports/sysdeps/arm/dl-machine.h |  120 +++++++++++++++++-----------------------
 2 files changed, 57 insertions(+), 69 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]