[mips] Use pristine object file while processing relocations.
authorAkira Hatanaka <ahatanaka@mips.com>
Wed, 24 Jul 2013 01:58:40 +0000 (01:58 +0000)
committerAkira Hatanaka <ahatanaka@mips.com>
Wed, 24 Jul 2013 01:58:40 +0000 (01:58 +0000)
    Similar to ARM change r182800, dynamic linker will read bits/addends from
    the original object rather than from the object that might have been patched
    previously. For the purpose of relocations for MCJIT stubs on MIPS, we
    internally use otherwise unused MIPS relocations.

    The change also enables MCJIT unit tests for MIPS (EL/BE), and the following
    two tests now pass:

    - MCJITTest.return_global and
    - MCJITTest.multiple_functions.

    These issues have been tracked as Bug 16250.

    Patch by Petar Jovanovic.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187019 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/ELF.h
include/llvm/Support/ELF.h
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
unittests/ExecutionEngine/MCJIT/MCJITTestBase.h

index c5c18a0666a760e2197c0f8495ba55d1becf44b9..a14d16803424e1d0b5bcc86ed6ad215371e587e2 100644 (file)
@@ -1666,6 +1666,8 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const {
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32);
+      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_UNUSED1);
+      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_UNUSED2);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6);
       LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64);
index d53ebdbfb9133f9e5c7cd79ce98debfeca1dd1a0..c32724054fdb6aff6a50387c6218dae0c551e93c 100644 (file)
@@ -868,6 +868,8 @@ enum {
   R_MIPS_PC16              = 10,
   R_MIPS_CALL16            = 11,
   R_MIPS_GPREL32           = 12,
+  R_MIPS_UNUSED1           = 13,
+  R_MIPS_UNUSED2           = 14,
   R_MIPS_SHIFT5            = 16,
   R_MIPS_SHIFT6            = 17,
   R_MIPS_64                = 18,
index cb3b5129f23fc15cc51860b0c248dae46fe73f34..05cb5f83bed526a8435fc706b8b23f6a62393154 100644 (file)
@@ -456,6 +456,8 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
                                            uint32_t Value,
                                            uint32_t Type,
                                            int32_t Addend) {
+  uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress +
+                                                      Offset);
   uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
   Value += Addend;
 
@@ -473,19 +475,30 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
     llvm_unreachable("Not implemented relocation type!");
     break;
   case ELF::R_MIPS_32:
-    *TargetPtr = Value + (*TargetPtr);
+    *TargetPtr = Value + (*Placeholder);
     break;
   case ELF::R_MIPS_26:
-    *TargetPtr = ((*TargetPtr) & 0xfc000000) | (( Value & 0x0fffffff) >> 2);
+    *TargetPtr = ((*Placeholder) & 0xfc000000) | (( Value & 0x0fffffff) >> 2);
     break;
   case ELF::R_MIPS_HI16:
     // Get the higher 16-bits. Also add 1 if bit 15 is 1.
-    Value += ((*TargetPtr) & 0x0000ffff) << 16;
+    Value += ((*Placeholder) & 0x0000ffff) << 16;
+    *TargetPtr = ((*Placeholder) & 0xffff0000) |
+                 (((Value + 0x8000) >> 16) & 0xffff);
+    break;
+  case ELF::R_MIPS_LO16:
+    Value += ((*Placeholder) & 0x0000ffff);
+    *TargetPtr = ((*Placeholder) & 0xffff0000) | (Value & 0xffff);
+    break;
+  case ELF::R_MIPS_UNUSED1:
+    // Similar to ELF::R_ARM_PRIVATE_0, R_MIPS_UNUSED1 and R_MIPS_UNUSED2
+    // are used for internal JIT purpose. These relocations are similar to
+    // R_MIPS_HI16 and R_MIPS_LO16, but they do not take any addend into
+    // account.
     *TargetPtr = ((*TargetPtr) & 0xffff0000) |
                  (((Value + 0x8000) >> 16) & 0xffff);
     break;
-   case ELF::R_MIPS_LO16:
-    Value += ((*TargetPtr) & 0x0000ffff);
+  case ELF::R_MIPS_UNUSED2:
     *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff);
     break;
    }
@@ -954,10 +967,10 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
       // Creating Hi and Lo relocations for the filled stub instructions.
       RelocationEntry REHi(SectionID,
                            StubTargetAddr - Section.Address,
-                           ELF::R_MIPS_HI16, Value.Addend);
+                           ELF::R_MIPS_UNUSED1, Value.Addend);
       RelocationEntry RELo(SectionID,
                            StubTargetAddr - Section.Address + 4,
-                           ELF::R_MIPS_LO16, Value.Addend);
+                           ELF::R_MIPS_UNUSED2, Value.Addend);
 
       if (Value.SymbolName) {
         addRelocationForSymbol(REHi, Value.SymbolName);
index 9766a79ae5216be5945f2496d8b4a4f783a02742..5debb8b57858aea93abfdf0d57a2bb1adb89cb39 100644 (file)
@@ -156,6 +156,8 @@ protected:
     // kept in sync.
     SupportedArchs.push_back(Triple::aarch64);
     SupportedArchs.push_back(Triple::arm);
+    SupportedArchs.push_back(Triple::mips);
+    SupportedArchs.push_back(Triple::mipsel);
     SupportedArchs.push_back(Triple::x86);
     SupportedArchs.push_back(Triple::x86_64);