X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FExecutionEngine%2FRuntimeDyld%2FRuntimeDyldMachO.cpp;h=d4a680d749a163e95a2aa33a727ea6965b0187ab;hp=a22689a40d926adee25ed450bc15a09d913dda49;hb=25103832b272eaa009fd56d3fc9eb98ebb7c2f1a;hpb=41db8128a2d7d34dbca8cb1906135e0a34b2f31f diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index a22689a40d9..d4a680d749a 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -12,48 +12,50 @@ //===----------------------------------------------------------------------===// #include "RuntimeDyldMachO.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" - -#include "Targets/RuntimeDyldMachOARM.h" #include "Targets/RuntimeDyldMachOAArch64.h" +#include "Targets/RuntimeDyldMachOARM.h" #include "Targets/RuntimeDyldMachOI386.h" #include "Targets/RuntimeDyldMachOX86_64.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" using namespace llvm; using namespace llvm::object; #define DEBUG_TYPE "dyld" +namespace { + +class LoadedMachOObjectInfo + : public RuntimeDyld::LoadedObjectInfoHelper { +public: + LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary + getObjectForDebug(const ObjectFile &Obj) const override { + return OwningBinary(); + } +}; + +} + namespace llvm { int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { - const SectionEntry &Section = Sections[RE.SectionID]; unsigned NumBytes = 1 << RE.Size; - int64_t Addend = 0; - uint8_t *LocalAddress = Section.Address + RE.Offset; - uint8_t *Dst = reinterpret_cast(&Addend); + uint8_t *Src = Sections[RE.SectionID].Address + RE.Offset; - if (IsTargetLittleEndian == sys::IsLittleEndianHost) { - if (!sys::IsLittleEndianHost) - Dst += sizeof(Addend) - NumBytes; - memcpy(Dst, LocalAddress, NumBytes); - } else { - Dst += NumBytes - 1; - for (unsigned i = 0; i < NumBytes; ++i) - *Dst-- = *LocalAddress++; - } - - return Addend; + return static_cast(readBytesUnaligned(Src, NumBytes)); } RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( - ObjectImage &ObjImg, const relocation_iterator &RI, - const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols) { + const ObjectFile &BaseTObj, const relocation_iterator &RI, + const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); RelocationValueRef Value; @@ -63,39 +65,33 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( symbol_iterator Symbol = RI->getSymbol(); StringRef TargetName; Symbol->getName(TargetName); - SymbolTableMap::const_iterator SI = Symbols.find(TargetName.data()); - if (SI != Symbols.end()) { - Value.SectionID = SI->second.first; - Value.Addend = SI->second.second + RE.Addend; + RTDyldSymbolTable::const_iterator SI = + GlobalSymbolTable.find(TargetName.data()); + if (SI != GlobalSymbolTable.end()) { + const auto &SymInfo = SI->second; + Value.SectionID = SymInfo.getSectionID(); + Value.Offset = SymInfo.getOffset() + RE.Addend; } else { - SI = GlobalSymbolTable.find(TargetName.data()); - if (SI != GlobalSymbolTable.end()) { - Value.SectionID = SI->second.first; - Value.Addend = SI->second.second + RE.Addend; - } else { - Value.SymbolName = TargetName.data(); - Value.Addend = RE.Addend; - } + Value.SymbolName = TargetName.data(); + Value.Offset = RE.Addend; } } else { - SectionRef Sec = Obj.getRelocationSection(RelInfo); - bool IsCode = false; - Sec.isText(IsCode); - Value.SectionID = findOrEmitSection(ObjImg, Sec, IsCode, ObjSectionToID); - uint64_t Addr; - Sec.getAddress(Addr); - Value.Addend = RE.Addend - Addr; + SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); + bool IsCode = Sec.isText(); + Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); + uint64_t Addr = Sec.getAddress(); + Value.Offset = RE.Addend - Addr; } return Value; } void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, - ObjectImage &ObjImg, + const ObjectFile &BaseTObj, const relocation_iterator &RI, unsigned OffsetToNextPC) { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); @@ -103,7 +99,7 @@ void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, if (IsPCRel) { uint64_t RelocAddr = 0; RI->getAddress(RelocAddr); - Value.Addend += RelocAddr + OffsetToNextPC; + Value.Offset += RelocAddr + OffsetToNextPC; } } @@ -121,86 +117,143 @@ void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE, << " Size: " << (1 << RE.Size) << "\n"; } -bool RuntimeDyldMachO::writeBytesUnaligned(uint8_t *Dst, uint64_t Value, - unsigned Size) { - - uint8_t *Src = reinterpret_cast(&Value); - // If host and target endianness match use memcpy, otherwise copy in reverse - // order. - if (IsTargetLittleEndian == sys::IsLittleEndianHost) { - if (!sys::IsLittleEndianHost) - Src += sizeof(Value) - Size; - memcpy(Dst, Src, Size); - } else { - Src += Size - 1; - for (unsigned i = 0; i < Size; ++i) - *Dst++ = *Src--; +section_iterator +RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, + uint64_t Addr) { + section_iterator SI = Obj.section_begin(); + section_iterator SE = Obj.section_end(); + + for (; SI != SE; ++SI) { + uint64_t SAddr = SI->getAddress(); + uint64_t SSize = SI->getSize(); + if ((Addr >= SAddr) && (Addr < SAddr + SSize)) + return SI; } - return false; + return SE; } -bool -RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const { - if (InputBuffer->getBufferSize() < 4) - return false; - StringRef Magic(InputBuffer->getBufferStart(), 4); - if (Magic == "\xFE\xED\xFA\xCE") - return true; - if (Magic == "\xCE\xFA\xED\xFE") - return true; - if (Magic == "\xFE\xED\xFA\xCF") - return true; - if (Magic == "\xCF\xFA\xED\xFE") - return true; - return false; + +// Populate __pointers section. +void RuntimeDyldMachO::populateIndirectSymbolPointersSection( + const MachOObjectFile &Obj, + const SectionRef &PTSection, + unsigned PTSectionID) { + assert(!Obj.is64Bit() && + "Pointer table section not supported in 64-bit MachO."); + + MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); + MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); + uint32_t PTSectionSize = Sec32.size; + unsigned FirstIndirectSymbol = Sec32.reserved1; + const unsigned PTEntrySize = 4; + unsigned NumPTEntries = PTSectionSize / PTEntrySize; + unsigned PTEntryOffset = 0; + + assert((PTSectionSize % PTEntrySize) == 0 && + "Pointers section does not contain a whole number of stubs?"); + + DEBUG(dbgs() << "Populating pointer table section " + << Sections[PTSectionID].Name + << ", Section ID " << PTSectionID << ", " + << NumPTEntries << " entries, " << PTEntrySize + << " bytes each:\n"); + + for (unsigned i = 0; i < NumPTEntries; ++i) { + unsigned SymbolIndex = + Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); + symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); + StringRef IndirectSymbolName; + SI->getName(IndirectSymbolName); + DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex + << ", PT offset: " << PTEntryOffset << "\n"); + RelocationEntry RE(PTSectionID, PTEntryOffset, + MachO::GENERIC_RELOC_VANILLA, 0, false, 2); + addRelocationForSymbol(RE, IndirectSymbolName); + PTEntryOffset += PTEntrySize; + } } -bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const { - return Obj->isMachO(); +bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isMachO(); } -static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, - intptr_t DeltaForEH) { +template +void RuntimeDyldMachOCRTPBase::finalizeLoad(const ObjectFile &Obj, + ObjSectionToIDMap &SectionMap) { + unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; + unsigned TextSID = RTDYLD_INVALID_SECTION_ID; + unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; + + for (const auto &Section : Obj.sections()) { + StringRef Name; + Section.getName(Name); + + // Force emission of the __text, __eh_frame, and __gcc_except_tab sections + // if they're present. Otherwise call down to the impl to handle other + // sections that have already been emitted. + if (Name == "__text") + TextSID = findOrEmitSection(Obj, Section, true, SectionMap); + else if (Name == "__eh_frame") + EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap); + else if (Name == "__gcc_except_tab") + ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap); + else { + auto I = SectionMap.find(Section); + if (I != SectionMap.end()) + impl().finalizeSection(Obj, I->second, Section); + } + } + UnregisteredEHFrameSections.push_back( + EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); +} + +template +unsigned char *RuntimeDyldMachOCRTPBase::processFDE(unsigned char *P, + int64_t DeltaForText, + int64_t DeltaForEH) { + typedef typename Impl::TargetPtrT TargetPtrT; + DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText << ", Delta for EH: " << DeltaForEH << "\n"); - uint32_t Length = *((uint32_t *)P); + uint32_t Length = readBytesUnaligned(P, 4); P += 4; unsigned char *Ret = P + Length; - uint32_t Offset = *((uint32_t *)P); + uint32_t Offset = readBytesUnaligned(P, 4); if (Offset == 0) // is a CIE return Ret; P += 4; - intptr_t FDELocation = *((intptr_t *)P); - intptr_t NewLocation = FDELocation - DeltaForText; - *((intptr_t *)P) = NewLocation; - P += sizeof(intptr_t); + TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT)); + TargetPtrT NewLocation = FDELocation - DeltaForText; + writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT)); + + P += sizeof(TargetPtrT); // Skip the FDE address range - P += sizeof(intptr_t); + P += sizeof(TargetPtrT); uint8_t Augmentationsize = *P; P += 1; if (Augmentationsize != 0) { - intptr_t LSDA = *((intptr_t *)P); - intptr_t NewLSDA = LSDA - DeltaForEH; - *((intptr_t *)P) = NewLSDA; + TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT)); + TargetPtrT NewLSDA = LSDA - DeltaForEH; + writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT)); } return Ret; } -static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { - intptr_t ObjDistance = A->ObjAddress - B->ObjAddress; - intptr_t MemDistance = A->LoadAddress - B->LoadAddress; +static int64_t computeDelta(SectionEntry *A, SectionEntry *B) { + int64_t ObjDistance = + static_cast(A->ObjAddress) - static_cast(B->ObjAddress); + int64_t MemDistance = A->LoadAddress - B->LoadAddress; return ObjDistance - MemDistance; } -void RuntimeDyldMachO::registerEHFrames() { +template +void RuntimeDyldMachOCRTPBase::registerEHFrames() { - if (!MemMgr) - return; for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || @@ -212,8 +265,8 @@ void RuntimeDyldMachO::registerEHFrames() { if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) ExceptTab = &Sections[SectionInfo.ExceptTabSID]; - intptr_t DeltaForText = computeDelta(Text, EHFrame); - intptr_t DeltaForEH = 0; + int64_t DeltaForText = computeDelta(Text, EHFrame); + int64_t DeltaForEH = 0; if (ExceptTab) DeltaForEH = computeDelta(ExceptTab, EHFrame); @@ -223,23 +276,37 @@ void RuntimeDyldMachO::registerEHFrames() { P = processFDE(P, DeltaForText, DeltaForEH); } while (P != End); - MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, - EHFrame->Size); + MemMgr.registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, + EHFrame->Size); } UnregisteredEHFrameSections.clear(); } std::unique_ptr -llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { +RuntimeDyldMachO::create(Triple::ArchType Arch, + RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldMachO."); break; - case Triple::arm: return make_unique(MM); - case Triple::aarch64: return make_unique(MM); - case Triple::x86: return make_unique(MM); - case Triple::x86_64: return make_unique(MM); + case Triple::arm: + return make_unique(MemMgr, Resolver); + case Triple::aarch64: + return make_unique(MemMgr, Resolver); + case Triple::x86: + return make_unique(MemMgr, Resolver); + case Triple::x86_64: + return make_unique(MemMgr, Resolver); } } +std::unique_ptr +RuntimeDyldMachO::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique(*this, SectionStartIdx, + SectionEndIdx); +} + } // end namespace llvm