aboutsummaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-03-29 23:23:59 +0000
committerBill Wendling <isanbard@gmail.com>2012-03-29 23:23:59 +0000
commit288967dfac246c8e35dc4f85afb667e74d1d26a8 (patch)
tree7dd4eef16e2e567d38180a3dbdbc01f5e9be3b0c /lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
parent7a4c071cd9f67599eba21e902079d0e85f2abf97 (diff)
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
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp409
1 files changed, 228 insertions, 181 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index 9d46b21f59..e15b200c5e 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -25,58 +25,222 @@ using namespace llvm::object;
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 @@ void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress,
// 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) {
-
- 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;
- }
- }
+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);
}
- 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 {