[ppc64] Patch in TOC restore code after all external function calls
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 11 Mar 2014 15:26:27 +0000 (15:26 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Tue, 11 Mar 2014 15:26:27 +0000 (15:26 +0000)
When resolving a function call to an external routine, the dynamic
loader must patch the "nop" after the branch instruction to a load
that restores the TOC register.

Current code does that, but only with the *first* instance of a call
to any particular external routine, i.e. at the point where it also
allocates the call stub.  With subsequent calls to the same routine,
current code neglects to patch in the TOC restore code.  This is a
bug, and leads to corrupt TOC pointers in those cases.

Fixed by patching in restore code every time.

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

lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp

index 0a593e60f2dad0a4f06b15cbb93b26a36291c010..96b4e127aa6373e58d4ea753aece604b8a4f39dd 100644 (file)
@@ -1206,11 +1206,11 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
           resolveRelocation(Section, Offset,
                             (uint64_t)Section.Address + Section.StubOffset,
                             RelType, 0);
-          if (SymType == SymbolRef::ST_Unknown)
-            // Restore the TOC for external calls
-            writeInt32BE(Target+4, 0xE8410028); // ld r2,40(r1)
           Section.StubOffset += getMaxStubSize();
         }
+        if (SymType == SymbolRef::ST_Unknown)
+          // Restore the TOC for external calls
+          writeInt32BE(Target+4, 0xE8410028); // ld r2,40(r1)
       }
     } else {
       RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);