ARM: use pristine object file while processing relocations
authorTim Northover <tnorthover@apple.com>
Tue, 28 May 2013 19:48:19 +0000 (19:48 +0000)
committerTim Northover <tnorthover@apple.com>
Tue, 28 May 2013 19:48:19 +0000 (19:48 +0000)
Previously we would read-modify-write the target bits when processing
relocations for the MCJIT. This had the problem that when relocations
were processed multiple times for the same object file (as they can
be), the result is not idempotent and the values became corrupted.

The solution to this is to take any bits used in the destination from
the pristine object file as LLVM emitted it.

This should fix PR16013 and remote MCJIT on ARM ELF targets.

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

lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
test/ExecutionEngine/MCJIT/remote/simpletest-remote.ll
test/ExecutionEngine/MCJIT/remote/stubs-remote.ll
test/ExecutionEngine/MCJIT/remote/test-fp-no-external-funcs-remote.ll

index 9494e6b44e87073710748adadb460174f1e07850..c5eed251f915b5221c8d3a2de1b0f7b13984de23 100644 (file)
@@ -377,13 +377,14 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
   }
 }
 
-// FIXME: PR16013: this routine needs modification to handle repeated relocations.
 void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
                                           uint64_t Offset,
                                           uint32_t Value,
                                           uint32_t Type,
                                           int32_t Addend) {
   // TODO: Add Thumb relocations.
+  uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress +
+                                                      Offset);
   uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
   uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
   Value += Addend;
@@ -402,44 +403,51 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
 
   // Write a 32bit value to relocation address, taking into account the
   // implicit addend encoded in the target.
-  case ELF::R_ARM_TARGET1 :
-  case ELF::R_ARM_ABS32 :
-    *TargetPtr += Value;
+  case ELF::R_ARM_TARGET1:
+  case ELF::R_ARM_ABS32:
+    *TargetPtr = *Placeholder + Value;
     break;
-
   // Write first 16 bit of 32 bit value to the mov instruction.
   // Last 4 bit should be shifted.
-  case ELF::R_ARM_MOVW_ABS_NC :
+  case ELF::R_ARM_MOVW_ABS_NC:
     // We are not expecting any other addend in the relocation address.
     // Using 0x000F0FFF because MOVW has its 16 bit immediate split into 2
     // non-contiguous fields.
+    assert((*Placeholder & 0x000F0FFF) == 0);
     Value = Value & 0xFFFF;
-    *TargetPtr &= ~0x000F0FFF; // Not really right; see FIXME at top.
-    *TargetPtr |= Value & 0xFFF;
+    *TargetPtr = *Placeholder | (Value & 0xFFF);
     *TargetPtr |= ((Value >> 12) & 0xF) << 16;
     break;
-
   // Write last 16 bit of 32 bit value to the mov instruction.
   // Last 4 bit should be shifted.
-  case ELF::R_ARM_MOVT_ABS :
+  case ELF::R_ARM_MOVT_ABS:
     // We are not expecting any other addend in the relocation address.
     // Use 0x000F0FFF for the same reason as R_ARM_MOVW_ABS_NC.
+    assert((*Placeholder & 0x000F0FFF) == 0);
+
     Value = (Value >> 16) & 0xFFFF;
-    *TargetPtr &= ~0x000F0FFF; // Not really right; see FIXME at top.
-    *TargetPtr |= Value & 0xFFF;
+    *TargetPtr = *Placeholder | (Value & 0xFFF);
     *TargetPtr |= ((Value >> 12) & 0xF) << 16;
     break;
-
   // Write 24 bit relative value to the branch instruction.
   case ELF::R_ARM_PC24 :    // Fall through.
   case ELF::R_ARM_CALL :    // Fall through.
-  case ELF::R_ARM_JUMP24 :
+  case ELF::R_ARM_JUMP24: {
     int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8);
     RelValue = (RelValue & 0x03FFFFFC) >> 2;
+    assert((*TargetPtr & 0xFFFFFF) == 0xFFFFFE);
     *TargetPtr &= 0xFF000000;
     *TargetPtr |= RelValue;
     break;
   }
+  case ELF::R_ARM_PRIVATE_0:
+    // This relocation is reserved by the ARM ELF ABI for internal use. We
+    // appropriate it here to act as an R_ARM_ABS32 without any addend for use
+    // in the stubs created during JIT (which can't put an addend into the
+    // original object file).
+    *TargetPtr = Value;
+    break;
+  }
 }
 
 void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
@@ -898,7 +906,7 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
       uint8_t *StubTargetAddr = createStubFunction(Section.Address +
                                                    Section.StubOffset);
       RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
-                         ELF::R_ARM_ABS32, Value.Addend);
+                         ELF::R_ARM_PRIVATE_0, Value.Addend);
       if (Value.SymbolName)
         addRelocationForSymbol(RE, Value.SymbolName);
       else
index bdd7e3a593ae3042e58b6a640558e660cda71651..f1a69d8d5d50adfcdfa259b646bde79f58ccbd69 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: %lli_mcjit -remote-mcjit %s > /dev/null
-; XFAIL: arm, mips
+; XFAIL:  mips
 
 define i32 @bar() {
        ret i32 0
index 15cb5d037efc6a55956fa95e8ec713621d8e4215..47a710db0e5e3408c453570bf31f82d45efeb259 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: %lli_mcjit -remote-mcjit -disable-lazy-compilation=false %s
-; XFAIL: arm, mips
+; XFAIL:  mips
 
 define i32 @main() nounwind {
 entry:
index c7d48126ae6ee11d8c40390df26a535d0039f28a..d7e8c35716cdd1d4003b8628f81b344231acee74 100644 (file)
@@ -1,5 +1,5 @@
 ; RUN: %lli_mcjit -remote-mcjit %s > /dev/null
-; XFAIL: arm, mips
+; XFAIL:  mips
 
 define double @test(double* %DP, double %Arg) {
        %D = load double* %DP           ; <double> [#uses=1]