diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2012-03-22 05:44:06 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2012-03-22 05:44:06 +0000 |
commit | 3e29671cca14f8fce1ea6b602175880cb3df7199 (patch) | |
tree | e288bd135f9f6d086a608315cf816660502b76b7 /lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | |
parent | f2f6182f6a88cf4b8d8cb95686d68aa14ddb6857 (diff) |
Revert a series of commits to MCJIT to get the build working in CMake
(and hopefully on Windows). The bots have been down most of the day
because of this, and it's not clear to me what all will be required to
fix it.
The commits started with r153205, then r153207, r153208, and r153221.
The first commit seems to be the real culprit, but I couldn't revert
a smaller number of patches.
When resubmitting, r153207 and r153208 should be folded into r153205,
they were simple build fixes.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153241 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 408 |
1 files changed, 228 insertions, 180 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 9351b6c361..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,173 +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 it = Symbols.find(TargetName.data()); - if (it != Symbols.end()) { - Value.SectionID = it->second.first; - Value.Addend = it->second.second; - } else { - // Second look the symbol in global symbol table. - StringMap<SymbolLoc>::iterator itS = SymbolTable.find(TargetName.data()); - if (itS != SymbolTable.end()) { - Value.SectionID = itS->second.first; - Value.Addend = itS->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 sIt = Obj.end_sections(); - Symbol.getSection(sIt); - if (sIt == Obj.end_sections()) - llvm_unreachable("Symbol section not found, bad object file format!"); - DEBUG(dbgs() << "\t\tThis is section symbol\n"); - Value.SectionID = findOrEmitSection((*sIt), 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 stubIt = Stubs.find(Value); - if (stubIt != Stubs.end()) { - resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address + - stubIt->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 { |