Revert r153694. It was causing failures in the buildbots.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153701 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index 9d46b21..e15b200 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -25,58 +25,222 @@
 
 namespace llvm {
 
+namespace {
 
-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;
+// 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!");
   case ELF::R_X86_64_64: {
-    uint64_t *Target = (uint64_t*)(LocalAddress);
-    *Target = Value + Addend;
+    uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
+    *Target = Addr + RE.Addend;
     break;
   }
   case ELF::R_X86_64_32:
   case ELF::R_X86_64_32S: {
-    Value += Addend;
+    uint64_t Value = reinterpret_cast<uint64_t>(Addr) + RE.Addend;
     // FIXME: Handle the possibility of this assertion failing
-    assert((Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
-           (Type == ELF::R_X86_64_32S &&
+    assert((RE.Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
+           (RE.Type == ELF::R_X86_64_32S &&
             (Value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL));
     uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
-    uint32_t *Target = reinterpret_cast<uint32_t*>(LocalAddress);
+    uint32_t *Target = reinterpret_cast<uint32_t*>(TargetAddr);
     *Target = TruncatedAddr;
     break;
   }
   case ELF::R_X86_64_PC32: {
-    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);
+    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);
     *Placeholder = TruncOffset;
     break;
   }
   }
 }
 
-void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress,
-                                          uint32_t FinalAddress,
-                                          uint32_t Value,
-                                          uint32_t Type,
-                                          int32_t Addend) {
-  switch (Type) {
+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) {
   case ELF::R_386_32: {
-    uint32_t *Target = (uint32_t*)(LocalAddress);
-    *Target = Value + Addend;
+    uint8_t **Target = reinterpret_cast<uint8_t**>(TargetAddr);
+    *Target = Addr + RE.Addend;
     break;
   }
   case ELF::R_386_PC32: {
-    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
-    uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
+    uint32_t *Placeholder = reinterpret_cast<uint32_t*>(TargetAddr);
+    uint32_t RealOffset = *Placeholder + reinterpret_cast<uintptr_t>(Addr) +
+                           RE.Addend - reinterpret_cast<uintptr_t>(TargetAddr);
     *Placeholder = RealOffset;
     break;
     }
@@ -84,174 +248,57 @@
       // 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(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::resolveArmRelocation(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) {
+void RuntimeDyldELF::resolveRelocation(StringRef Name,
+                                       uint8_t *Addr,
+                                       const RelocationEntry &RE) {
   switch (Arch) {
   case Triple::x86_64:
-    resolveX86_64Relocation(LocalAddress, FinalAddress, Value, Type, Addend);
+    resolveX86_64Relocation(Name, Addr, RE);
     break;
   case Triple::x86:
-    resolveX86Relocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
-                         (uint32_t)(Value & 0xffffffffL), Type,
-                         (uint32_t)(Addend & 0xffffffffL));
+    resolveX86Relocation(Name, Addr, RE);
     break;
-  case Triple::arm:    // Fall through.
-  case Triple::thumb:
-    resolveARMRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
-                         (uint32_t)(Value & 0xffffffffL), Type,
-                         (uint32_t)(Addend & 0xffffffffL));
+  case Triple::arm:
+    resolveArmRelocation(Name, Addr, RE);
     break;
   default: llvm_unreachable("Unsupported CPU type!");
   }
 }
 
-void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
-                                          const ObjectFile &Obj,
-                                          ObjSectionToIDMap &ObjSectionToID,
-                                          LocalSymbolMap &Symbols,
-                                          StubMap &Stubs) {
+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!");
 
-  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;
-      }
-    }
+  RelocationList &Relocs = Relocations[Name];
+  for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
+    RelocationEntry &RE = Relocs[i];
+    resolveRelocation(Name, Addr, RE);
   }
-  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);
+// 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);
 }
 
 bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {