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 roland/fix_bad_pc24 created. glibc-2.16-ports-merge-433-gec2ed54


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, roland/fix_bad_pc24 has been created
        at  ec2ed549d8e36561c901550005af3c22064e0531 (commit)

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

commit ec2ed549d8e36561c901550005af3c22064e0531
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:

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


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]