Bug 632920 part 2 - Add support for R_ARM_THM_JUMP24 relocation in elfhack. r=tglek,a=bsmedberg
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 16 Feb 2011 17:27:35 +0100
changeset 62673 bc02cd2cfd9830772d0a519769e161b94af5a6d5
parent 62672 c705e1cdb6ec717762188f14f177c65a48b7c73d
child 62674 972ccbb745326b451131da3fd48df3e0ddde45a4
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
reviewerstglek, bsmedberg
bugs632920
milestone2.0b12pre
Bug 632920 part 2 - Add support for R_ARM_THM_JUMP24 relocation in elfhack. r=tglek,a=bsmedberg
build/unix/elfhack/elfhack.cpp
--- a/build/unix/elfhack/elfhack.cpp
+++ b/build/unix/elfhack/elfhack.cpp
@@ -44,16 +44,19 @@
 
 #define ver "0"
 #define elfhack_data ".elfhack.data.v" ver
 #define elfhack_text ".elfhack.text.v" ver
 
 #ifndef R_ARM_V4BX
 #define R_ARM_V4BX 0x28
 #endif
+#ifndef R_ARM_THM_JUMP24
+#define R_ARM_THM_JUMP24 0x1e
+#endif
 
 char *rundir = NULL;
 
 class Elf_RelHack_Traits {
 public:
     typedef Elf32_Rel Type32;
     typedef Elf32_Rel Type64;
 
@@ -232,16 +235,50 @@ private:
             // We don't care about sign_extend because the only case where this is
             // going to be used only jumps forward.
             Elf32_Addr tmp = (Elf32_Addr) (addr - offset - base_addr) >> 2;
             tmp = (addend + tmp) & 0x00ffffff;
             return (addend & 0xff000000) | tmp;
         }
     };
 
+    class arm_thm_jump24_relocation {
+    public:
+        Elf32_Addr operator()(unsigned int base_addr, Elf32_Off offset,
+                              Elf32_Word addend, unsigned int addr)
+        {
+            /* Follows description of b.w instructions as per
+               ARM Architecture Reference Manual ARMĀ® v7-A and ARMĀ® v7-R edition, A8.6.16
+               We limit ourselves to Encoding T3.
+               We don't care about sign_extend because the only case where this is
+               going to be used only jumps forward. */
+            Elf32_Addr tmp = (Elf32_Addr) (addr - offset - base_addr);
+            unsigned int word0 = addend & 0xffff,
+                         word1 = addend >> 16;
+
+            if (((word0 & 0xf800) != 0xf000) || ((word1 & 0xd000) != 0x9000))
+                throw std::runtime_error("R_ARM_THM_JUMP24 relocation only supported for B.W <label>");
+
+            unsigned int s = (word0 & (1 << 10)) >> 10;
+            unsigned int j1 = (word1 & (1 << 13)) >> 13;
+            unsigned int j2 = (word1 & (1 << 11)) >> 11;
+            unsigned int i1 = j1 ^ s ? 0 : 1;
+            unsigned int i2 = j2 ^ s ? 0 : 1;
+
+            tmp += ((s << 24) | (i1 << 23) | (i2 << 22) | ((word0 & 0x3ff) << 12) | ((word1 & 0x7ff) << 1));
+
+            s = (tmp & (1 << 24)) >> 24;
+            j1 = ((tmp & (1 << 23)) >> 23) ^ !s;
+            j2 = ((tmp & (1 << 22)) >> 22) ^ !s;
+
+            return 0xf000 | (s << 10) | ((tmp & (0x3ff << 12)) >> 12) | 
+                   (0x9000 << 16) | (j1 << 29) | (j2 << 27) | ((tmp & 0xffe) << 15);
+        }
+    };
+
     class gotoff_relocation {
     public:
         Elf32_Addr operator()(unsigned int base_addr, Elf32_Off offset,
                               Elf32_Word addend, unsigned int addr)
         {
             return addr + addend;
         }
     };
@@ -301,21 +338,25 @@ private:
             }
             // Do the relocation
 #define REL(machine, type) (EM_ ## machine | (R_ ## machine ## _ ## type << 8))
             switch (elf->getMachine() | (ELF32_R_TYPE(r->r_info) << 8)) {
             case REL(X86_64, PC32):
             case REL(386, PC32):
             case REL(386, GOTPC):
             case REL(ARM, GOTPC):
+            case REL(ARM, REL32):
                 apply_relocation<pc32_relocation>(the_code, buf, &*r, addr);
                 break;
             case REL(ARM, PLT32):
                 apply_relocation<arm_plt32_relocation>(the_code, buf, &*r, addr);
                 break;
+            case REL(ARM, THM_JUMP24):
+                apply_relocation<arm_thm_jump24_relocation>(the_code, buf, &*r, addr);
+                break;
             case REL(386, GOTOFF):
             case REL(ARM, GOTOFF):
                 apply_relocation<gotoff_relocation>(the_code, buf, &*r, addr);
                 break;
             case REL(ARM, V4BX):
                 // Ignore R_ARM_V4BX relocations
                 break;
             default: