diff options
author | Bill Wendling <isanbard@gmail.com> | 2012-03-29 23:23:59 +0000 |
---|---|---|
committer | Bill Wendling <isanbard@gmail.com> | 2012-03-29 23:23:59 +0000 |
commit | 288967dfac246c8e35dc4f85afb667e74d1d26a8 (patch) | |
tree | 7dd4eef16e2e567d38180a3dbdbc01f5e9be3b0c /lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | |
parent | 7a4c071cd9f67599eba21e902079d0e85f2abf97 (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.cpp | 409 |
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 { |