Bug 632920 part 1 - Refactor relocations application to avoid error-prone duplication of code in elfhack. r=tglek,a=bsmedberg
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 16 Feb 2011 17:25:51 +0100
changeset 62672 c705e1cdb6ec717762188f14f177c65a48b7c73d
parent 62671 76d33291395a07fbbace83bdfe72cef4d9c4e99e
child 62673 bc02cd2cfd9830772d0a519769e161b94af5a6d5
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
reviewerstglek, bsmedberg
bugs632920
milestone2.0b12pre
Bug 632920 part 1 - Refactor relocations application to avoid error-prone duplication of code in elfhack. r=tglek,a=bsmedberg
build/unix/elfhack/elfhack.cpp
--- a/build/unix/elfhack/elfhack.cpp
+++ b/build/unix/elfhack/elfhack.cpp
@@ -210,52 +210,63 @@ public:
     bool isRelocatable() {
         return true;
     }
 
     unsigned int getEntryPoint() {
         return entry_point;
     }
 private:
-    void apply_pc32_relocation(ElfSection *the_code, char *base, Elf_Rel *r, unsigned int addr)
+    class pc32_relocation {
+    public:
+        Elf32_Addr operator()(unsigned int base_addr, Elf32_Off offset,
+                              Elf32_Word addend, unsigned int addr)
+        {
+            return addr + addend - offset - base_addr;
+        }
+    };
+
+    class arm_plt32_relocation {
+    public:
+        Elf32_Addr operator()(unsigned int base_addr, Elf32_Off offset,
+                              Elf32_Word addend, unsigned int addr)
+        {
+            // 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 gotoff_relocation {
+    public:
+        Elf32_Addr operator()(unsigned int base_addr, Elf32_Off offset,
+                              Elf32_Word addend, unsigned int addr)
+        {
+            return addr + addend;
+        }
+    };
+
+    template <class relocation_type>
+    void apply_relocation(ElfSection *the_code, char *base, Elf_Rel *r, unsigned int addr)
     {
-        *(Elf32_Addr *)(base + r->r_offset) += (Elf32_Addr) (addr - r->r_offset - the_code->getAddr());
-    }
-
-    void apply_pc32_relocation(ElfSection *the_code, char *base, Elf_Rela *r, unsigned int addr)
-    {
-        *(Elf32_Addr *)(base + r->r_offset) = (Elf32_Addr) (addr + r->r_addend - r->r_offset - the_code->getAddr());
+        relocation_type relocation;
+        Elf32_Addr value;
+        memcpy(&value, base + r->r_offset, 4);
+        value = relocation(the_code->getAddr(), r->r_offset, value, addr);
+        memcpy(base + r->r_offset, &value, 4);
     }
 
-    void apply_arm_plt32_relocation(ElfSection *the_code, char *base, Elf_Rel *r, unsigned int addr)
-    {
-        // We don't care about sign_extend because the only case where this is
-        // going to be used only jumps forward.
-        Elf32_Addr addend = (Elf32_Addr) (addr - r->r_offset - the_code->getAddr()) >> 2;
-        addend = (*(Elf32_Addr *)(base + r->r_offset) + addend) & 0x00ffffff;
-        *(Elf32_Addr *)(base + r->r_offset) = (*(Elf32_Addr *)(base + r->r_offset) & 0xff000000) | addend;
-    }
-
-    void apply_arm_plt32_relocation(ElfSection *the_code, char *base, Elf_Rela *r, unsigned int addr)
+    template <class relocation_type>
+    void apply_relocation(ElfSection *the_code, char *base, Elf_Rela *r, unsigned int addr)
     {
-        // We don't care about sign_extend because the only case where this is
-        // going to be used only jumps forward.
-        Elf32_Addr addend = (Elf32_Addr) (addr - r->r_offset - the_code->getAddr()) >> 2;
-        addend = (r->r_addend + addend) & 0x00ffffff;
-        *(Elf32_Addr *)(base + r->r_offset) = (r->r_addend & 0xff000000) | addend;
-    }
-
-    void apply_gotoff_relocation(ElfSection *the_code, char *base, Elf_Rel *r, unsigned int addr)
-    {
-        *(Elf32_Addr *)(base + r->r_offset) += (Elf32_Addr) addr;
-    }
-
-    void apply_gotoff_relocation(ElfSection *the_code, char *base, Elf_Rela *r, unsigned int addr)
-    {
-        *(Elf32_Addr *)(base + r->r_offset) = (Elf32_Addr) addr + r->r_addend;
+        relocation_type relocation;
+        Elf32_Addr value = relocation(the_code->getAddr(), r->r_offset, r->r_addend, addr);
+        memcpy(base + r->r_offset, &value, 4);
     }
 
     template <typename Rel_Type>
     void apply_relocations(ElfRel_Section<Rel_Type> *rel, ElfSection *the_code)
     {
         assert(rel->getType() == Rel_Type::sh_type);
         char *buf = data + (the_code->getAddr() - code.front()->getAddr());
         // TODO: various checks on the sections
@@ -290,24 +301,24 @@ 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):
-                apply_pc32_relocation(the_code, buf, &*r, addr);
+                apply_relocation<pc32_relocation>(the_code, buf, &*r, addr);
                 break;
             case REL(ARM, PLT32):
-                apply_arm_plt32_relocation(the_code, buf, &*r, addr);
+                apply_relocation<arm_plt32_relocation>(the_code, buf, &*r, addr);
                 break;
             case REL(386, GOTOFF):
             case REL(ARM, GOTOFF):
-                apply_gotoff_relocation(the_code, buf, &*r, addr);
+                apply_relocation<gotoff_relocation>(the_code, buf, &*r, addr);
                 break;
             case REL(ARM, V4BX):
                 // Ignore R_ARM_V4BX relocations
                 break;
             default:
                 throw std::runtime_error("Unsupported relocation type");
             }
         }