[RuntimeDyld] Fix ppc64 stub relocations on little-endian
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Fri, 20 Jun 2014 18:17:56 +0000 (18:17 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Fri, 20 Jun 2014 18:17:56 +0000 (18:17 +0000)
When RuntimeDyldELF creates stub functions, it needs to install
relocations that will resolve to the final address of the target
routine. Since those are 16-bit relocs, they need to be applied to the
least-significant halfword of the instruction.  On big-endian ppc64,
this means that addresses have to be adjusted by 2, which is what the
code currently does.

However, on a little-endian system, the address must *not* be adjusted;
the least-significant halfword is the first one.  This patch updates the
RuntimeDyldELF code to take the target byte order into account.

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

lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp

index f6348be746d44373b29889bf26049b0c8d2a9cd1..03e0a36ab90e03528691831c54e2d6ef4f8c636c 100644 (file)
@@ -1205,14 +1205,20 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
                              ELF::R_PPC64_ADDR64, Value.Addend);
 
           // Generates the 64-bits address loads as exemplified in section
-          // 4.5.1 in PPC64 ELF ABI.
-          RelocationEntry REhst(SectionID, StubTargetAddr - Section.Address + 2,
+          // 4.5.1 in PPC64 ELF ABI.  Note that the relocations need to
+          // apply to the low part of the instructions, so we have to update
+          // the offset according to the target endianness.
+          uint64_t StubRelocOffset = StubTargetAddr - Section.Address;
+          if (!IsTargetLittleEndian)
+            StubRelocOffset += 2;
+
+          RelocationEntry REhst(SectionID, StubRelocOffset + 0,
                                 ELF::R_PPC64_ADDR16_HIGHEST, Value.Addend);
-          RelocationEntry REhr(SectionID, StubTargetAddr - Section.Address + 6,
+          RelocationEntry REhr(SectionID, StubRelocOffset + 4,
                                ELF::R_PPC64_ADDR16_HIGHER, Value.Addend);
-          RelocationEntry REh(SectionID, StubTargetAddr - Section.Address + 14,
+          RelocationEntry REh(SectionID, StubRelocOffset + 12,
                               ELF::R_PPC64_ADDR16_HI, Value.Addend);
-          RelocationEntry REl(SectionID, StubTargetAddr - Section.Address + 18,
+          RelocationEntry REl(SectionID, StubRelocOffset + 16,
                               ELF::R_PPC64_ADDR16_LO, Value.Addend);
 
           if (Value.SymbolName) {