[llvm-commits] [llvm] r153754 - in /llvm/trunk: include/llvm/ExecutionEngine/RuntimeDyld.h lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h tools/llvm-rtdyld/llvm-rtdyld.cpp

Danil Malyshev dmalyshev at accesssoftek.com
Fri Mar 30 09:45:20 PDT 2012


Author: danil
Date: Fri Mar 30 11:45:19 2012
New Revision: 153754

URL: http://llvm.org/viewvc/llvm-project?rev=153754&view=rev
Log:
Re-factored RuntimeDyLd:

1. The main works will made in the RuntimeDyLdImpl with uses the ObjectFile class. RuntimeDyLdMachO and RuntimeDyLdELF now only parses relocations and resolve it. This is allows to make improvements of the RuntimeDyLd more easily. In addition the support for COFF can be easily added.

2. Added ARM relocations to RuntimeDyLdELF.

3. Added support for stub functions for the ARM, allowing to do a long branch.

4. Added support for external functions that are not loaded from the object files, but can be loaded from external libraries. Now MCJIT can correctly execute the code containing the printf, putc, and etc.

5. The sections emitted instead functions, thanks Jim Grosbach. MemoryManager.startFunctionBody() and MemoryManager.endFunctionBody() have been removed.
6. MCJITMemoryManager.allocateDataSection() and MCJITMemoryManager. allocateCodeSection() used JMM->allocateSpace() instead of JMM->allocateCodeSection() and JMM->allocateDataSection(), because I got an error: "Cannot allocate an allocated block!" with object file contains more than one code or data sections.

Modified:
    llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h
    llvm/trunk/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
    llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp

Modified: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h Fri Mar 30 11:45:19 2012
@@ -45,17 +45,6 @@
   virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
                                        unsigned SectionID) = 0;
 
-  // Allocate ActualSize bytes, or more, for the named function. Return
-  // a pointer to the allocated memory and update Size to reflect how much
-  // memory was acutally allocated.
-  virtual uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) = 0;
-
-  // Mark the end of the function, including how much of the allocated
-  // memory was actually used.
-  virtual void endFunctionBody(const char *Name, uint8_t *FunctionStart,
-                               uint8_t *FunctionEnd) = 0;
-
-  
   virtual void *getPointerToNamedFunction(const std::string &Name,
                                           bool AbortOnFailure = true) = 0;
 };

Modified: llvm/trunk/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h (original)
+++ llvm/trunk/lib/ExecutionEngine/MCJIT/MCJITMemoryManager.h Fri Mar 30 11:45:19 2012
@@ -34,12 +34,12 @@
 
   uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
                                unsigned SectionID) {
-    return JMM->allocateDataSection(Size, Alignment, SectionID);
+    return JMM->allocateSpace(Size, Alignment);
   }
 
   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
                                unsigned SectionID) {
-    return JMM->allocateCodeSection(Size, Alignment, SectionID);
+    return JMM->allocateSpace(Size, Alignment);
   }
 
   virtual void *getPointerToNamedFunction(const std::string &Name,
@@ -47,40 +47,6 @@
     return JMM->getPointerToNamedFunction(Name, AbortOnFailure);
   }
 
-  // Allocate ActualSize bytes, or more, for the named function. Return
-  // a pointer to the allocated memory and update Size to reflect how much
-  // memory was acutally allocated.
-  uint8_t *startFunctionBody(const char *Name, uintptr_t &Size) {
-    // FIXME: This should really reference the MCAsmInfo to get the global
-    //        prefix.
-    if (Name[0] == '_') ++Name;
-    Function *F = M->getFunction(Name);
-    // Some ObjC names have a prefixed \01 in the IR. If we failed to find
-    // the symbol and it's of the ObjC conventions (starts with "-" or
-    // "+"), try prepending a \01 and see if we can find it that way.
-    if (!F && (Name[0] == '-' || Name[0] == '+'))
-      F = M->getFunction((Twine("\1") + Name).str());
-    assert(F && "No matching function in JIT IR Module!");
-    return JMM->startFunctionBody(F, Size);
-  }
-
-  // Mark the end of the function, including how much of the allocated
-  // memory was actually used.
-  void endFunctionBody(const char *Name, uint8_t *FunctionStart,
-                       uint8_t *FunctionEnd) {
-    // FIXME: This should really reference the MCAsmInfo to get the global
-    //        prefix.
-    if (Name[0] == '_') ++Name;
-    Function *F = M->getFunction(Name);
-    // Some ObjC names have a prefixed \01 in the IR. If we failed to find
-    // the symbol and it's of the ObjC conventions (starts with "-" or
-    // "+"), try prepending a \01 and see if we can find it that way.
-    if (!F && (Name[0] == '-' || Name[0] == '+'))
-      F = M->getFunction((Twine("\1") + Name).str());
-    assert(F && "No matching function in JIT IR Module!");
-    JMM->endFunctionBody(F, FunctionStart, FunctionEnd);
-  }
-
 };
 
 } // End llvm namespace

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Fri Mar 30 11:45:19 2012
@@ -26,45 +26,290 @@
 
 namespace llvm {
 
-void RuntimeDyldImpl::extractFunction(StringRef Name, uint8_t *StartAddress,
-                                      uint8_t *EndAddress) {
-  // FIXME: DEPRECATED in favor of by-section allocation.
-  // Allocate memory for the function via the memory manager.
-  uintptr_t Size = EndAddress - StartAddress + 1;
-  uintptr_t AllocSize = Size;
-  uint8_t *Mem = MemMgr->startFunctionBody(Name.data(), AllocSize);
-  assert(Size >= (uint64_t)(EndAddress - StartAddress + 1) &&
-         "Memory manager failed to allocate enough memory!");
-  // Copy the function payload into the memory block.
-  memcpy(Mem, StartAddress, Size);
-  MemMgr->endFunctionBody(Name.data(), Mem, Mem + Size);
-  // Remember where we put it.
-  unsigned SectionID = Sections.size();
-  Sections.push_back(sys::MemoryBlock(Mem, Size));
+namespace {
+  // Helper for extensive error checking in debug builds.
+  error_code Check(error_code Err) {
+    if (Err) {
+      report_fatal_error(Err.message());
+    }
+    return Err;
+  }
+} // end anonymous namespace
 
-  // Default the assigned address for this symbol to wherever this
-  // allocated it.
-  SymbolTable[Name] = SymbolLoc(SectionID, 0);
-  DEBUG(dbgs() << "    allocated to [" << Mem << ", " << Mem + Size << "]\n");
-}
 
 // Resolve the relocations for all symbols we currently know about.
 void RuntimeDyldImpl::resolveRelocations() {
+  // First, resolve relocations assotiated with external symbols.
+  resolveSymbols();
+
   // Just iterate over the sections we have and resolve all the relocations
   // in them. Gross overkill, but it gets the job done.
   for (int i = 0, e = Sections.size(); i != e; ++i) {
-    reassignSectionAddress(i, SectionLoadAddress[i]);
+    reassignSectionAddress(i, Sections[i].LoadAddress);
   }
 }
 
 void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress,
                                         uint64_t TargetAddress) {
-  assert(SectionLocalMemToID.count(LocalAddress) &&
-         "Attempting to remap address of unknown section!");
-  unsigned SectionID = SectionLocalMemToID[LocalAddress];
-  reassignSectionAddress(SectionID, TargetAddress);
+  for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
+    if (Sections[i].Address == LocalAddress) {
+      reassignSectionAddress(i, TargetAddress);
+      return;
+    }
+  }
+  llvm_unreachable("Attempting to remap address of unknown section!");
+}
+
+bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
+  // FIXME: ObjectFile don't modify MemoryBuffer.
+  //        It should use const MemoryBuffer as parameter.
+  ObjectFile *obj
+    = ObjectFile::createObjectFile(const_cast<MemoryBuffer*>(InputBuffer));
+
+  Arch = (Triple::ArchType)obj->getArch();
+
+  LocalSymbolMap LocalSymbols;     // Functions and data symbols from the
+                                   // object file.
+  ObjSectionToIDMap LocalSections; // Used sections from the object file
+
+  error_code err;
+  // Parse symbols
+  DEBUG(dbgs() << "Parse symbols:\n");
+  for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols();
+       i != e; i.increment(err)) {
+    Check(err);
+    object::SymbolRef::Type SymType;
+    StringRef Name;
+    Check(i->getType(SymType));
+    Check(i->getName(Name));
+
+    if (SymType == object::SymbolRef::ST_Function ||
+        SymType == object::SymbolRef::ST_Data) {
+      uint64_t FileOffset;
+      uint32_t flags;
+      StringRef sData;
+      section_iterator si = obj->end_sections();
+      Check(i->getFileOffset(FileOffset));
+      Check(i->getFlags(flags));
+      Check(i->getSection(si));
+      if (si == obj->end_sections()) continue;
+      Check(si->getContents(sData));
+      const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() +
+                              (uintptr_t)FileOffset;
+      uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin());
+      unsigned SectionID
+        = findOrEmitSection(*si,
+                          SymType == object::SymbolRef::ST_Function,
+                          LocalSections);
+      bool isGlobal = flags & SymbolRef::SF_Global;
+      LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
+      DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset)
+                   << " flags: " << flags
+                   << " SID: " << SectionID
+                   << " Offset: " << format("%p", SectOffset));
+      if (isGlobal)
+        SymbolTable[Name] = SymbolLoc(SectionID, SectOffset);
+    }
+    DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n");
+  }
+
+  // Parse and proccess relocations
+  DEBUG(dbgs() << "Parse relocations:\n");
+  for (section_iterator si = obj->begin_sections(),
+       se = obj->end_sections(); si != se; si.increment(err)) {
+    Check(err);
+    bool isFirstRelocation = true;
+    unsigned SectionID = 0;
+    StubMap Stubs;
+
+    for (relocation_iterator i = si->begin_relocations(),
+         e = si->end_relocations(); i != e; i.increment(err)) {
+      Check(err);
+
+      // If it's first relocation in this section, find its SectionID
+      if (isFirstRelocation) {
+        SectionID = findOrEmitSection(*si, true, LocalSections);
+        DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
+        isFirstRelocation = false;
+      }
+
+      ObjRelocationInfo RI;
+      RI.SectionID = SectionID;
+      Check(i->getAdditionalInfo(RI.AdditionalInfo));
+      Check(i->getOffset(RI.Offset));
+      Check(i->getSymbol(RI.Symbol));
+      Check(i->getType(RI.Type));
+
+      DEBUG(dbgs() << "\t\tAddend: " << RI.AdditionalInfo
+                   << " Offset: " << format("%p", (uintptr_t)RI.Offset)
+                   << " Type: " << (uint32_t)(RI.Type & 0xffffffffL)
+                   << "\n");
+      processRelocationRef(RI, *obj, LocalSections, LocalSymbols, Stubs);
+    }
+  }
+  return false;
 }
 
+unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section,
+                                      bool IsCode) {
+
+  unsigned StubBufSize = 0,
+           StubSize = getMaxStubSize();
+  error_code err;
+  if (StubSize > 0) {
+    for (relocation_iterator i = Section.begin_relocations(),
+         e = Section.end_relocations(); i != e; i.increment(err))
+      StubBufSize += StubSize;
+  }
+  StringRef data;
+  uint64_t Alignment64;
+  Check(Section.getContents(data));
+  Check(Section.getAlignment(Alignment64));
+
+  unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
+  unsigned DataSize = data.size();
+  unsigned Allocate = DataSize + StubBufSize;
+  unsigned SectionID = Sections.size();
+  const char *pData = data.data();
+  uint8_t *Addr = IsCode
+    ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID)
+    : MemMgr->allocateDataSection(Allocate, Alignment, SectionID);
+
+  memcpy(Addr, pData, DataSize);
+  DEBUG(dbgs() << "emitSection SectionID: " << SectionID
+               << " obj addr: " << format("%p", pData)
+               << " new addr: " << format("%p", Addr)
+               << " DataSize: " << DataSize
+               << " StubBufSize: " << StubBufSize
+               << " Allocate: " << Allocate
+               << "\n");
+  Sections.push_back(SectionEntry(Addr, Allocate, DataSize,(uintptr_t)pData));
+  return SectionID;
+}
+
+unsigned RuntimeDyldImpl::findOrEmitSection(const SectionRef &Section,
+                                            bool IsCode,
+                                            ObjSectionToIDMap &LocalSections) {
+
+  unsigned SectionID = 0;
+  ObjSectionToIDMap::iterator i = LocalSections.find(Section);
+  if (i != LocalSections.end())
+    SectionID = i->second;
+  else {
+    SectionID = emitSection(Section, IsCode);
+    LocalSections[Section] = SectionID;
+  }
+  return SectionID;
+}
+
+void RuntimeDyldImpl::AddRelocation(const RelocationValueRef &Value,
+                                   unsigned SectionID, uintptr_t Offset,
+                                   uint32_t RelType) {
+  DEBUG(dbgs() << "AddRelocation SymNamePtr: " << format("%p", Value.SymbolName)
+               << " SID: " << Value.SectionID
+               << " Addend: " << format("%p", Value.Addend)
+               << " Offset: " << format("%p", Offset)
+               << " RelType: " << format("%x", RelType)
+               << "\n");
+
+  if (Value.SymbolName == 0) {
+    Relocations[Value.SectionID].push_back(RelocationEntry(
+      SectionID,
+      Offset,
+      RelType,
+      Value.Addend));
+  } else
+    SymbolRelocations[Value.SymbolName].push_back(RelocationEntry(
+      SectionID,
+      Offset,
+      RelType,
+      Value.Addend));
+}
+
+uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
+  // TODO: There is only ARM far stub now. We should add the Thumb stub,
+  // and stubs for branches Thumb - ARM and ARM - Thumb.
+  if (Arch == Triple::arm) {
+    uint32_t *StubAddr = (uint32_t*)Addr;
+    *StubAddr = 0xe51ff004; // ldr pc,<label>
+    return (uint8_t*)++StubAddr;
+  }
+  else
+    return Addr;
+}
+
+// Assign an address to a symbol name and resolve all the relocations
+// associated with it.
+void RuntimeDyldImpl::reassignSectionAddress(unsigned SectionID,
+                                             uint64_t Addr) {
+  // The address to use for relocation resolution is not
+  // the address of the local section buffer. We must be doing
+  // a remote execution environment of some sort. Re-apply any
+  // relocations referencing this section with the given address.
+  //
+  // Addr is a uint64_t because we can't assume the pointer width
+  // of the target is the same as that of the host. Just use a generic
+  // "big enough" type.
+  Sections[SectionID].LoadAddress = Addr;
+  DEBUG(dbgs() << "Resolving relocations Section #" << SectionID
+          << "\t" << format("%p", (uint8_t *)Addr)
+          << "\n");
+  resolveRelocationList(Relocations[SectionID], Addr);
+}
+
+void RuntimeDyldImpl::resolveRelocationEntry(const RelocationEntry &RE,
+                                             uint64_t Value) {
+    uint8_t *Target = Sections[RE.SectionID].Address + RE.Offset;
+    DEBUG(dbgs() << "\tSectionID: " << RE.SectionID
+          << " + " << RE.Offset << " (" << format("%p", Target) << ")"
+          << " Data: " << RE.Data
+          << " Addend: " << RE.Addend
+          << "\n");
+
+    resolveRelocation(Target, Sections[RE.SectionID].LoadAddress + RE.Offset,
+                      Value, RE.Data, RE.Addend);
+}
+
+void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
+                                            uint64_t Value) {
+  for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
+    resolveRelocationEntry(Relocs[i], Value);
+  }
+}
+
+// resolveSymbols - Resolve any relocations to the specified symbols if
+// we know where it lives.
+void RuntimeDyldImpl::resolveSymbols() {
+  StringMap<RelocationList>::iterator i = SymbolRelocations.begin(),
+                                      e = SymbolRelocations.end();
+  for (; i != e; i++) {
+    StringRef Name = i->first();
+    RelocationList &Relocs = i->second;
+    StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(Name);
+    if (Loc == SymbolTable.end()) {
+      // This is an external symbol, try to get it address from
+      // MemoryManager.
+      uint8_t *Addr = (uint8_t*) MemMgr->getPointerToNamedFunction(Name.data(),
+                                                                   true);
+      DEBUG(dbgs() << "Resolving relocations Name: " << Name
+              << "\t" << format("%p", Addr)
+              << "\n");
+      resolveRelocationList(Relocs, (uintptr_t)Addr);
+    } else {
+      // Change the relocation to be section relative rather than symbol
+      // relative and move it to the resolved relocation list.
+      DEBUG(dbgs() << "Resolving symbol '" << Name << "'\n");
+      for (int i = 0, e = Relocs.size(); i != e; ++i) {
+        RelocationEntry Entry = Relocs[i];
+        Entry.Addend += Loc->second.second;
+        Relocations[Loc->second.first].push_back(Entry);
+      }
+      Relocs.clear();
+    }
+  }
+}
+
+
 //===----------------------------------------------------------------------===//
 // RuntimeDyld class implementation
 RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp Fri Mar 30 11:45:19 2012
@@ -25,222 +25,58 @@
 
 namespace llvm {
 
-namespace {
 
-// FIXME: this function should probably not live here...
-//
-// Returns the name and address of an unrelocated symbol in an ELF section
-void getSymbolInfo(symbol_iterator Sym, uint64_t &Addr, StringRef &Name) {
-  //FIXME: error checking here required to catch corrupt ELF objects...
-  error_code Err = Sym->getName(Name);
-
-  uint64_t AddrInSection;
-  Err = Sym->getAddress(AddrInSection);
-
-  SectionRef empty_section;
-  section_iterator Section(empty_section);
-  Err = Sym->getSection(Section);
-
-  StringRef SectionContents;
-  Section->getContents(SectionContents);
-
-  Addr = reinterpret_cast<uint64_t>(SectionContents.data()) + AddrInSection;
-}
-
-}
-
-bool RuntimeDyldELF::loadObject(MemoryBuffer *InputBuffer) {
-  if (!isCompatibleFormat(InputBuffer))
-    return true;
-
-  OwningPtr<ObjectFile> Obj(ObjectFile::createELFObjectFile(InputBuffer));
-
-  Arch = Obj->getArch();
-
-  // Map address in the Object file image to function names
-  IntervalMap<uint64_t, StringRef>::Allocator A;
-  IntervalMap<uint64_t, StringRef> FuncMap(A);
-
-  // This is a bit of a hack.  The ObjectFile we've just loaded reports
-  // section addresses as 0 and doesn't provide access to the section
-  // offset (from which we could calculate the address.  Instead,
-  // we're storing the address when it comes up in the ST_Debug case
-  // below.
-  //
-  StringMap<uint64_t> DebugSymbolMap;
-
-  symbol_iterator SymEnd = Obj->end_symbols();
-  error_code Err;
-  for (symbol_iterator Sym = Obj->begin_symbols();
-       Sym != SymEnd; Sym.increment(Err)) {
-    SymbolRef::Type Type;
-    Sym->getType(Type);
-    if (Type == SymbolRef::ST_Function) {
-      StringRef Name;
-      uint64_t Addr;
-      getSymbolInfo(Sym, Addr, Name);
-
-      uint64_t Size;
-      Err = Sym->getSize(Size);
-
-      uint8_t *Start;
-      uint8_t *End;
-      Start = reinterpret_cast<uint8_t*>(Addr);
-      End   = reinterpret_cast<uint8_t*>(Addr + Size - 1);
-
-      extractFunction(Name, Start, End);
-      FuncMap.insert(Addr, Addr + Size - 1, Name);
-    } else if (Type == SymbolRef::ST_Debug) {
-      // This case helps us find section addresses
-      StringRef Name;
-      uint64_t Addr;
-      getSymbolInfo(Sym, Addr, Name);
-      DebugSymbolMap[Name] = Addr;
-    }
-  }
-
-  // Iterate through the relocations for this object
-  section_iterator SecEnd = Obj->end_sections();
-  for (section_iterator Sec = Obj->begin_sections();
-       Sec != SecEnd; Sec.increment(Err)) {
-    StringRef SecName;
-    uint64_t  SecAddr;
-    Sec->getName(SecName);
-    // Ignore sections that aren't in our map
-    if (DebugSymbolMap.find(SecName) == DebugSymbolMap.end()) {
-      continue;
-    }
-    SecAddr = DebugSymbolMap[SecName];
-    relocation_iterator RelEnd = Sec->end_relocations();
-    for (relocation_iterator Rel = Sec->begin_relocations();
-         Rel != RelEnd; Rel.increment(Err)) {
-      uint64_t RelOffset;
-      uint64_t RelType;
-      int64_t RelAddend;
-      SymbolRef RelSym;
-      StringRef SymName;
-      uint64_t SymAddr;
-      uint64_t SymOffset;
-
-      Rel->getAddress(RelOffset);
-      Rel->getType(RelType);
-      Rel->getAdditionalInfo(RelAddend);
-      Rel->getSymbol(RelSym);
-      RelSym.getName(SymName);
-      RelSym.getAddress(SymAddr);
-      RelSym.getFileOffset(SymOffset);
-
-      // If this relocation is inside a function, we want to store the
-      // function name and a function-relative offset
-      IntervalMap<uint64_t, StringRef>::iterator ContainingFunc
-        = FuncMap.find(SecAddr + RelOffset);
-      if (ContainingFunc.valid()) {
-        // Re-base the relocation to make it relative to the target function
-        RelOffset = (SecAddr + RelOffset) - ContainingFunc.start();
-        Relocations[SymName].push_back(RelocationEntry(ContainingFunc.value(),
-                                                       RelOffset,
-                                                       RelType,
-                                                       RelAddend,
-                                                       true));
-      } else {
-        Relocations[SymName].push_back(RelocationEntry(SecName,
-                                                       RelOffset,
-                                                       RelType,
-                                                       RelAddend,
-                                                       false));
-      }
-    }
-  }
-  return false;
-}
-
-void RuntimeDyldELF::resolveRelocations() {
-  // FIXME: deprecated. should be changed to use the by-section
-  // allocation and relocation scheme.
-
-  // Just iterate over the symbols in our symbol table and assign their
-  // addresses.
-  StringMap<SymbolLoc>::iterator i = SymbolTable.begin();
-  StringMap<SymbolLoc>::iterator e = SymbolTable.end();
-  for (;i != e; ++i) {
-    assert (i->getValue().second == 0 && "non-zero offset in by-function sym!");
-    reassignSymbolAddress(i->getKey(),
-                          (uint8_t*)Sections[i->getValue().first].base());
-  }
-}
-
-void RuntimeDyldELF::resolveX86_64Relocation(StringRef Name,
-                                             uint8_t *Addr,
-                                             const RelocationEntry &RE) {
-  uint8_t *TargetAddr;
-  if (RE.IsFunctionRelative) {
-    StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(RE.Target);
-    assert(Loc != SymbolTable.end() && "Function for relocation not found");
-    TargetAddr =
-      reinterpret_cast<uint8_t*>(Sections[Loc->second.first].base()) +
-      Loc->second.second + RE.Offset;
-  } else {
-    // FIXME: Get the address of the target section and add that to RE.Offset
-    llvm_unreachable("Non-function relocation not implemented yet!");
-  }
-
-  switch (RE.Type) {
-  default: llvm_unreachable("Relocation type not implemented yet!");
+void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
+                                             uint64_t FinalAddress,
+                                             uint64_t Value,
+                                             uint32_t Type,
+                                             int64_t Addend) {
+  switch (Type) {
+  default:
+    llvm_unreachable("Relocation type not implemented yet!");
+  break;
   case ELF::R_X86_64_64: {
-    uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
-    *Target = Addr + RE.Addend;
+    uint64_t *Target = (uint64_t*)(LocalAddress);
+    *Target = Value + Addend;
     break;
   }
   case ELF::R_X86_64_32:
   case ELF::R_X86_64_32S: {
-    uint64_t Value = reinterpret_cast<uint64_t>(Addr) + RE.Addend;
+    Value += Addend;
     // FIXME: Handle the possibility of this assertion failing
-    assert((RE.Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
-           (RE.Type == ELF::R_X86_64_32S &&
+    assert((Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
+           (Type == ELF::R_X86_64_32S &&
             (Value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL));
     uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
-    uint32_t *Target = reinterpret_cast<uint32_t*>(TargetAddr);
+    uint32_t *Target = reinterpret_cast<uint32_t*>(LocalAddress);
     *Target = TruncatedAddr;
     break;
   }
   case ELF::R_X86_64_PC32: {
-    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
-    uint64_t RealOffset = *Placeholder +
-                           reinterpret_cast<uint64_t>(Addr) +
-                           RE.Addend - reinterpret_cast<uint64_t>(TargetAddr);
-    assert((RealOffset & 0xFFFFFFFF) == RealOffset);
-    uint32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
+    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
+    int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
+    assert(RealOffset <= 214783647 && RealOffset >= -214783648);
+    int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
     *Placeholder = TruncOffset;
     break;
   }
   }
 }
 
-void RuntimeDyldELF::resolveX86Relocation(StringRef Name,
-                                          uint8_t *Addr,
-                                          const RelocationEntry &RE) {
-  uint8_t *TargetAddr;
-  if (RE.IsFunctionRelative) {
-    StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(RE.Target);
-    assert(Loc != SymbolTable.end() && "Function for relocation not found");
-    TargetAddr =
-      reinterpret_cast<uint8_t*>(Sections[Loc->second.first].base()) +
-      Loc->second.second + RE.Offset;
-  } else {
-    // FIXME: Get the address of the target section and add that to RE.Offset
-    llvm_unreachable("Non-function relocation not implemented yet!");
-  }
-
-  switch (RE.Type) {
+void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress,
+                                          uint32_t FinalAddress,
+                                          uint32_t Value,
+                                          uint32_t Type,
+                                          int32_t Addend) {
+  switch (Type) {
   case ELF::R_386_32: {
-    uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
-    *Target = Addr + RE.Addend;
+    uint32_t *Target = (uint32_t*)(LocalAddress);
+    *Target = Value + Addend;
     break;
   }
   case ELF::R_386_PC32: {
-    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
-    uint32_t RealOffset = *Placeholder + reinterpret_cast<uintptr_t>(Addr) +
-                           RE.Addend - reinterpret_cast<uintptr_t>(TargetAddr);
+    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
+    uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
     *Placeholder = RealOffset;
     break;
     }
@@ -248,57 +84,174 @@
       // There are other relocation types, but it appears these are the
       //  only ones currently used by the LLVM ELF object writer
       llvm_unreachable("Relocation type not implemented yet!");
+      break;
   }
 }
 
-void RuntimeDyldELF::resolveArmRelocation(StringRef Name,
-                                          uint8_t *Addr,
-                                          const RelocationEntry &RE) {
+void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress,
+                                          uint32_t FinalAddress,
+                                          uint32_t Value,
+                                          uint32_t Type,
+                                          int32_t Addend) {
+  // TODO: Add Thumb relocations.
+  uint32_t* TargetPtr = (uint32_t*)LocalAddress;
+  Value += Addend;
+
+  DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " << LocalAddress
+               << " FinalAddress: " << format("%p",FinalAddress)
+               << " Value: " << format("%x",Value)
+               << " Type: " << format("%x",Type)
+               << " Addend: " << format("%x",Addend)
+               << "\n");
+
+  switch(Type) {
+  default:
+    llvm_unreachable("Not implemented relocation type!");
+
+  // Just write 32bit value to relocation address
+  case ELF::R_ARM_ABS32 :
+    *TargetPtr = 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 :
+    Value = Value & 0xFFFF;
+    *TargetPtr |= 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 :
+    Value = (Value >> 16) & 0xFFFF;
+    *TargetPtr |= 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 :
+    int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8);
+    RelValue = (RelValue & 0x03FFFFFC) >> 2;
+    *TargetPtr &= 0xFF000000;
+    *TargetPtr |= RelValue;
+    break;
+  }
 }
 
-void RuntimeDyldELF::resolveRelocation(StringRef Name,
-                                       uint8_t *Addr,
-                                       const RelocationEntry &RE) {
+void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
+                                       uint64_t FinalAddress,
+                                       uint64_t Value,
+                                       uint32_t Type,
+                                       int64_t Addend) {
   switch (Arch) {
   case Triple::x86_64:
-    resolveX86_64Relocation(Name, Addr, RE);
+    resolveX86_64Relocation(LocalAddress, FinalAddress, Value, Type, Addend);
     break;
   case Triple::x86:
-    resolveX86Relocation(Name, Addr, RE);
-    break;
-  case Triple::arm:
-    resolveArmRelocation(Name, Addr, RE);
+    resolveX86Relocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
+                         (uint32_t)(Value & 0xffffffffL), Type,
+                         (uint32_t)(Addend & 0xffffffffL));
+    break;
+  case Triple::arm:    // Fall through.
+  case Triple::thumb:
+    resolveARMRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
+                         (uint32_t)(Value & 0xffffffffL), Type,
+                         (uint32_t)(Addend & 0xffffffffL));
     break;
   default: llvm_unreachable("Unsupported CPU type!");
   }
 }
 
-void RuntimeDyldELF::reassignSymbolAddress(StringRef Name, uint8_t *Addr) {
-  // FIXME: deprecated. switch to reassignSectionAddress() instead.
-  //
-  // Actually moving the symbol address requires by-section mapping.
-  assert(Sections[SymbolTable.lookup(Name).first].base() == (void*)Addr &&
-         "Unable to relocate section in by-function JIT allocation model!");
-
-  RelocationList &Relocs = Relocations[Name];
-  for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
-    RelocationEntry &RE = Relocs[i];
-    resolveRelocation(Name, Addr, RE);
+void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
+                                          const ObjectFile &Obj,
+                                          ObjSectionToIDMap &ObjSectionToID,
+                                          LocalSymbolMap &Symbols,
+                                          StubMap &Stubs) {
+
+  uint32_t RelType = (uint32_t)(Rel.Type & 0xffffffffL);
+  intptr_t Addend = (intptr_t)Rel.AdditionalInfo;
+  RelocationValueRef Value;
+  StringRef TargetName;
+  const SymbolRef &Symbol = Rel.Symbol;
+  Symbol.getName(TargetName);
+  DEBUG(dbgs() << "\t\tRelType: " << RelType
+               << " Addend: " << Addend
+               << " TargetName: " << TargetName
+               << "\n");
+  // First look the symbol in object file symbols.
+  LocalSymbolMap::iterator lsi = Symbols.find(TargetName.data());
+  if (lsi != Symbols.end()) {
+    Value.SectionID = lsi->second.first;
+    Value.Addend = lsi->second.second;
+  } else {
+    // Second look the symbol in global symbol table.
+    StringMap<SymbolLoc>::iterator gsi = SymbolTable.find(TargetName.data());
+    if (gsi != SymbolTable.end()) {
+      Value.SectionID = gsi->second.first;
+      Value.Addend = gsi->second.second;
+    } else {
+      SymbolRef::Type SymType;
+      Symbol.getType(SymType);
+      switch (SymType) {
+        case SymbolRef::ST_Debug: {
+          // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
+          // and can be changed by another developers. Maybe best way is add
+          // a new symbol type ST_Section to SymbolRef and use it.
+          section_iterator si = Obj.end_sections();
+          Symbol.getSection(si);
+          if (si == Obj.end_sections())
+            llvm_unreachable("Symbol section not found, bad object file format!");
+          DEBUG(dbgs() << "\t\tThis is section symbol\n");
+          Value.SectionID = findOrEmitSection((*si), true, ObjSectionToID);
+          Value.Addend = Addend;
+          break;
+        }
+        case SymbolRef::ST_Unknown: {
+          Value.SymbolName = TargetName.data();
+          Value.Addend = Addend;
+          break;
+        }
+        default:
+          llvm_unreachable("Unresolved symbol type!");
+          break;
+      }
+    }
   }
-}
-
-// Assign an address to a symbol name and resolve all the relocations
-// associated with it.
-void RuntimeDyldELF::reassignSectionAddress(unsigned SectionID, uint64_t Addr) {
-  // The address to use for relocation resolution is not
-  // the address of the local section buffer. We must be doing
-  // a remote execution environment of some sort. Re-apply any
-  // relocations referencing this section with the given address.
-  //
-  // Addr is a uint64_t because we can't assume the pointer width
-  // of the target is the same as that of the host. Just use a generic
-  // "big enough" type.
-  assert(0);
+  DEBUG(dbgs() << "\t\tRel.SectionID: " << Rel.SectionID
+               << " Rel.Offset: " << Rel.Offset
+               << "\n");
+  if (Arch == Triple::arm &&
+      (RelType == ELF::R_ARM_PC24 ||
+       RelType == ELF::R_ARM_CALL ||
+       RelType == ELF::R_ARM_JUMP24)) {
+    // This is an ARM branch relocation, need to use a stub function.
+    DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.");
+    SectionEntry &Section = Sections[Rel.SectionID];
+    uint8_t *Target = Section.Address + Rel.Offset;
+
+    //  Look up for existing stub.
+    StubMap::const_iterator i = Stubs.find(Value);
+    if (i != Stubs.end()) {
+      resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address +
+                        i->second, RelType, 0);
+      DEBUG(dbgs() << " Stub function found\n");
+    } else {
+      // Create a new stub function.
+      DEBUG(dbgs() << " Create a new stub function\n");
+      Stubs[Value] = Section.StubOffset;
+      uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+                                                   Section.StubOffset);
+      AddRelocation(Value, Rel.SectionID,
+                    StubTargetAddr - Section.Address, ELF::R_ARM_ABS32);
+      resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address +
+                        Section.StubOffset, RelType, 0);
+      Section.StubOffset += getMaxStubSize();
+    }
+  } else
+    AddRelocation(Value, Rel.SectionID, Rel.Offset, RelType);
 }
 
 bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h Fri Mar 30 11:45:19 2012
@@ -21,158 +21,42 @@
 
 namespace llvm {
 class RuntimeDyldELF : public RuntimeDyldImpl {
-    // For each symbol, keep a list of relocations based on it. Anytime
-    // its address is reassigned (the JIT re-compiled the function, e.g.),
-    // the relocations get re-resolved.
-    struct RelocationEntry {
-      // Function or section this relocation is contained in.
-      std::string Target;
-      // Offset into the target function or section for the relocation.
-      uint32_t    Offset;
-      // Relocation type
-      uint32_t    Type;
-      // Addend encoded in the instruction itself, if any.
-      int32_t     Addend;
-      // Has the relocation been recalcuated as an offset within a function?
-      bool        IsFunctionRelative;
-      // Has this relocation been resolved previously?
-      bool        isResolved;
-
-      RelocationEntry(StringRef t,
-                      uint32_t offset,
-                      uint32_t type,
-                      int32_t addend,
-                      bool isFunctionRelative)
-        : Target(t)
-        , Offset(offset)
-        , Type(type)
-        , Addend(addend)
-        , IsFunctionRelative(isFunctionRelative)
-        , isResolved(false) { }
-    };
-    typedef SmallVector<RelocationEntry, 4> RelocationList;
-    StringMap<RelocationList> Relocations;
-    unsigned Arch;
-
-    void resolveRelocations();
-
-    void resolveX86_64Relocation(StringRef Name,
-                                 uint8_t *Addr,
-                                 const RelocationEntry &RE);
-
-    void resolveX86Relocation(StringRef Name,
-                              uint8_t *Addr,
-                              const RelocationEntry &RE);
-
-    void resolveArmRelocation(StringRef Name,
-                              uint8_t *Addr,
-                              const RelocationEntry &RE);
-
-    void resolveRelocation(StringRef Name,
-                           uint8_t *Addr,
-                           const RelocationEntry &RE);
+protected:
+  void resolveX86_64Relocation(uint8_t *LocalAddress,
+                               uint64_t FinalAddress,
+                               uint64_t Value,
+                               uint32_t Type,
+                               int64_t Addend);
+
+  void resolveX86Relocation(uint8_t *LocalAddress,
+                            uint32_t FinalAddress,
+                            uint32_t Value,
+                            uint32_t Type,
+                            int32_t Addend);
+
+  void resolveARMRelocation(uint8_t *LocalAddress,
+                            uint32_t FinalAddress,
+                            uint32_t Value,
+                            uint32_t Type,
+                            int32_t Addend);
+
+  virtual void resolveRelocation(uint8_t *LocalAddress,
+                                 uint64_t FinalAddress,
+                                 uint64_t Value,
+                                 uint32_t Type,
+                                 int64_t Addend);
+
+  virtual void processRelocationRef(const ObjRelocationInfo &Rel,
+                                    const ObjectFile &Obj,
+                                    ObjSectionToIDMap &ObjSectionToID,
+                                    LocalSymbolMap &Symbols, StubMap &Stubs);
 
 public:
   RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
 
-  bool loadObject(MemoryBuffer *InputBuffer);
-
-  void reassignSymbolAddress(StringRef Name, uint8_t *Addr);
-  void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
-
-  bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
-};
-
-} // end namespace llvm
-
-#endif 
-
-//===-- RuntimeDyldELF.h - Run-time dynamic linker for MC-JIT ---*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// ELF support for MC-JIT runtime dynamic linker.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_RUNTIME_DYLD_ELF_H
-#define LLVM_RUNTIME_DYLD_ELF_H
-
-#include "RuntimeDyldImpl.h"
-
-using namespace llvm;
-
-
-namespace llvm {
-class RuntimeDyldELF : public RuntimeDyldImpl {
-    // For each symbol, keep a list of relocations based on it. Anytime
-    // its address is reassigned (the JIT re-compiled the function, e.g.),
-    // the relocations get re-resolved.
-    struct RelocationEntry {
-      // Function or section this relocation is contained in.
-      std::string Target;
-      // Offset into the target function or section for the relocation.
-      uint32_t    Offset;
-      // Relocation type
-      uint32_t    Type;
-      // Addend encoded in the instruction itself, if any.
-      int32_t     Addend;
-      // Has the relocation been recalcuated as an offset within a function?
-      bool        IsFunctionRelative;
-      // Has this relocation been resolved previously?
-      bool        isResolved;
-
-      RelocationEntry(StringRef t,
-                      uint32_t offset,
-                      uint32_t type,
-                      int32_t addend,
-                      bool isFunctionRelative)
-        : Target(t)
-        , Offset(offset)
-        , Type(type)
-        , Addend(addend)
-        , IsFunctionRelative(isFunctionRelative)
-        , isResolved(false) { }
-    };
-    typedef SmallVector<RelocationEntry, 4> RelocationList;
-    StringMap<RelocationList> Relocations;
-    unsigned Arch;
-
-    void resolveRelocations();
-
-    void resolveX86_64Relocation(StringRef Name,
-                                 uint8_t *Addr,
-                                 const RelocationEntry &RE);
-
-    void resolveX86Relocation(StringRef Name,
-                              uint8_t *Addr,
-                              const RelocationEntry &RE);
-
-    void resolveArmRelocation(StringRef Name,
-                              uint8_t *Addr,
-                              const RelocationEntry &RE);
-
-    void resolveRelocation(StringRef Name,
-                           uint8_t *Addr,
-                           const RelocationEntry &RE);
-
-public:
-  RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
-
-  bool loadObject(MemoryBuffer *InputBuffer);
-
-  void reassignSymbolAddress(StringRef Name, uint8_t *Addr);
-  void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
-
   bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
 };
 
 } // end namespace llvm
 
-#endif 
-
+#endif

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h Fri Mar 30 11:45:19 2012
@@ -15,45 +15,125 @@
 #define LLVM_RUNTIME_DYLD_IMPL_H
 
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/Object/ObjectFile.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
 #include "llvm/Support/Memory.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/system_error.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/ADT/Triple.h"
+#include <map>
+#include "llvm/Support/Format.h"
 
 using namespace llvm;
+using namespace llvm::object;
 
 namespace llvm {
+
+class SectionEntry {
+public:
+  uint8_t* Address;
+  size_t Size;
+  uint64_t LoadAddress;   // For each section, the address it will be
+                          // considered to live at for relocations. The same
+                          // as the pointer to the above memory block for
+                          // hosted JITs.
+  uintptr_t StubOffset;   // It's used for architecturies with stub
+                          // functions for far relocations like ARM.
+  uintptr_t ObjAddress;   // Section address in object file. It's use for
+                          // calculate MachO relocation addend
+  SectionEntry(uint8_t* address, size_t size, uintptr_t stubOffset,
+               uintptr_t objAddress)
+    : Address(address), Size(size), LoadAddress((uintptr_t)address),
+      StubOffset(stubOffset), ObjAddress(objAddress) {}
+};
+
+class RelocationEntry {
+public:
+  unsigned    SectionID;  // Section the relocation is contained in.
+  uintptr_t   Offset;     // Offset into the section for the relocation.
+  uint32_t    Data;       // Relocatino data. Including type of relocation
+                          // and another flags and parameners from
+  intptr_t    Addend;     // Addend encoded in the instruction itself, if any,
+                          // plus the offset into the source section for
+                          // the symbol once the relocation is resolvable.
+  RelocationEntry(unsigned id, uint64_t offset, uint32_t data, int64_t addend)
+    : SectionID(id), Offset(offset), Data(data), Addend(addend) {}
+};
+
+// Raw relocation data from object file
+class ObjRelocationInfo {
+public:
+  unsigned  SectionID;
+  uint64_t  Offset;
+  SymbolRef Symbol;
+  uint64_t  Type;
+  int64_t   AdditionalInfo;
+};
+
+class RelocationValueRef {
+public:
+  unsigned  SectionID;
+  intptr_t  Addend;
+  const char *SymbolName;
+  RelocationValueRef(): SectionID(0), Addend(0), SymbolName(0) {}
+
+  inline bool operator==(const RelocationValueRef &Other) const {
+    return std::memcmp(this, &Other, sizeof(RelocationValueRef)) == 0;
+  }
+  inline bool operator <(const RelocationValueRef &Other) const {
+    return std::memcmp(this, &Other, sizeof(RelocationValueRef)) < 0;
+  }
+};
+
 class RuntimeDyldImpl {
 protected:
-  unsigned CPUType;
-  unsigned CPUSubtype;
-
   // The MemoryManager to load objects into.
   RTDyldMemoryManager *MemMgr;
 
-  // For each section, we have a MemoryBlock of it's data.
-  // Indexed by SectionID.
-  SmallVector<sys::MemoryBlock, 32> Sections;
-  // For each section, the address it will be considered to live at for
-  // relocations. The same as the pointer to the above memory block for hosted
-  // JITs. Indexed by SectionID.
-  SmallVector<uint64_t, 32> SectionLoadAddress;
-
-  // Keep a map of starting local address to the SectionID which references it.
-  // Lookup function for when we assign virtual addresses.
-  DenseMap<void *, unsigned> SectionLocalMemToID;
+  // A list of emmitted sections.
+  typedef SmallVector<SectionEntry, 64> SectionList;
+  SectionList Sections;
+
+  // Keep a map of sections from object file to the SectionID which
+  // references it.
+  typedef std::map<SectionRef, unsigned> ObjSectionToIDMap;
 
   // Master symbol table. As modules are loaded and external symbols are
   // resolved, their addresses are stored here as a SectionID/Offset pair.
-  typedef std::pair<unsigned, uint64_t> SymbolLoc;
+  typedef std::pair<unsigned, uintptr_t> SymbolLoc;
   StringMap<SymbolLoc> SymbolTable;
+  typedef DenseMap<const char*, SymbolLoc> LocalSymbolMap;
+
+  // For each symbol, keep a list of relocations based on it. Anytime
+  // its address is reassigned (the JIT re-compiled the function, e.g.),
+  // the relocations get re-resolved.
+  // The symbol (or section) the relocation is sourced from is the Key
+  // in the relocation list where it's stored.
+  typedef SmallVector<RelocationEntry, 64> RelocationList;
+  // Relocations to sections already loaded. Indexed by SectionID which is the
+  // source of the address. The target where the address will be writen is
+  // SectionID/Offset in the relocation itself.
+  DenseMap<unsigned, RelocationList> Relocations;
+  // Relocations to external symbols that are not yet resolved.
+  // Indexed by symbol name.
+  StringMap<RelocationList> SymbolRelocations;
+
+  typedef std::map<RelocationValueRef, uintptr_t> StubMap;
+
+  Triple::ArchType Arch;
+
+  inline unsigned getMaxStubSize() {
+    if (Arch == Triple::arm || Arch == Triple::thumb)
+      return 8; // 32-bit instruction and 32-bit address
+    else
+      return 0;
+  }
 
   bool HasError;
   std::string ErrorStr;
@@ -66,17 +146,62 @@
   }
 
   uint8_t *getSectionAddress(unsigned SectionID) {
-    return (uint8_t*)Sections[SectionID].base();
+    return (uint8_t*)Sections[SectionID].Address;
   }
-  void extractFunction(StringRef Name, uint8_t *StartAddress,
-                       uint8_t *EndAddress);
 
+  /// \brief Emits section data from the object file to the MemoryManager.
+  /// \param IsCode if it's true then allocateCodeSection() will be
+  ///        used for emmits, else allocateDataSection() will be used.
+  /// \return SectionID.
+  unsigned emitSection(const SectionRef &Section, bool IsCode);
+
+  /// \brief Find Section in LocalSections. If the secton is not found - emit
+  ///        it and store in LocalSections.
+  /// \param IsCode if it's true then allocateCodeSection() will be
+  ///        used for emmits, else allocateDataSection() will be used.
+  /// \return SectionID.
+  unsigned findOrEmitSection(const SectionRef &Section, bool IsCode,
+                             ObjSectionToIDMap &LocalSections);
+
+  /// \brief If Value.SymbolName is NULL then store relocation to the
+  ///        Relocations, else store it in the SymbolRelocations.
+  void AddRelocation(const RelocationValueRef &Value, unsigned SectionID,
+                     uintptr_t Offset, uint32_t RelType);
+
+  /// \brief Emits long jump instruction to Addr.
+  /// \return Pointer to the memory area for emitting target address.
+  uint8_t* createStubFunction(uint8_t *Addr);
+
+  /// \brief Resolves relocations from Relocs list with address from Value.
+  void resolveRelocationList(const RelocationList &Relocs, uint64_t Value);
+  void resolveRelocationEntry(const RelocationEntry &RE, uint64_t Value);
+
+  /// \brief A object file specific relocation resolver
+  /// \param Address Address to apply the relocation action
+  /// \param Value Target symbol address to apply the relocation action
+  /// \param Type object file specific relocation type
+  /// \param Addend A constant addend used to compute the value to be stored
+  ///        into the relocatable field
+  virtual void resolveRelocation(uint8_t *LocalAddress,
+                                 uint64_t FinalAddress,
+                                 uint64_t Value,
+                                 uint32_t Type,
+                                 int64_t Addend) = 0;
+
+  /// \brief Parses the object file relocation and store it to Relocations
+  ///        or SymbolRelocations. Its depend from object file type.
+  virtual void processRelocationRef(const ObjRelocationInfo &Rel,
+                                    const ObjectFile &Obj,
+                                    ObjSectionToIDMap &ObjSectionToID,
+                                    LocalSymbolMap &Symbols, StubMap &Stubs) = 0;
+
+  void resolveSymbols();
 public:
   RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
 
   virtual ~RuntimeDyldImpl();
 
-  virtual bool loadObject(MemoryBuffer *InputBuffer) = 0;
+  bool loadObject(const MemoryBuffer *InputBuffer);
 
   void *getSymbolAddress(StringRef Name) {
     // FIXME: Just look up as a function for now. Overly simple of course.
@@ -87,9 +212,9 @@
     return getSectionAddress(Loc.first) + Loc.second;
   }
 
-  virtual void resolveRelocations();
+  void resolveRelocations();
 
-  virtual void reassignSectionAddress(unsigned SectionID, uint64_t Addr) = 0;
+  void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
 
   void mapSectionAddress(void *LocalAddress, uint64_t TargetAddress);
 
@@ -103,6 +228,7 @@
   StringRef getErrorString() { return ErrorStr; }
 
   virtual bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const = 0;
+
 };
 
 } // end namespace llvm

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp Fri Mar 30 11:45:19 2012
@@ -21,41 +21,55 @@
 
 namespace llvm {
 
-bool RuntimeDyldMachO::
-resolveRelocation(uint8_t *LocalAddress,
-                  uint64_t FinalAddress,
-                  uint64_t Value,
-                  bool isPCRel,
-                  unsigned Type,
-                  unsigned Size,
-                  int64_t Addend) {
+void RuntimeDyldMachO::resolveRelocation(uint8_t *LocalAddress,
+                                         uint64_t FinalAddress,
+                                         uint64_t Value,
+                                         uint32_t Type,
+                                         int64_t Addend) {
+  bool isPCRel = (Type >> 24) & 1;
+  unsigned MachoType = (Type >> 28) & 0xf;
+  unsigned Size = 1 << ((Type >> 25) & 3);
+
+  DEBUG(dbgs() << "resolveRelocation LocalAddress: " << format("%p", LocalAddress)
+        << " FinalAddress: " << format("%p", FinalAddress)
+        << " Value: " << format("%p", Value)
+        << " Addend: " << Addend
+        << " isPCRel: " << isPCRel
+        << " MachoType: " << MachoType
+        << " Size: " << Size
+        << "\n");
+
   // This just dispatches to the proper target specific routine.
-  switch (CPUType) {
+  switch (Arch) {
   default: llvm_unreachable("Unsupported CPU type!");
-  case mach::CTM_i386:
-    return resolveI386Relocation(LocalAddress,
+  case Triple::x86_64:
+    resolveX86_64Relocation(LocalAddress,
+                            FinalAddress,
+                            (uintptr_t)Value,
+                            isPCRel,
+                            MachoType,
+                            Size,
+                            Addend);
+    break;
+  case Triple::x86:
+    resolveI386Relocation(LocalAddress,
                                  FinalAddress,
                                  (uintptr_t)Value,
                                  isPCRel,
                                  Type,
                                  Size,
                                  Addend);
-  case mach::CTM_x86_64:
-    return resolveX86_64Relocation(LocalAddress,
-                                   FinalAddress,
-                                   (uintptr_t)Value,
-                                   isPCRel,
-                                   Type,
-                                   Size,
-                                   Addend);
-  case mach::CTM_ARM:
-    return resolveARMRelocation(LocalAddress,
-                                FinalAddress,
-                                (uintptr_t)Value,
-                                isPCRel,
-                                Type,
-                                Size,
-                                Addend);
+    break;
+  case Triple::arm:    // Fall through.
+  case Triple::thumb:
+    resolveARMRelocation(LocalAddress,
+                         FinalAddress,
+                         (uintptr_t)Value,
+                         isPCRel,
+                         MachoType,
+                         Size,
+                         Addend);
+    break;
   }
 }
 
@@ -190,503 +204,84 @@
   return false;
 }
 
-bool RuntimeDyldMachO::
-loadSegment32(const MachOObject *Obj,
-              const MachOObject::LoadCommandInfo *SegmentLCI,
-              const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC) {
-  // FIXME: This should really be combined w/ loadSegment64. Templatized
-  // function on the 32/64 datatypes maybe?
-  InMemoryStruct<macho::SegmentLoadCommand> SegmentLC;
-  Obj->ReadSegmentLoadCommand(*SegmentLCI, SegmentLC);
-  if (!SegmentLC)
-    return Error("unable to load segment load command");
-
-
-  SmallVector<unsigned, 16> SectionMap;
-  for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
-    InMemoryStruct<macho::Section> Sect;
-    Obj->ReadSection(*SegmentLCI, SectNum, Sect);
-    if (!Sect)
-      return Error("unable to load section: '" + Twine(SectNum) + "'");
-
-    // Allocate memory via the MM for the section.
-    uint8_t *Buffer;
-    uint32_t SectionID = Sections.size();
-    if (Sect->Flags == 0x80000400)
-      Buffer = MemMgr->allocateCodeSection(Sect->Size, Sect->Align, SectionID);
-    else
-      Buffer = MemMgr->allocateDataSection(Sect->Size, Sect->Align, SectionID);
-
-    DEBUG(dbgs() << "Loading "
-                 << ((Sect->Flags == 0x80000400) ? "text" : "data")
-                 << " (ID #" << SectionID << ")"
-                 << " '" << Sect->SegmentName << ","
-                 << Sect->Name << "' of size " << Sect->Size
-                 << " to address " << Buffer << ".\n");
-
-    // Copy the payload from the object file into the allocated buffer.
-    uint8_t *Base = (uint8_t*)Obj->getData(SegmentLC->FileOffset,
-                                           SegmentLC->FileSize).data();
-    memcpy(Buffer, Base + Sect->Address, Sect->Size);
-
-    // Remember what got allocated for this SectionID.
-    Sections.push_back(sys::MemoryBlock(Buffer, Sect->Size));
-    SectionLocalMemToID[Buffer] = SectionID;
-
-    // By default, the load address of a section is its memory buffer.
-    SectionLoadAddress.push_back((uint64_t)Buffer);
-
-    // Keep a map of object file section numbers to corresponding SectionIDs
-    // while processing the file.
-    SectionMap.push_back(SectionID);
-  }
-
-  // Process the symbol table.
-  SmallVector<StringRef, 64> SymbolNames;
-  processSymbols32(Obj, SectionMap, SymbolNames, SymtabLC);
-
-  // Process the relocations for each section we're loading.
-  Relocations.grow(Relocations.size() + SegmentLC->NumSections);
-  Referrers.grow(Referrers.size() + SegmentLC->NumSections);
-  for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
-    InMemoryStruct<macho::Section> Sect;
-    Obj->ReadSection(*SegmentLCI, SectNum, Sect);
-    if (!Sect)
-      return Error("unable to load section: '" + Twine(SectNum) + "'");
-    for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) {
-      InMemoryStruct<macho::RelocationEntry> RE;
-      Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE);
-      if (RE->Word0 & macho::RF_Scattered)
-        return Error("NOT YET IMPLEMENTED: scattered relocations.");
-      // Word0 of the relocation is the offset into the section where the
-      // relocation should be applied. We need to translate that into an
-      // offset into a function since that's our atom.
-      uint32_t Offset = RE->Word0;
-      bool isExtern = (RE->Word1 >> 27) & 1;
-
-      // FIXME: Get the relocation addend from the target address.
-      // FIXME: VERY imporant for internal relocations.
-
-      // Figure out the source symbol of the relocation. If isExtern is true,
-      // this relocation references the symbol table, otherwise it references
-      // a section in the same object, numbered from 1 through NumSections
-      // (SectionBases is [0, NumSections-1]).
-      uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value
-      if (!isExtern) {
-        assert(SourceNum > 0 && "Invalid relocation section number!");
-        unsigned SectionID = SectionMap[SourceNum - 1];
-        unsigned TargetID = SectionMap[SectNum];
-        DEBUG(dbgs() << "Internal relocation at Section #"
-                     << TargetID << " + " << Offset
-                     << " from Section #"
-                     << SectionID << " (Word1: "
-                     << format("0x%x", RE->Word1) << ")\n");
-
-        // Store the relocation information. It will get resolved when
-        // the section addresses are assigned.
-        uint32_t RelocationIndex = Relocations[SectionID].size();
-        Relocations[SectionID].push_back(RelocationEntry(TargetID,
-                                                         Offset,
-                                                         RE->Word1,
-                                                         0 /*Addend*/));
-        Referrers[TargetID].push_back(Referrer(SectionID, RelocationIndex));
-      } else {
-        StringRef SourceName = SymbolNames[SourceNum];
-
-        // Now store the relocation information. Associate it with the source
-        // symbol. Just add it to the unresolved list and let the general
-        // path post-load resolve it if we know where the symbol is.
-        UnresolvedRelocations[SourceName].push_back(RelocationEntry(SectNum,
-                                                                    Offset,
-                                                                    RE->Word1,
-                                                                 0 /*Addend*/));
-        DEBUG(dbgs() << "Relocation at Section #" << SectNum << " + " << Offset
-              << " from '" << SourceName << "(Word1: "
-              << format("0x%x", RE->Word1) << ")\n");
-      }
+void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
+                                            const ObjectFile &Obj,
+                                            ObjSectionToIDMap &ObjSectionToID,
+                                            LocalSymbolMap &Symbols,
+                                            StubMap &Stubs) {
+
+  uint32_t RelType = (uint32_t) (Rel.Type & 0xffffffffL);
+  RelocationValueRef Value;
+  SectionEntry &Section = Sections[Rel.SectionID];
+  uint8_t *Target = Section.Address + Rel.Offset;
+
+  bool isExtern = (RelType >> 27) & 1;
+  if (isExtern) {
+    StringRef TargetName;
+    const SymbolRef &Symbol = Rel.Symbol;
+    Symbol.getName(TargetName);
+    // First look the symbol in object file symbols.
+    LocalSymbolMap::iterator lsi = Symbols.find(TargetName.data());
+    if (lsi != Symbols.end()) {
+      Value.SectionID = lsi->second.first;
+      Value.Addend = lsi->second.second;
+    } else {
+      // Second look the symbol in global symbol table.
+      StringMap<SymbolLoc>::iterator gsi = SymbolTable.find(TargetName.data());
+      if (gsi != SymbolTable.end()) {
+        Value.SectionID = gsi->second.first;
+        Value.Addend = gsi->second.second;
+      } else
+        Value.SymbolName = TargetName.data();
     }
-  }
-
-  // Resolve the addresses of any symbols that were defined in this segment.
-  for (int i = 0, e = SymbolNames.size(); i != e; ++i)
-    resolveSymbol(SymbolNames[i]);
-
-  return false;
-}
-
-
-bool RuntimeDyldMachO::
-loadSegment64(const MachOObject *Obj,
-              const MachOObject::LoadCommandInfo *SegmentLCI,
-              const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC) {
-  InMemoryStruct<macho::Segment64LoadCommand> Segment64LC;
-  Obj->ReadSegment64LoadCommand(*SegmentLCI, Segment64LC);
-  if (!Segment64LC)
-    return Error("unable to load segment load command");
-
-
-  SmallVector<unsigned, 16> SectionMap;
-  for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections; ++SectNum) {
-    InMemoryStruct<macho::Section64> Sect;
-    Obj->ReadSection64(*SegmentLCI, SectNum, Sect);
-    if (!Sect)
-      return Error("unable to load section: '" + Twine(SectNum) + "'");
-
-    // Allocate memory via the MM for the section.
-    uint8_t *Buffer;
-    uint32_t SectionID = Sections.size();
-    unsigned Align = 1 << Sect->Align; // .o file has log2 alignment.
-    if (Sect->Flags == 0x80000400)
-      Buffer = MemMgr->allocateCodeSection(Sect->Size, Align, SectionID);
-    else
-      Buffer = MemMgr->allocateDataSection(Sect->Size, Align, SectionID);
-
-    DEBUG(dbgs() << "Loading "
-                 << ((Sect->Flags == 0x80000400) ? "text" : "data")
-                 << " (ID #" << SectionID << ")"
-                 << " '" << Sect->SegmentName << ","
-                 << Sect->Name << "' of size " << Sect->Size
-                 << " (align " << Align << ")"
-                 << " to address " << Buffer << ".\n");
-
-    // Copy the payload from the object file into the allocated buffer.
-    uint8_t *Base = (uint8_t*)Obj->getData(Segment64LC->FileOffset,
-                                           Segment64LC->FileSize).data();
-    memcpy(Buffer, Base + Sect->Address, Sect->Size);
-
-    // Remember what got allocated for this SectionID.
-    Sections.push_back(sys::MemoryBlock(Buffer, Sect->Size));
-    SectionLocalMemToID[Buffer] = SectionID;
-
-    // By default, the load address of a section is its memory buffer.
-    SectionLoadAddress.push_back((uint64_t)Buffer);
-
-    // Keep a map of object file section numbers to corresponding SectionIDs
-    // while processing the file.
-    SectionMap.push_back(SectionID);
-  }
-
-  // Process the symbol table.
-  SmallVector<StringRef, 64> SymbolNames;
-  processSymbols64(Obj, SectionMap, SymbolNames, SymtabLC);
-
-  // Process the relocations for each section we're loading.
-  Relocations.grow(Relocations.size() + Segment64LC->NumSections);
-  Referrers.grow(Referrers.size() + Segment64LC->NumSections);
-  for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections; ++SectNum) {
-    InMemoryStruct<macho::Section64> Sect;
-    Obj->ReadSection64(*SegmentLCI, SectNum, Sect);
-    if (!Sect)
-      return Error("unable to load section: '" + Twine(SectNum) + "'");
-    for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) {
-      InMemoryStruct<macho::RelocationEntry> RE;
-      Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE);
-      if (RE->Word0 & macho::RF_Scattered)
-        return Error("NOT YET IMPLEMENTED: scattered relocations.");
-      // Word0 of the relocation is the offset into the section where the
-      // relocation should be applied. We need to translate that into an
-      // offset into a function since that's our atom.
-      uint32_t Offset = RE->Word0;
-      bool isExtern = (RE->Word1 >> 27) & 1;
-
-      // FIXME: Get the relocation addend from the target address.
-      // FIXME: VERY imporant for internal relocations.
-
-      // Figure out the source symbol of the relocation. If isExtern is true,
-      // this relocation references the symbol table, otherwise it references
-      // a section in the same object, numbered from 1 through NumSections
-      // (SectionBases is [0, NumSections-1]).
-      uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value
-      if (!isExtern) {
-        assert(SourceNum > 0 && "Invalid relocation section number!");
-        unsigned SectionID = SectionMap[SourceNum - 1];
-        unsigned TargetID = SectionMap[SectNum];
-        DEBUG(dbgs() << "Internal relocation at Section #"
-                     << TargetID << " + " << Offset
-                     << " from Section #"
-                     << SectionID << " (Word1: "
-                     << format("0x%x", RE->Word1) << ")\n");
-
-        // Store the relocation information. It will get resolved when
-        // the section addresses are assigned.
-        uint32_t RelocationIndex = Relocations[SectionID].size();
-        Relocations[SectionID].push_back(RelocationEntry(TargetID,
-                                                         Offset,
-                                                         RE->Word1,
-                                                         0 /*Addend*/));
-        Referrers[TargetID].push_back(Referrer(SectionID, RelocationIndex));
-      } else {
-        StringRef SourceName = SymbolNames[SourceNum];
-
-        // Now store the relocation information. Associate it with the source
-        // symbol. Just add it to the unresolved list and let the general
-        // path post-load resolve it if we know where the symbol is.
-        UnresolvedRelocations[SourceName].push_back(RelocationEntry(SectNum,
-                                                                    Offset,
-                                                                    RE->Word1,
-                                                                 0 /*Addend*/));
-        DEBUG(dbgs() << "Relocation at Section #" << SectNum << " + " << Offset
-              << " from '" << SourceName << "(Word1: "
-              << format("0x%x", RE->Word1) << ")\n");
-      }
+  } else {
+    error_code err;
+    uint8_t sectionIndex = static_cast<uint8_t>(RelType & 0xFF);
+    section_iterator si = Obj.begin_sections(),
+                     se = Obj.end_sections();
+    for (uint8_t i = 1; i < sectionIndex; i++) {
+      error_code err;
+      si.increment(err);
+      if (si == se)
+        break;
     }
-  }
-
-  // Resolve the addresses of any symbols that were defined in this segment.
-  for (int i = 0, e = SymbolNames.size(); i != e; ++i)
-    resolveSymbol(SymbolNames[i]);
-
-  return false;
-}
-
-bool RuntimeDyldMachO::
-processSymbols32(const MachOObject *Obj,
-                 SmallVectorImpl<unsigned> &SectionMap,
-                 SmallVectorImpl<StringRef> &SymbolNames,
-                 const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC) {
-  // FIXME: Combine w/ processSymbols64. Factor 64/32 datatype and such.
-  for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
-    InMemoryStruct<macho::SymbolTableEntry> STE;
-    Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE);
-    if (!STE)
-      return Error("unable to read symbol: '" + Twine(i) + "'");
-    // Get the symbol name.
-    StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
-    SymbolNames.push_back(Name);
-
-    // FIXME: Check the symbol type and flags.
-    if (STE->Type != 0xF)  // external, defined in this segment.
-      continue;
-    // Flags in the upper nibble we don't care about.
-    if ((STE->Flags & 0xf) != 0x0)
-      continue;
-
-    // Remember the symbol.
-    uint32_t SectionID = SectionMap[STE->SectionIndex - 1];
-    SymbolTable[Name] = SymbolLoc(SectionID, STE->Value);
-
-    DEBUG(dbgs() << "Symbol: '" << Name << "' @ "
-                 << (getSectionAddress(SectionID) + STE->Value)
-                 << "\n");
-  }
-  return false;
-}
-
-bool RuntimeDyldMachO::
-processSymbols64(const MachOObject *Obj,
-                 SmallVectorImpl<unsigned> &SectionMap,
-                 SmallVectorImpl<StringRef> &SymbolNames,
-                 const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC) {
-  for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) {
-    InMemoryStruct<macho::Symbol64TableEntry> STE;
-    Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE);
-    if (!STE)
-      return Error("unable to read symbol: '" + Twine(i) + "'");
-    // Get the symbol name.
-    StringRef Name = Obj->getStringAtIndex(STE->StringIndex);
-    SymbolNames.push_back(Name);
-
-    // FIXME: Check the symbol type and flags.
-    if (STE->Type != 0xF)  // external, defined in this segment.
-      continue;
-    // Flags in the upper nibble we don't care about.
-    if ((STE->Flags & 0xf) != 0x0)
-      continue;
-
-    // Remember the symbol.
-    uint32_t SectionID = SectionMap[STE->SectionIndex - 1];
-    SymbolTable[Name] = SymbolLoc(SectionID, STE->Value);
-
-    DEBUG(dbgs() << "Symbol: '" << Name << "' @ "
-                 << (getSectionAddress(SectionID) + STE->Value)
-                 << "\n");
-  }
-  return false;
-}
-
-// resolveSymbol - Resolve any relocations to the specified symbol if
-// we know where it lives.
-void RuntimeDyldMachO::resolveSymbol(StringRef Name) {
-  StringMap<SymbolLoc>::const_iterator Loc = SymbolTable.find(Name);
-  if (Loc == SymbolTable.end())
-    return;
-
-  RelocationList &Relocs = UnresolvedRelocations[Name];
-  DEBUG(dbgs() << "Resolving symbol '" << Name << "'\n");
-  for (int i = 0, e = Relocs.size(); i != e; ++i) {
-    // Change the relocation to be section relative rather than symbol
-    // relative and move it to the resolved relocation list.
-    RelocationEntry Entry = Relocs[i];
-    Entry.Addend += Loc->second.second;
-    uint32_t RelocationIndex = Relocations[Loc->second.first].size();
-    Relocations[Loc->second.first].push_back(Entry);
-    Referrers[Entry.SectionID].push_back(Referrer(Loc->second.first, RelocationIndex));
-  }
-  // FIXME: Keep a worklist of the relocations we've added so that we can
-  // resolve more selectively later.
-  Relocs.clear();
-}
-
-bool RuntimeDyldMachO::loadObject(MemoryBuffer *InputBuffer) {
-  // If the linker is in an error state, don't do anything.
-  if (hasError())
-    return true;
-  // Load the Mach-O wrapper object.
-  std::string ErrorStr;
-  OwningPtr<MachOObject> Obj(
-    MachOObject::LoadFromBuffer(InputBuffer, &ErrorStr));
-  if (!Obj)
-    return Error("unable to load object: '" + ErrorStr + "'");
-
-  // Get the CPU type information from the header.
-  const macho::Header &Header = Obj->getHeader();
-
-  // FIXME: Error checking that the loaded object is compatible with
-  //        the system we're running on.
-  CPUType = Header.CPUType;
-  CPUSubtype = Header.CPUSubtype;
-
-  // Validate that the load commands match what we expect.
-  const MachOObject::LoadCommandInfo *SegmentLCI = 0, *SymtabLCI = 0,
-    *DysymtabLCI = 0;
-  for (unsigned i = 0; i != Header.NumLoadCommands; ++i) {
-    const MachOObject::LoadCommandInfo &LCI = Obj->getLoadCommandInfo(i);
-    switch (LCI.Command.Type) {
-    case macho::LCT_Segment:
-    case macho::LCT_Segment64:
-      if (SegmentLCI)
-        return Error("unexpected input object (multiple segments)");
-      SegmentLCI = &LCI;
-      break;
-    case macho::LCT_Symtab:
-      if (SymtabLCI)
-        return Error("unexpected input object (multiple symbol tables)");
-      SymtabLCI = &LCI;
-      break;
-    case macho::LCT_Dysymtab:
-      if (DysymtabLCI)
-        return Error("unexpected input object (multiple symbol tables)");
-      DysymtabLCI = &LCI;
-      break;
-    default:
-      return Error("unexpected input object (unexpected load command");
+    assert(si != se && "No section containing relocation!");
+    Value.SectionID = findOrEmitSection(*si, true, ObjSectionToID);
+    Value.Addend = *(const intptr_t *)Target;
+    if (Value.Addend) {
+      // The MachO addend is offset from the current section, we need set it
+      // as offset from destination section
+      Value.Addend += Section.ObjAddress - Sections[Value.SectionID].ObjAddress;
     }
   }
 
-  if (!SymtabLCI)
-    return Error("no symbol table found in object");
-  if (!SegmentLCI)
-    return Error("no segments found in object");
-
-  // Read and register the symbol table data.
-  InMemoryStruct<macho::SymtabLoadCommand> SymtabLC;
-  Obj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC);
-  if (!SymtabLC)
-    return Error("unable to load symbol table load command");
-  Obj->RegisterStringTable(*SymtabLC);
-
-  // Read the dynamic link-edit information, if present (not present in static
-  // objects).
-  if (DysymtabLCI) {
-    InMemoryStruct<macho::DysymtabLoadCommand> DysymtabLC;
-    Obj->ReadDysymtabLoadCommand(*DysymtabLCI, DysymtabLC);
-    if (!DysymtabLC)
-      return Error("unable to load dynamic link-exit load command");
-
-    // FIXME: We don't support anything interesting yet.
-//    if (DysymtabLC->LocalSymbolsIndex != 0)
-//      return Error("NOT YET IMPLEMENTED: local symbol entries");
-//    if (DysymtabLC->ExternalSymbolsIndex != 0)
-//      return Error("NOT YET IMPLEMENTED: non-external symbol entries");
-//    if (DysymtabLC->UndefinedSymbolsIndex != SymtabLC->NumSymbolTableEntries)
-//      return Error("NOT YET IMPLEMENTED: undefined symbol entries");
-  }
-
-  // Load the segment load command.
-  if (SegmentLCI->Command.Type == macho::LCT_Segment) {
-    if (loadSegment32(Obj.get(), SegmentLCI, SymtabLC))
-      return true;
-  } else {
-    if (loadSegment64(Obj.get(), SegmentLCI, SymtabLC))
-      return true;
-  }
-
-  // Assign the addresses of the sections from the object so that any
-  // relocations to them get set properly.
-  // FIXME: This is done directly from the client at the moment. We should
-  // default the values to the local storage, at least when the target arch
-  // is the same as the host arch.
+  if (Arch == Triple::arm && RelType == macho::RIT_ARM_Branch24Bit) {
+    // This is an ARM branch relocation, need to use a stub function.
 
-  return false;
+    //  Look up for existing stub.
+    StubMap::const_iterator i = Stubs.find(Value);
+    if (i != Stubs.end())
+      resolveRelocation(Target, (uint64_t)Target,
+                        (uint64_t)Section.Address + i->second,
+                        RelType, 0);
+    else {
+      // Create a new stub function.
+      Stubs[Value] = Section.StubOffset;
+      uint8_t *StubTargetAddr = createStubFunction(Section.Address +
+                                                   Section.StubOffset);
+      AddRelocation(Value, Rel.SectionID, StubTargetAddr - Section.Address,
+                    macho::RIT_Vanilla);
+      resolveRelocation(Target, (uint64_t)Target,
+                        (uint64_t)Section.Address + Section.StubOffset,
+                        RelType, 0);
+      Section.StubOffset += getMaxStubSize();
+    }
+  } else
+    AddRelocation(Value, Rel.SectionID, Rel.Offset, RelType);
 }
 
-// Assign an address to a symbol name and resolve all the relocations
-// associated with it.
-void RuntimeDyldMachO::reassignSectionAddress(unsigned SectionID,
-                                              uint64_t Addr) {
-  // The address to use for relocation resolution is not
-  // the address of the local section buffer. We must be doing
-  // a remote execution environment of some sort. Re-apply any
-  // relocations referencing this section with the given address.
-  //
-  // Addr is a uint64_t because we can't assume the pointer width
-  // of the target is the same as that of the host. Just use a generic
-  // "big enough" type.
-
-  SectionLoadAddress[SectionID] = Addr;
-
-  RelocationList &Relocs = Relocations[SectionID];
-  for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
-    RelocationEntry &RE = Relocs[i];
-    uint8_t *Target = (uint8_t*)Sections[RE.SectionID].base() + RE.Offset;
-    uint64_t FinalTarget = (uint64_t)SectionLoadAddress[RE.SectionID] + RE.Offset;
-    bool isPCRel = (RE.Data >> 24) & 1;
-    unsigned Type = (RE.Data >> 28) & 0xf;
-    unsigned Size = 1 << ((RE.Data >> 25) & 3);
-
-    DEBUG(dbgs() << "Resolving relocation at Section #" << RE.SectionID
-          << " + " << RE.Offset << " (" << format("%p", Target) << ")"
-          << " from Section #" << SectionID << " (" << format("%p", Addr) << ")"
-          << "(" << (isPCRel ? "pcrel" : "absolute")
-          << ", type: " << Type << ", Size: " << Size << ", Addend: "
-          << RE.Addend << ").\n");
-
-    resolveRelocation(Target,
-                      FinalTarget,
-                      Addr,
-                      isPCRel,
-                      Type,
-                      Size,
-                      RE.Addend);
-  }
-  ReferrerList &Refers = Referrers[SectionID];
-  for (unsigned i = 0, e = Refers.size(); i != e; ++i) {
-    Referrer &R = Refers[i];
-    RelocationEntry &RE = Relocations[R.SectionID][R.Index];
-    uint8_t *Target = (uint8_t*)Sections[RE.SectionID].base() + RE.Offset;
-    uint64_t FinalTarget = (uint64_t)SectionLoadAddress[RE.SectionID] + RE.Offset;
-    bool isPCRel = (RE.Data >> 24) & 1;
-    unsigned Type = (RE.Data >> 28) & 0xf;
-    unsigned Size = 1 << ((RE.Data >> 25) & 3);
-
-    DEBUG(dbgs() << "Resolving relocation at Section #" << RE.SectionID
-          << " + " << RE.Offset << " (" << format("%p", Target) << ")"
-          << " from Section #" << SectionID << " (" << format("%p", Addr) << ")"
-          << "(" << (isPCRel ? "pcrel" : "absolute")
-          << ", type: " << Type << ", Size: " << Size << ", Addend: "
-          << RE.Addend << ").\n");
-
-    resolveRelocation(Target,
-                      FinalTarget,
-                      Addr,
-                      isPCRel,
-                      Type,
-                      Size,
-                      RE.Addend);
-  }
-}
 
-bool RuntimeDyldMachO::isKnownFormat(const MemoryBuffer *InputBuffer) {
+bool RuntimeDyldMachO::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {
   StringRef Magic = InputBuffer->getBuffer().slice(0, 4);
   if (Magic == "\xFE\xED\xFA\xCE") return true;
   if (Magic == "\xCE\xFA\xED\xFE") return true;

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h Fri Mar 30 11:45:19 2012
@@ -25,55 +25,7 @@
 
 namespace llvm {
 class RuntimeDyldMachO : public RuntimeDyldImpl {
-
-  // For each symbol, keep a list of relocations based on it. Anytime
-  // its address is reassigned (the JIT re-compiled the function, e.g.),
-  // the relocations get re-resolved.
-  // The symbol (or section) the relocation is sourced from is the Key
-  // in the relocation list where it's stored.
-  struct RelocationEntry {
-    unsigned    SectionID;  // Section the relocation is contained in.
-    uint64_t    Offset;     // Offset into the section for the relocation.
-    uint32_t    Data;       // Second word of the raw macho relocation entry.
-    int64_t     Addend;     // Addend encoded in the instruction itself, if any,
-                            // plus the offset into the source section for
-                            // the symbol once the relocation is resolvable.
-
-    RelocationEntry(unsigned id, uint64_t offset, uint32_t data, int64_t addend)
-      : SectionID(id), Offset(offset), Data(data), Addend(addend) {}
-  };
-  typedef SmallVector<RelocationEntry, 4> RelocationList;
-
-  // For each section, keep a list of referrers in that section that are clients
-  // of relocations in other sections.  Whenever a relocation gets created,
-  // create a corresponding referrer.  Whenever relocations are re-resolved,
-  // re-resolve the referrers' relocations as well.
-  struct Referrer {
-    unsigned    SectionID;  // Section whose RelocationList contains the relocation.
-    uint32_t    Index;      // Index of the RelocatonEntry in that RelocationList.
-
-    Referrer(unsigned id, uint32_t index)
-      : SectionID(id), Index(index) {}
-  };
-  typedef SmallVector<Referrer, 4> ReferrerList;
-
-  // Relocations to sections already loaded. Indexed by SectionID which is the
-  // source of the address. The target where the address will be writen is
-  // SectionID/Offset in the relocation itself.
-  IndexedMap<RelocationList> Relocations;
-  // Referrers corresponding to Relocations.
-  IndexedMap<ReferrerList> Referrers;
-  // Relocations to symbols that are not yet resolved. Must be external
-  // relocations by definition. Indexed by symbol name.
-  StringMap<RelocationList> UnresolvedRelocations;
-
-  bool resolveRelocation(uint8_t *LocalAddress,
-                         uint64_t FinalAddress,
-                         uint64_t Value,
-                         bool isPCRel,
-                         unsigned Type,
-                         unsigned Size,
-                         int64_t Addend);
+protected:
   bool resolveI386Relocation(uint8_t *LocalAddress,
                              uint64_t FinalAddress,
                              uint64_t Value,
@@ -96,35 +48,21 @@
                             unsigned Size,
                             int64_t Addend);
 
-  bool loadSegment32(const MachOObject *Obj,
-                     const MachOObject::LoadCommandInfo *SegmentLCI,
-                     const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
-  bool loadSegment64(const MachOObject *Obj,
-                     const MachOObject::LoadCommandInfo *SegmentLCI,
-                     const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
-  bool processSymbols32(const MachOObject *Obj,
-                      SmallVectorImpl<unsigned> &SectionMap,
-                      SmallVectorImpl<StringRef> &SymbolNames,
-                      const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
-  bool processSymbols64(const MachOObject *Obj,
-                      SmallVectorImpl<unsigned> &SectionMap,
-                      SmallVectorImpl<StringRef> &SymbolNames,
-                      const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC);
-
-  void resolveSymbol(StringRef Name);
+  virtual void processRelocationRef(const ObjRelocationInfo &Rel,
+                                    const ObjectFile &Obj,
+                                    ObjSectionToIDMap &ObjSectionToID,
+                                    LocalSymbolMap &Symbols, StubMap &Stubs);
 
 public:
+  virtual void resolveRelocation(uint8_t *LocalAddress,
+                                 uint64_t FinalAddress,
+                                 uint64_t Value,
+                                 uint32_t Type,
+                                 int64_t Addend);
+                                 
   RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
 
-  bool loadObject(MemoryBuffer *InputBuffer);
-
-  void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
-
-  static bool isKnownFormat(const MemoryBuffer *InputBuffer);
-
-  bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const {
-    return isKnownFormat(InputBuffer);
-  }
+  bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
 };
 
 } // end namespace llvm

Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp?rev=153754&r1=153753&r2=153754&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp (original)
+++ llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Fri Mar 30 11:45:19 2012
@@ -58,10 +58,6 @@
   uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
                                unsigned SectionID);
 
-  uint8_t *startFunctionBody(const char *Name, uintptr_t &Size);
-  void endFunctionBody(const char *Name, uint8_t *FunctionStart,
-                       uint8_t *FunctionEnd);
-
   virtual void *getPointerToNamedFunction(const std::string &Name,
                                           bool AbortOnFailure = true) {
     return 0;
@@ -81,18 +77,6 @@
   return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base();
 }
 
-uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name,
-                                                 uintptr_t &Size) {
-  return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base();
-}
-
-void TrivialMemoryManager::endFunctionBody(const char *Name,
-                                           uint8_t *FunctionStart,
-                                           uint8_t *FunctionEnd) {
-  uintptr_t Size = FunctionEnd - FunctionStart + 1;
-  FunctionMemory.push_back(sys::MemoryBlock(FunctionStart, Size));
-}
-
 static const char *ProgramName;
 
 static void Message(const char *Type, const Twine &Msg) {





More information about the llvm-commits mailing list