[llvm-branch-commits] [llvm-branch] r98650 - in /llvm/branches/Apple/Morbo: ./ include/llvm/ExecutionEngine/ExecutionEngine.h include/llvm/ExecutionEngine/JITMemoryManager.h lib/ExecutionEngine/ExecutionEngine.cpp lib/ExecutionEngine/JIT/JIT.cpp lib/ExecutionEngine/JIT/JIT.h lib/ExecutionEngine/JIT/JITEmitter.cpp lib/ExecutionEngine/JIT/JITMemoryManager.cpp unittests/ExecutionEngine/JIT/JITTest.cpp

Eric Christopher echristo at apple.com
Tue Mar 16 11:58:06 PDT 2010


Author: echristo
Date: Tue Mar 16 13:58:06 2010
New Revision: 98650

URL: http://llvm.org/viewvc/llvm-project?rev=98650&view=rev
Log:
Merge 96835 from Hermes to bring back dlsym support.

Modified:
    llvm/branches/Apple/Morbo/   (props changed)
    llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/ExecutionEngine.h
    llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/JITMemoryManager.h
    llvm/branches/Apple/Morbo/lib/ExecutionEngine/ExecutionEngine.cpp
    llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.cpp
    llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.h
    llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITEmitter.cpp
    llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
    llvm/branches/Apple/Morbo/unittests/ExecutionEngine/JIT/JITTest.cpp

Propchange: llvm/branches/Apple/Morbo/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Mar 16 13:58:06 2010
@@ -1,2 +1,2 @@
-/llvm/branches/Apple/Hermes:96832,96858,96870,96876,96879
+/llvm/branches/Apple/Hermes:96832,96835,96858,96870,96876,96879
 /llvm/trunk:98602,98604,98612,98615-98616

Modified: llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/ExecutionEngine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/ExecutionEngine.h?rev=98650&r1=98649&r2=98650&view=diff
==============================================================================
--- llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/ExecutionEngine.h (original)
+++ llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/ExecutionEngine.h Tue Mar 16 13:58:06 2010
@@ -92,6 +92,7 @@
   bool CompilingLazily;
   bool GVCompilationDisabled;
   bool SymbolSearchingDisabled;
+  bool DlsymStubsEnabled;
 
   friend class EngineBuilder;  // To allow access to JITCtor and InterpCtor.
 
@@ -387,7 +388,15 @@
   bool isSymbolSearchingDisabled() const {
     return SymbolSearchingDisabled;
   }
-
+  
+  /// EnableDlsymStubs - 
+  void EnableDlsymStubs(bool Enabled = true) {
+    DlsymStubsEnabled = Enabled;
+  }
+  bool areDlsymStubsEnabled() const {
+    return DlsymStubsEnabled;
+  }
+  
   /// InstallLazyFunctionCreator - If an unknown function is needed, the
   /// specified function pointer is invoked to create it.  If it returns null,
   /// the JIT will abort.

Modified: llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/JITMemoryManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/JITMemoryManager.h?rev=98650&r1=98649&r2=98650&view=diff
==============================================================================
--- llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/JITMemoryManager.h (original)
+++ llvm/branches/Apple/Morbo/include/llvm/ExecutionEngine/JITMemoryManager.h Tue Mar 16 13:58:06 2010
@@ -71,6 +71,17 @@
   /// return a pointer to its base.
   virtual uint8_t *getGOTBase() const = 0;
   
+  /// SetDlsymTable - If the JIT must be able to relocate stubs after they have
+  /// been emitted, potentially because they are being copied to a process
+  /// where external symbols live at different addresses than in the JITing
+  ///  process, allocate a table with sufficient information to do so.
+  virtual void SetDlsymTable(void *ptr) = 0;
+  
+  /// getDlsymTable - If this is managing a table of entries so that stubs to
+  /// external symbols can be later relocated, this method should return a
+  /// pointer to it.
+  virtual void *getDlsymTable() const = 0;
+  
   /// NeedsExactSize - If the memory manager requires to know the size of the
   /// objects to be emitted
   bool NeedsExactSize() const {

Modified: llvm/branches/Apple/Morbo/lib/ExecutionEngine/ExecutionEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Morbo/lib/ExecutionEngine/ExecutionEngine.cpp?rev=98650&r1=98649&r2=98650&view=diff
==============================================================================
--- llvm/branches/Apple/Morbo/lib/ExecutionEngine/ExecutionEngine.cpp (original)
+++ llvm/branches/Apple/Morbo/lib/ExecutionEngine/ExecutionEngine.cpp Tue Mar 16 13:58:06 2010
@@ -57,6 +57,7 @@
   CompilingLazily         = false;
   GVCompilationDisabled   = false;
   SymbolSearchingDisabled = false;
+  DlsymStubsEnabled       = false;
   Modules.push_back(M);
   assert(M && "Module is null?");
 }

Modified: llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.cpp?rev=98650&r1=98649&r2=98650&view=diff
==============================================================================
--- llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.cpp (original)
+++ llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.cpp Tue Mar 16 13:58:06 2010
@@ -659,6 +659,11 @@
     // the stub with real address of the function.
     updateFunctionStub(PF);
   }
+  
+  // If the JIT is configured to emit info so that dlsym can be used to
+  // rewrite stubs to external globals, do so now.
+  if (areDlsymStubsEnabled() && !isCompilingLazily())
+    updateDlsymStubTable();
 }
 
 /// getPointerToFunction - This method is used to get the address of the
@@ -684,7 +689,8 @@
     return Addr;
 
   if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
-    bool AbortOnFailure = !F->hasExternalWeakLinkage();
+    bool AbortOnFailure =
+      !areDlsymStubsEnabled() && !F->hasExternalWeakLinkage();
     void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
     addGlobalMapping(F, Addr);
     return Addr;
@@ -713,7 +719,7 @@
       return (void*)&__dso_handle;
 #endif
     Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName());
-    if (Ptr == 0) {
+    if (Ptr == 0 && !areDlsymStubsEnabled()) {
       llvm_report_error("Could not resolve external global address: "
                         +GV->getName());
     }

Modified: llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.h?rev=98650&r1=98649&r2=98650&view=diff
==============================================================================
--- llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.h (original)
+++ llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JIT.h Tue Mar 16 13:58:06 2010
@@ -202,6 +202,7 @@
                                        TargetMachine &tm);
   void runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked);
   void updateFunctionStub(Function *F);
+  void updateDlsymStubTable();
 
 protected:
 

Modified: llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=98650&r1=98649&r2=98650&view=diff
==============================================================================
--- llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITEmitter.cpp (original)
+++ llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITEmitter.cpp Tue Mar 16 13:58:06 2010
@@ -369,6 +369,10 @@
     ValueMap<const Function *, EmittedCode,
              EmittedFunctionConfig> EmittedFunctions;
 
+    // ExtFnStubs - A map of external function names to stubs which have entries
+    // in the JITResolver's ExternalFnToStubMap.
+    StringMap<void *> ExtFnStubs;
+
     DILocation PrevDLT;
 
     /// Instance of the JIT
@@ -413,7 +417,7 @@
     void startGVStub(const GlobalValue* GV,
                      unsigned StubSize, unsigned Alignment = 1);
     void startGVStub(void *Buffer, unsigned StubSize);
-    void finishGVStub();
+    void *finishGVStub();
     virtual void *allocIndirectGV(const GlobalValue *GV,
                                   const uint8_t *Buffer, size_t Size,
                                   unsigned Alignment);
@@ -457,6 +461,10 @@
     /// function body.
     void deallocateMemForFunction(const Function *F);
 
+    /// getExternalFnStubs - Accessor for the JIT to find stubs emitted for
+    /// MachineRelocations that reference external functions by name.
+    const StringMap<void*> &getExternalFnStubs() const { return ExtFnStubs; }
+
     virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn);
 
     virtual void emitLabel(MCSymbol *Label) {
@@ -595,8 +603,10 @@
     Actual = TheJIT->getPointerToFunction(F);
 
     // If we resolved the symbol to a null address (eg. a weak external)
-    // don't emit a stub. Return a null pointer to the application.
-    if (!Actual) return 0;
+    // don't emit a stub. Return a null pointer to the application.  If dlsym
+    // stubs are enabled, not being able to resolve the address is not
+    // meaningful.
+    if (!Actual && !TheJIT->areDlsymStubsEnabled()) return 0;
   }
 
   TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout();
@@ -801,8 +811,10 @@
     if (ResultPtr) return ResultPtr;
 
     // If this is an external function pointer, we can force the JIT to
-    // 'compile' it, which really just adds it to the map.
-    if (isNonGhostDeclaration(F) || F->hasAvailableExternallyLinkage())
+    // 'compile' it, which really just adds it to the map.  In dlsym mode,
+    // external functions are forced through a stub, regardless of reloc type.
+    if (isNonGhostDeclaration(F) || F->hasAvailableExternallyLinkage() &&
+        !TheJIT->areDlsymStubsEnabled())
       return TheJIT->getPointerToFunction(F);
   }
 
@@ -825,7 +837,7 @@
     DILocation CurDLT = EmissionDetails.MF->getDILocation(DL);
 
     if (BeforePrintingInsn) {
-      if (CurDLT.getScope().getNode() != 0 
+      if (CurDLT.getScope().getNode() != 0
           && PrevDLT.getNode() != CurDLT.getNode()) {
         JITEvent_EmittedFunctionDetails::LineStart NextLine;
         NextLine.Address = getCurrentPCValue();
@@ -1139,7 +1151,15 @@
 
           // If the target REALLY wants a stub for this function, emit it now.
           if (MR.mayNeedFarStub()) {
-            ResultPtr = Resolver.getExternalFunctionStub(ResultPtr);
+            if (!TheJIT->areDlsymStubsEnabled()) {
+              ResultPtr = Resolver.getExternalFunctionStub(ResultPtr);
+            } else {
+              void *&Stub = ExtFnStubs[MR.getExternalSymbol()];
+              if (!Stub) {
+                Stub = Resolver.getExternalFunctionStub((void *)&Stub);
+              }
+              ResultPtr = Stub;
+            }
           }
         } else if (MR.isGlobalValue()) {
           ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
@@ -1417,7 +1437,7 @@
   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
   if (JT.empty() || JumpTableBase == 0) return;
 
-  
+
   switch (MJTI->getEntryKind()) {
   case MachineJumpTableInfo::EK_Inline:
     return;
@@ -1426,11 +1446,11 @@
     //     .word LBB123
     assert(MJTI->getEntrySize(*TheJIT->getTargetData()) == sizeof(void*) &&
            "Cross JIT'ing?");
-    
+
     // For each jump table, map each target in the jump table to the address of
     // an emitted MachineBasicBlock.
     intptr_t *SlotPtr = (intptr_t*)JumpTableBase;
-    
+
     for (unsigned i = 0, e = JT.size(); i != e; ++i) {
       const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs;
       // Store the address of the basic block for this jump table slot in the
@@ -1440,7 +1460,7 @@
     }
     break;
   }
-      
+
   case MachineJumpTableInfo::EK_Custom32:
   case MachineJumpTableInfo::EK_GPRel32BlockAddress:
   case MachineJumpTableInfo::EK_LabelDifference32: {
@@ -1484,12 +1504,13 @@
   BufferEnd = BufferBegin+StubSize+1;
 }
 
-void JITEmitter::finishGVStub() {
+void *JITEmitter::finishGVStub() {
   assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
   NumBytes += getCurrentPCOffset();
-  BufferBegin = SavedBufferBegin;
+  std::swap(SavedBufferBegin, BufferBegin);
   BufferEnd = SavedBufferEnd;
   CurBufferPtr = SavedCurBufferPtr;
+  return SavedBufferBegin;
 }
 
 void *JITEmitter::allocIndirectGV(const GlobalValue *GV,
@@ -1579,6 +1600,92 @@
   JE->finishGVStub();
 }
 
+/// updateDlsymStubTable - Emit the data necessary to relocate the stubs
+/// that were emitted during code generation.
+///
+void JIT::updateDlsymStubTable() {
+  assert(isa<JITEmitter>(JCE) && "Unexpected MCE?");
+  JITEmitter *JE = cast<JITEmitter>(getCodeEmitter());
+
+  SmallVector<GlobalValue*, 8> GVs;
+  SmallVector<void*, 8> Ptrs;
+  const StringMap<void *> &ExtFns = JE->getExternalFnStubs();
+
+  JE->getJITResolver().getRelocatableGVs(GVs, Ptrs);
+
+  unsigned nStubs = GVs.size() + ExtFns.size();
+
+  // If there are no relocatable stubs, return.
+  if (nStubs == 0)
+    return;
+
+  // If there are no new relocatable stubs, return.
+  void *CurTable = JE->getMemMgr()->getDlsymTable();
+  if (CurTable && (*(unsigned *)CurTable == nStubs))
+    return;
+
+  // Calculate the size of the stub info
+  unsigned offset = 4 + 4 * nStubs + sizeof(intptr_t) * nStubs;
+
+  SmallVector<unsigned, 8> Offsets;
+  for (unsigned i = 0; i != GVs.size(); ++i) {
+    Offsets.push_back(offset);
+    offset += GVs[i]->getName().size() + 1;
+  }
+  for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
+       i != e; ++i) {
+    Offsets.push_back(offset);
+    offset += strlen(i->first()) + 1;
+  }
+
+  // Allocate space for the new "stub", which contains the dlsym table.
+  JE->startGVStub(0, offset, 4);
+
+  // Emit the number of records
+  JE->emitInt32(nStubs);
+
+  // Emit the string offsets
+  for (unsigned i = 0; i != nStubs; ++i)
+    JE->emitInt32(Offsets[i]);
+
+  // Emit the pointers.  Verify that they are at least 2-byte aligned, and set
+  // the low bit to 0 == GV, 1 == Function, so that the client code doing the
+  // relocation can write the relocated pointer at the appropriate place in
+  // the stub.
+  for (unsigned i = 0; i != GVs.size(); ++i) {
+    intptr_t Ptr = (intptr_t)Ptrs[i];
+    assert((Ptr & 1) == 0 && "Stub pointers must be at least 2-byte aligned!");
+
+    if (isa<Function>(GVs[i]))
+      Ptr |= (intptr_t)1;
+
+    if (sizeof(Ptr) == 8)
+      JE->emitInt64(Ptr);
+    else
+      JE->emitInt32(Ptr);
+  }
+  for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
+       i != e; ++i) {
+    intptr_t Ptr = (intptr_t)i->second | 1;
+
+    if (sizeof(Ptr) == 8)
+      JE->emitInt64(Ptr);
+    else
+      JE->emitInt32(Ptr);
+  }
+
+  // Emit the strings.
+  for (unsigned i = 0; i != GVs.size(); ++i)
+    JE->emitString(GVs[i]->getName());
+  for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
+       i != e; ++i)
+    JE->emitString(i->first());
+
+  // Tell the JIT memory manager where it is.  The JIT Memory Manager will
+  // deallocate space for the old one, if one existed.
+  JE->getMemMgr()->SetDlsymTable(JE->finishGVStub());
+}
+
 /// freeMachineCodeForFunction - release machine code memory for given Function.
 ///
 void JIT::freeMachineCodeForFunction(Function *F) {

Modified: llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITMemoryManager.cpp?rev=98650&r1=98649&r2=98650&view=diff
==============================================================================
--- llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITMemoryManager.cpp (original)
+++ llvm/branches/Apple/Morbo/lib/ExecutionEngine/JIT/JITMemoryManager.cpp Tue Mar 16 13:58:06 2010
@@ -296,6 +296,7 @@
     MemoryRangeHeader *CurBlock;
 
     uint8_t *GOTBase;     // Target Specific reserved memory
+    void *DlsymTable;     // Stub external symbol information
   public:
     DefaultJITMemoryManager();
     ~DefaultJITMemoryManager();
@@ -317,6 +318,7 @@
     static const size_t DefaultSizeThreshold;
 
     void AllocateGOT();
+    void SetDlsymTable(void *);
 
     // Testing methods.
     virtual bool CheckInvariants(std::string &ErrorStr);
@@ -467,6 +469,10 @@
       return GOTBase;
     }
 
+    void *getDlsymTable() const {
+      return DlsymTable;
+    }
+
     void deallocateBlock(void *Block) {
       // Find the block that is allocated for this function.
       MemoryRangeHeader *MemRange = static_cast<MemoryRangeHeader*>(Block) - 1;
@@ -593,6 +599,7 @@
   FreeMemoryList = Mem0;
 
   GOTBase = NULL;
+  DlsymTable = NULL;
 }
 
 void DefaultJITMemoryManager::AllocateGOT() {
@@ -601,6 +608,10 @@
   HasGOT = true;
 }
 
+void DefaultJITMemoryManager::SetDlsymTable(void *ptr) {
+  DlsymTable = ptr;
+}
+
 DefaultJITMemoryManager::~DefaultJITMemoryManager() {
   for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i)
     sys::Memory::ReleaseRWX(CodeSlabs[i]);

Modified: llvm/branches/Apple/Morbo/unittests/ExecutionEngine/JIT/JITTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Morbo/unittests/ExecutionEngine/JIT/JITTest.cpp?rev=98650&r1=98649&r2=98650&view=diff
==============================================================================
--- llvm/branches/Apple/Morbo/unittests/ExecutionEngine/JIT/JITTest.cpp (original)
+++ llvm/branches/Apple/Morbo/unittests/ExecutionEngine/JIT/JITTest.cpp Tue Mar 16 13:58:06 2010
@@ -72,6 +72,8 @@
   virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); }
   virtual void AllocateGOT() { Base->AllocateGOT(); }
   virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); }
+  virtual void SetDlsymTable(void *ptr) { Base->SetDlsymTable(ptr); }
+  virtual void *getDlsymTable() const { return Base->getDlsymTable(); }
   struct StartFunctionBodyCall {
     StartFunctionBodyCall(uint8_t *Result, const Function *F,
                           uintptr_t ActualSize, uintptr_t ActualSizeResult)
@@ -311,6 +313,7 @@
       ConstantInt::get(TypeBuilder<int, false>::get(Context), 7));
   Builder.CreateRet(result);
 
+  TheJIT->EnableDlsymStubs(false);
   TheJIT->DisableLazyCompilation(true);
   int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
       (intptr_t)TheJIT->getPointerToFunction(TestFunction));





More information about the llvm-branch-commits mailing list