//===-- RuntimeDyld.cpp - Run-time dynamic linker for MC-JIT ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Implementation of the MC-JIT runtime dynamic linker. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dyld" #include "RuntimeDyldImpl.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldMachO.h" #include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::object; // Empty out-of-line virtual destructor as the key function. RTDyldMemoryManager::~RTDyldMemoryManager() {} RuntimeDyldImpl::~RuntimeDyldImpl() {} namespace llvm { namespace { // Helper for extensive error checking in debug builds. error_code Check(error_code Err) { if (Err) { report_fatal_error(Err.message()); } return Err; } } // end anonymous namespace // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { // First, resolve relocations assotiated with external symbols. resolveSymbols(); // Just iterate over the sections we have and resolve all the relocations // in them. Gross overkill, but it gets the job done. for (int i = 0, e = Sections.size(); i != e; ++i) { reassignSectionAddress(i, Sections[i].LoadAddress); } } void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress, uint64_t TargetAddress) { for (unsigned i = 0, e = Sections.size(); i != e; ++i) { if (Sections[i].Address == LocalAddress) { reassignSectionAddress(i, TargetAddress); return; } } llvm_unreachable("Attempting to remap address of unknown section!"); } bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { // FIXME: ObjectFile don't modify MemoryBuffer. // It should use const MemoryBuffer as parameter. ObjectFile *obj = ObjectFile::createObjectFile(const_cast(InputBuffer)); Arch = (Triple::ArchType)obj->getArch(); LocalSymbolMap LocalSymbols; // Functions and data symbols from the // object file. ObjSectionToIDMap LocalSections; // Used sections from the object file error_code err; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols(); i != e; i.increment(err)) { Check(err); object::SymbolRef::Type SymType; StringRef Name; Check(i->getType(SymType)); Check(i->getName(Name)); if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data) { uint64_t FileOffset; uint32_t flags; StringRef sData; section_iterator si = obj->end_sections(); Check(i->getFileOffset(FileOffset)); Check(i->getFlags(flags)); Check(i->getSection(si)); if (si == obj->end_sections()) continue; Check(si->getContents(sData)); const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + (uintptr_t)FileOffset; uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin()); unsigned SectionID = findOrEmitSection(*si, SymType == object::SymbolRef::ST_Function, LocalSections); bool isGlobal = flags & SymbolRef::SF_Global; LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) << " flags: " << flags << " SID: " << SectionID << " Offset: " << format("%p", SectOffset)); if (isGlobal) SymbolTable[Name] = SymbolLoc(SectionID, SectOffset); } DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Parse and proccess relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator si = obj->begin_sections(), se = obj->end_sections(); si != se; si.increment(err)) { Check(err); bool isFirstRelocation = true; unsigned SectionID = 0; StubMap Stubs; for (relocation_iterator i = si->begin_relocations(), e = si->end_relocations(); i != e; i.increment(err)) { Check(err); // If it's first relocation in this section, find its SectionID if (isFirstRelocation) { SectionID = findOrEmitSection(*si, true, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); isFirstRelocation = false; } ObjRelocationInfo RI; RI.SectionID = SectionID; Check(i->getAdditionalInfo(RI.AdditionalInfo)); Check(i->getOffset(RI.Offset)); Check(i->getSymbol(RI.Symbol)); Check(i->getType(RI.Type)); DEBUG(dbgs() << "\t\tAddend: " << RI.AdditionalInfo << " Offset: " << format("%p", (uintptr_t)RI.Offset) << " Type: " << (uint32_t)(RI.Type & 0xffffffffL) << "\n"); processRelocationRef(RI, *obj, LocalSections, LocalSymbols, Stubs); } } return false; } unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section, bool IsCode) { unsigned StubBufSize = 0, StubSize = getMaxStubSize(); error_code err; if (StubSize > 0) { for (relocation_iterator i = Section.begin_relocations(), e = Section.end_relocations(); i != e; i.increment(err)) StubBufSize += StubSize; } StringRef data; uint64_t Alignment64; Check(Section.getContents(data)); Check(Section.getAlignment(Alignment64)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; unsigned DataSize = data.size(); unsigned Allocate = DataSize + StubBufSize; unsigned SectionID = Sections.size(); const char *pData = data.data(); uint8_t *Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) : MemMgr->allocateDataSection(Allocate, Alignment, SectionID); memcpy(Addr, pData, DataSize); DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " obj addr: " << format("%p", pData) << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); Sections.push_back(SectionEntry(Addr, Allocate, DataSize,(uintptr_t)pData)); return SectionID; } unsigned RuntimeDyldImpl::findOrEmitSection(const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections) { unsigned SectionID = 0; ObjSectionToIDMap::iterator i = LocalSections.find(Section); if (i != LocalSections.end()) SectionID = i->second; else { SectionID = emitSection(Section, IsCode); LocalSections[Section] = SectionID; } return SectionID; } void RuntimeDyldImpl::AddRelocation(const RelocationValueRef &Value, unsigned SectionID, uintptr_t Offset, uint32_t RelType) { DEBUG(dbgs() << "AddRelocation SymNamePtr: " << format("%p", Value.SymbolName) << " SID: " << Value.SectionID << " Addend: " << format("%p", Value.Addend) << " Offset: " << format("%p", Offset) << " RelType: " << format("%x", RelType) << "\n"); if (Value.SymbolName == 0) { Relocations[Value.SectionID].push_back(RelocationEntry( SectionID, Offset, RelType, Value.Addend)); } else SymbolRelocations[Value.SymbolName].push_back(RelocationEntry( SectionID, Offset, RelType, Value.Addend)); } uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { // TODO: There is only ARM far stub now. We should add the Thumb stub, // and stubs for branches Thumb - ARM and ARM - Thumb. if (Arch == Triple::arm) { uint32_t *StubAddr = (uint32_t*)Addr; *StubAddr = 0xe51ff004; // ldr pc,