diff options
| author | Lang Hames <lhames@gmail.com> | 2014-07-17 18:54:50 +0000 |
|---|---|---|
| committer | Lang Hames <lhames@gmail.com> | 2014-07-17 18:54:50 +0000 |
| commit | a521688cf40fcb6d1b3e9a6dc4e78d306dbbd5ec (patch) | |
| tree | e84714ff85a35732633fc7e26d034369c9326e9d /llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h | |
| parent | 535b6f936157d6fec5b074a149200f81e6bcbb9d (diff) | |
| download | bcm5719-llvm-a521688cf40fcb6d1b3e9a6dc4e78d306dbbd5ec.tar.gz bcm5719-llvm-a521688cf40fcb6d1b3e9a6dc4e78d306dbbd5ec.zip | |
[MCJIT] Significantly refactor the RuntimeDyldMachO class.
The previous implementation of RuntimeDyldMachO mixed logic for all targets
within a single class, creating problems for readability, maintainability, and
performance. To address these issues, this patch strips the RuntimeDyldMachO
class down to just target-independent functionality, and moves all
target-specific functionality into target-specific subclasses RuntimeDyldMachO.
The new class hierarchy is as follows:
class RuntimeDyldMachO
Implemented in RuntimeDyldMachO.{h,cpp}
Contains logic that is completely independent of the target. This consists
mostly of MachO helper utilities which the derived classes use to get their
work done.
template <typename Impl>
class RuntimeDyldMachOCRTPBase<Impl> : public RuntimeDyldMachO
Implemented in RuntimeDyldMachO.h
Contains generic MachO algorithms/data structures that defer to the Impl class
for target-specific behaviors.
RuntimeDyldMachOARM : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM>
RuntimeDyldMachOARM64 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM64>
RuntimeDyldMachOI386 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386>
RuntimeDyldMachOX86_64 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOX86_64>
Implemented in their respective *.h files in lib/ExecutionEngine/RuntimeDyld/MachOTargets
Each of these contains the relocation logic specific to their target architecture.
llvm-svn: 213293
Diffstat (limited to 'llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h')
| -rw-r--r-- | llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h new file mode 100644 index 00000000000..856c6ca3035 --- /dev/null +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -0,0 +1,315 @@ +//===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_RUNTIMEDYLDMACHOI386_H +#define LLVM_RUNTIMEDYLDMACHOI386_H + +#include "../RuntimeDyldMachO.h" + +#define DEBUG_TYPE "dyld" + +namespace llvm { + +class RuntimeDyldMachOI386 + : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { +public: + RuntimeDyldMachOI386(RTDyldMemoryManager *MM) + : RuntimeDyldMachOCRTPBase(MM) {} + + unsigned getMaxStubSize() override { return 0; } + + unsigned getStubAlignment() override { return 1; } + + relocation_iterator + processRelocationRef(unsigned SectionID, relocation_iterator RelI, + ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, + const SymbolTableMap &Symbols, StubMap &Stubs) override { + const MachOObjectFile &Obj = + static_cast<const MachOObjectFile &>(*ObjImg.getObjectFile()); + MachO::any_relocation_info RelInfo = + Obj.getRelocation(RelI->getRawDataRefImpl()); + uint32_t RelType = Obj.getAnyRelocationType(RelInfo); + + if (Obj.isRelocationScattered(RelInfo)) { + if (RelType == MachO::GENERIC_RELOC_SECTDIFF || + RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) + return processSECTDIFFRelocation(SectionID, RelI, ObjImg, + ObjSectionToID); + else if (Arch == Triple::x86 && RelType == MachO::GENERIC_RELOC_VANILLA) + return processI386ScatteredVANILLA(SectionID, RelI, ObjImg, + ObjSectionToID); + llvm_unreachable("Unhandled scattered relocation."); + } + + RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI)); + RelocationValueRef Value( + getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + + // Addends for external, PC-rel relocations on i386 point back to the zero + // offset. Calculate the final offset from the relocation target instead. + // This allows us to use the same logic for both external and internal + // relocations in resolveI386RelocationRef. + // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); + // if (IsExtern && RE.IsPCRel) { + // uint64_t RelocAddr = 0; + // RelI->getAddress(RelocAddr); + // Value.Addend += RelocAddr + 4; + // } + if (RE.IsPCRel) + makeValueAddendPCRel(Value, ObjImg, RelI); + + RE.Addend = Value.Addend; + + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + + return ++RelI; + } + + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) { + DEBUG(dumpRelocationToResolve(RE, Value)); + + const SectionEntry &Section = Sections[RE.SectionID]; + uint8_t *LocalAddress = Section.Address + RE.Offset; + + if (RE.IsPCRel) { + uint64_t FinalAddress = Section.LoadAddress + RE.Offset; + Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. + } + + switch (RE.RelType) { + default: + llvm_unreachable("Invalid relocation type!"); + case MachO::GENERIC_RELOC_VANILLA: + writeBytesUnaligned(LocalAddress, Value + RE.Addend, 1 << RE.Size); + break; + case MachO::GENERIC_RELOC_SECTDIFF: + case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { + uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress; + uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress; + assert((Value == SectionABase || Value == SectionBBase) && + "Unexpected SECTDIFF relocation value."); + Value = SectionABase - SectionBBase + RE.Addend; + writeBytesUnaligned(LocalAddress, Value, 1 << RE.Size); + break; + } + case MachO::GENERIC_RELOC_PB_LA_PTR: + Error("Relocation type not implemented yet!"); + } + } + + void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + const SectionRef &Section) { + StringRef Name; + Section.getName(Name); + + if (Name == "__jump_table") + populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), Section, + SectionID); + else if (Name == "__pointers") + populatePointersSection(cast<MachOObjectFile>(*ObjImg.getObjectFile()), + Section, SectionID); + } + +private: + relocation_iterator + processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, + ObjectImage &Obj, + ObjSectionToIDMap &ObjSectionToID) { + const MachOObjectFile *MachO = + static_cast<const MachOObjectFile *>(Obj.getObjectFile()); + MachO::any_relocation_info RE = + MachO->getRelocation(RelI->getRawDataRefImpl()); + + SectionEntry &Section = Sections[SectionID]; + uint32_t RelocType = MachO->getAnyRelocationType(RE); + bool IsPCRel = MachO->getAnyRelocationPCRel(RE); + unsigned Size = MachO->getAnyRelocationLength(RE); + uint64_t Offset; + RelI->getOffset(Offset); + uint8_t *LocalAddress = Section.Address + Offset; + unsigned NumBytes = 1 << Size; + int64_t Addend = 0; + memcpy(&Addend, LocalAddress, NumBytes); + + ++RelI; + MachO::any_relocation_info RE2 = + MachO->getRelocation(RelI->getRawDataRefImpl()); + + uint32_t AddrA = MachO->getScatteredRelocationValue(RE); + section_iterator SAI = getSectionByAddress(*MachO, AddrA); + assert(SAI != MachO->section_end() && "Can't find section for address A"); + uint64_t SectionABase; + SAI->getAddress(SectionABase); + uint64_t SectionAOffset = AddrA - SectionABase; + SectionRef SectionA = *SAI; + bool IsCode; + SectionA.isText(IsCode); + uint32_t SectionAID = + findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); + + uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); + section_iterator SBI = getSectionByAddress(*MachO, AddrB); + assert(SBI != MachO->section_end() && "Can't find section for address B"); + uint64_t SectionBBase; + SBI->getAddress(SectionBBase); + uint64_t SectionBOffset = AddrB - SectionBBase; + SectionRef SectionB = *SBI; + uint32_t SectionBID = + findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID); + + if (Addend != AddrA - AddrB) + Error("Unexpected SECTDIFF relocation addend."); + + DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB + << ", Addend: " << Addend << ", SectionA ID: " << SectionAID + << ", SectionAOffset: " << SectionAOffset + << ", SectionB ID: " << SectionBID + << ", SectionBOffset: " << SectionBOffset << "\n"); + RelocationEntry R(SectionID, Offset, RelocType, 0, SectionAID, + SectionAOffset, SectionBID, SectionBOffset, IsPCRel, + Size); + + addRelocationForSection(R, SectionAID); + addRelocationForSection(R, SectionBID); + + return ++RelI; + } + + relocation_iterator processI386ScatteredVANILLA( + unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, + RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { + const MachOObjectFile *MachO = + static_cast<const MachOObjectFile *>(Obj.getObjectFile()); + MachO::any_relocation_info RE = + MachO->getRelocation(RelI->getRawDataRefImpl()); + + SectionEntry &Section = Sections[SectionID]; + uint32_t RelocType = MachO->getAnyRelocationType(RE); + bool IsPCRel = MachO->getAnyRelocationPCRel(RE); + unsigned Size = MachO->getAnyRelocationLength(RE); + uint64_t Offset; + RelI->getOffset(Offset); + uint8_t *LocalAddress = Section.Address + Offset; + unsigned NumBytes = 1 << Size; + int64_t Addend = 0; + memcpy(&Addend, LocalAddress, NumBytes); + + unsigned SymbolBaseAddr = MachO->getScatteredRelocationValue(RE); + section_iterator TargetSI = getSectionByAddress(*MachO, SymbolBaseAddr); + assert(TargetSI != MachO->section_end() && "Can't find section for symbol"); + uint64_t SectionBaseAddr; + TargetSI->getAddress(SectionBaseAddr); + SectionRef TargetSection = *TargetSI; + bool IsCode; + TargetSection.isText(IsCode); + uint32_t TargetSectionID = + findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID); + + Addend -= SectionBaseAddr; + RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size); + + addRelocationForSection(R, TargetSectionID); + + return ++RelI; + } + + // Populate stubs in __jump_table section. + void populateJumpTable(MachOObjectFile &Obj, const SectionRef &JTSection, + unsigned JTSectionID) { + assert(!Obj.is64Bit() && + "__jump_table section not supported in 64-bit MachO."); + + MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); + MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); + uint32_t JTSectionSize = Sec32.size; + unsigned FirstIndirectSymbol = Sec32.reserved1; + unsigned JTEntrySize = Sec32.reserved2; + unsigned NumJTEntries = JTSectionSize / JTEntrySize; + uint8_t *JTSectionAddr = getSectionAddress(JTSectionID); + unsigned JTEntryOffset = 0; + + assert((JTSectionSize % JTEntrySize) == 0 && + "Jump-table section does not contain a whole number of stubs?"); + + for (unsigned i = 0; i < NumJTEntries; ++i) { + unsigned SymbolIndex = + Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); + symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); + StringRef IndirectSymbolName; + SI->getName(IndirectSymbolName); + uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset; + createStubFunction(JTEntryAddr); + RelocationEntry RE(JTSectionID, JTEntryOffset + 1, + MachO::GENERIC_RELOC_VANILLA, 0, true, 2); + addRelocationForSymbol(RE, IndirectSymbolName); + JTEntryOffset += JTEntrySize; + } + } + + // Populate __pointers section. + void populatePointersSection(MachOObjectFile &Obj, + const SectionRef &PTSection, + unsigned PTSectionID) { + assert(!Obj.is64Bit() && + "__pointers 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 __pointers, 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; + } + } + + static section_iterator 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, SSize; + SI->getAddress(SAddr); + SI->getSize(SSize); + if ((Addr >= SAddr) && (Addr < SAddr + SSize)) + return SI; + } + + return SE; + } +}; +} + +#undef DEBUG_TYPE + +#endif // LLVM_RUNTIMEDYLDMACHOI386_H |

