X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FExecutionEngine%2FRuntimeDyld%2FRuntimeDyld.cpp;h=d45b47218ae7a2543289c1f8825b5c3d89337618;hp=f0bd4e34a866cb3dea7f8c0b43f8035b155913e9;hb=f4ccd110750a3f3fe6a107d5c74c649c2a0dc407;hpb=3ecfcc20c15f9d430b2938416b63d7bbd4d45dec diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index f0bd4e34a86..d45b47218ae 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -13,13 +13,14 @@ #define DEBUG_TYPE "dyld" #include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "JITRegistrar.h" #include "ObjectImageCommon.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldImpl.h" #include "RuntimeDyldMachO.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Object/ELF.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MutexGuard.h" using namespace llvm; using namespace llvm::object; @@ -27,30 +28,44 @@ using namespace llvm::object; // Empty out-of-line virtual destructor as the key function. RuntimeDyldImpl::~RuntimeDyldImpl() {} +// Pin the JITRegistrar's and ObjectImage*'s vtables to this file. +void JITRegistrar::anchor() {} +void ObjectImage::anchor() {} +void ObjectImageCommon::anchor() {} + namespace llvm { -StringRef RuntimeDyldImpl::getEHFrameSection() { - return StringRef(); +void RuntimeDyldImpl::registerEHFrames() { +} + +void RuntimeDyldImpl::deregisterEHFrames() { } // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { + MutexGuard locked(lock); + // First, resolve relocations associated with external symbols. resolveExternalSymbols(); // 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) { + // The Section here (Sections[i]) refers to the section in which the + // symbol for the relocation is located. The SectionID in the relocation + // entry provides the section to which the relocation will be applied. uint64_t Addr = Sections[i].LoadAddress; DEBUG(dbgs() << "Resolving relocations Section #" << i << "\t" << format("%p", (uint8_t *)Addr) << "\n"); resolveRelocationList(Relocations[i], Addr); + Relocations.erase(i); } } void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) { + MutexGuard locked(lock); for (unsigned i = 0, e = Sections.size(); i != e; ++i) { if (Sections[i].Address == LocalAddress) { reassignSectionAddress(i, TargetAddress); @@ -66,13 +81,37 @@ ObjectImage *RuntimeDyldImpl::createObjectImage(ObjectBuffer *InputBuffer) { return new ObjectImageCommon(InputBuffer); } -ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { - OwningPtr obj(createObjectImage(InputBuffer)); - if (!obj) - report_fatal_error("Unable to create object image from memory buffer!"); +ObjectImage *RuntimeDyldImpl::createObjectImageFromFile(ObjectFile *InputObject) { + return new ObjectImageCommon(InputObject); +} - Arch = (Triple::ArchType)obj->getArch(); +ObjectImage *RuntimeDyldImpl::loadObject(ObjectFile *InputObject) { + return loadObject(createObjectImageFromFile(InputObject)); +} +ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { + return loadObject(createObjectImage(InputBuffer)); +} + +ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { + MutexGuard locked(lock); + + std::unique_ptr Obj(InputObject); + if (!Obj) + return NULL; + + // Save information about our target + Arch = (Triple::ArchType)Obj->getArch(); + IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian(); + + // Compute the memory size required to load all sections to be loaded + // and pass this information to the memory manager + if (MemMgr->needsToReserveAllocationSpace()) { + uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; + computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW); + MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); + } + // Symbols found in this object StringMap LocalSymbols; // Used sections from the object file @@ -83,29 +122,26 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { // Maximum required total memory to allocate all common symbols uint64_t CommonSize = 0; - 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); + for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E; + ++I) { object::SymbolRef::Type SymType; StringRef Name; - Check(i->getType(SymType)); - Check(i->getName(Name)); + Check(I->getType(SymType)); + Check(I->getName(Name)); - uint32_t flags; - Check(i->getFlags(flags)); + uint32_t Flags = I->getFlags(); - bool isCommon = flags & SymbolRef::SF_Common; - if (isCommon) { + bool IsCommon = Flags & SymbolRef::SF_Common; + if (IsCommon) { // Add the common symbols to a list. We'll allocate them all below. uint32_t Align; - Check(i->getAlignment(Align)); + Check(I->getAlignment(Align)); uint64_t Size = 0; - Check(i->getSize(Size)); + Check(I->getSize(Size)); CommonSize += Size + Align; - CommonSymbols[*i] = CommonSymbolInfo(Size, Align); + CommonSymbols[*I] = CommonSymbolInfo(Size, Align); } else { if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || @@ -113,20 +149,20 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { uint64_t FileOffset; StringRef SectionData; bool IsCode; - section_iterator si = obj->end_sections(); - Check(i->getFileOffset(FileOffset)); - Check(i->getSection(si)); - if (si == obj->end_sections()) continue; - Check(si->getContents(SectionData)); - Check(si->isText(IsCode)); - const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + + section_iterator SI = Obj->end_sections(); + Check(I->getFileOffset(FileOffset)); + Check(I->getSection(SI)); + if (SI == Obj->end_sections()) continue; + Check(SI->getContents(SectionData)); + Check(SI->isText(IsCode)); + const uint8_t* SymPtr = (const uint8_t*)InputObject->getData().data() + (uintptr_t)FileOffset; uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)SectionData.begin()); - unsigned SectionID = findOrEmitSection(*obj, *si, IsCode, LocalSections); + unsigned SectionID = findOrEmitSection(*Obj, *SI, IsCode, LocalSections); LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) - << " flags: " << flags + << " flags: " << Flags << " SID: " << SectionID << " Offset: " << format("%p", SectOffset)); GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); @@ -137,36 +173,177 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { // Allocate common symbols if (CommonSize != 0) - emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols); + emitCommonSymbols(*Obj, CommonSymbols, CommonSize, LocalSymbols); // Parse and process 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; + for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections(); + SI != SE; ++SI) { + bool IsFirstRelocation = true; unsigned SectionID = 0; StubMap Stubs; - section_iterator RelocatedSection = si->getRelocatedSection(); - - for (relocation_iterator i = si->begin_relocations(), - e = si->end_relocations(); i != e; i.increment(err)) { - Check(err); + section_iterator RelocatedSection = SI->getRelocatedSection(); + for (relocation_iterator I = SI->relocation_begin(), + E = SI->relocation_end(); + I != E; ++I) { // If it's the first relocation in this section, find its SectionID - if (isFirstRelocation) { + if (IsFirstRelocation) { + bool IsCode = false; + Check(RelocatedSection->isText(IsCode)); SectionID = - findOrEmitSection(*obj, *RelocatedSection, true, LocalSections); + findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); - isFirstRelocation = false; + IsFirstRelocation = false; } - processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols, - Stubs); + processRelocationRef(SectionID, *I, *Obj, LocalSections, LocalSymbols, + Stubs); } } - return obj.take(); + // Give the subclasses a chance to tie-up any loose ends. + finalizeLoad(LocalSections); + + return Obj.release(); +} + +// A helper method for computeTotalAllocSize. +// Computes the memory size required to allocate sections with the given sizes, +// assuming that all sections are allocated with the given alignment +static uint64_t computeAllocationSizeForSections(std::vector& SectionSizes, + uint64_t Alignment) { + uint64_t TotalSize = 0; + for (size_t Idx = 0, Cnt = SectionSizes.size(); Idx < Cnt; Idx++) { + uint64_t AlignedSize = (SectionSizes[Idx] + Alignment - 1) / + Alignment * Alignment; + TotalSize += AlignedSize; + } + return TotalSize; +} + +// Compute an upper bound of the memory size that is required to load all sections +void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, + uint64_t& CodeSize, uint64_t& DataSizeRO, uint64_t& DataSizeRW) { + // Compute the size of all sections required for execution + std::vector CodeSectionSizes; + std::vector ROSectionSizes; + std::vector RWSectionSizes; + uint64_t MaxAlignment = sizeof(void*); + + // Collect sizes of all sections to be loaded; + // also determine the max alignment of all sections + for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + SI != SE; ++SI) { + const SectionRef &Section = *SI; + + bool IsRequired; + Check(Section.isRequiredForExecution(IsRequired)); + + // Consider only the sections that are required to be loaded for execution + if (IsRequired) { + uint64_t DataSize = 0; + uint64_t Alignment64 = 0; + bool IsCode = false; + bool IsReadOnly = false; + StringRef Name; + Check(Section.getSize(DataSize)); + Check(Section.getAlignment(Alignment64)); + Check(Section.isText(IsCode)); + Check(Section.isReadOnlyData(IsReadOnly)); + Check(Section.getName(Name)); + unsigned Alignment = (unsigned) Alignment64 & 0xffffffffL; + + uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section); + uint64_t SectionSize = DataSize + StubBufSize; + + // The .eh_frame section (at least on Linux) needs an extra four bytes padded + // with zeroes added at the end. For MachO objects, this section has a + // slightly different name, so this won't have any effect for MachO objects. + if (Name == ".eh_frame") + SectionSize += 4; + + if (SectionSize > 0) { + // save the total size of the section + if (IsCode) { + CodeSectionSizes.push_back(SectionSize); + } else if (IsReadOnly) { + ROSectionSizes.push_back(SectionSize); + } else { + RWSectionSizes.push_back(SectionSize); + } + // update the max alignment + if (Alignment > MaxAlignment) { + MaxAlignment = Alignment; + } + } + } + } + + // Compute the size of all common symbols + uint64_t CommonSize = 0; + for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); + I != E; ++I) { + uint32_t Flags = I->getFlags(); + if (Flags & SymbolRef::SF_Common) { + // Add the common symbols to a list. We'll allocate them all below. + uint64_t Size = 0; + Check(I->getSize(Size)); + CommonSize += Size; + } + } + if (CommonSize != 0) { + RWSectionSizes.push_back(CommonSize); + } + + // Compute the required allocation space for each different type of sections + // (code, read-only data, read-write data) assuming that all sections are + // allocated with the max alignment. Note that we cannot compute with the + // individual alignments of the sections, because then the required size + // depends on the order, in which the sections are allocated. + CodeSize = computeAllocationSizeForSections(CodeSectionSizes, MaxAlignment); + DataSizeRO = computeAllocationSizeForSections(ROSectionSizes, MaxAlignment); + DataSizeRW = computeAllocationSizeForSections(RWSectionSizes, MaxAlignment); +} + +// compute stub buffer size for the given section +unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, + const SectionRef &Section) { + unsigned StubSize = getMaxStubSize(); + if (StubSize == 0) { + return 0; + } + // FIXME: this is an inefficient way to handle this. We should computed the + // necessary section allocation size in loadObject by walking all the sections + // once. + unsigned StubBufSize = 0; + for (section_iterator SI = Obj.begin_sections(), + SE = Obj.end_sections(); + SI != SE; ++SI) { + section_iterator RelSecI = SI->getRelocatedSection(); + if (!(RelSecI == Section)) + continue; + + for (relocation_iterator I = SI->relocation_begin(), + E = SI->relocation_end(); + I != E; ++I) { + StubBufSize += StubSize; + } + } + + // Get section data size and alignment + uint64_t Alignment64; + uint64_t DataSize; + Check(Section.getSize(DataSize)); + Check(Section.getAlignment(Alignment64)); + + // Add stubbuf size alignment + unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; + unsigned StubAlignment = getStubAlignment(); + unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment); + if (StubAlignment > EndAlignment) + StubBufSize += StubAlignment - EndAlignment; + return StubBufSize; } void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, @@ -175,8 +352,8 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, SymbolTableMap &SymbolTable) { // Allocate memory for the section unsigned SectionID = Sections.size(); - uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void*), - SectionID, false); + uint8_t *Addr = MemMgr->allocateDataSection( + TotalSize, sizeof(void*), SectionID, StringRef(), false); if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; @@ -214,28 +391,6 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, const SectionRef &Section, bool IsCode) { - unsigned StubBufSize = 0, - StubSize = getMaxStubSize(); - error_code err; - const ObjectFile *ObjFile = Obj.getObjectFile(); - // FIXME: this is an inefficient way to handle this. We should computed the - // necessary section allocation size in loadObject by walking all the sections - // once. - if (StubSize > 0) { - for (section_iterator SI = ObjFile->begin_sections(), - SE = ObjFile->end_sections(); - SI != SE; SI.increment(err), Check(err)) { - section_iterator RelSecI = SI->getRelocatedSection(); - if (!(RelSecI == Section)) - continue; - - for (relocation_iterator I = SI->begin_relocations(), - E = SI->end_relocations(); I != E; I.increment(err), Check(err)) { - StubBufSize += StubSize; - } - } - } - StringRef data; uint64_t Alignment64; Check(Section.getContents(data)); @@ -247,6 +402,8 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, bool IsZeroInit; bool IsReadOnly; uint64_t DataSize; + unsigned PaddingSize = 0; + unsigned StubBufSize = 0; StringRef Name; Check(Section.isRequiredForExecution(IsRequired)); Check(Section.isVirtual(IsVirtual)); @@ -254,14 +411,16 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, Check(Section.isReadOnlyData(IsReadOnly)); Check(Section.getSize(DataSize)); Check(Section.getName(Name)); - if (StubSize > 0) { - unsigned StubAlignment = getStubAlignment(); - unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment); - if (StubAlignment > EndAlignment) - StubBufSize += StubAlignment - EndAlignment; - } + + StubBufSize = computeSectionStubBufSize(Obj, Section); + + // The .eh_frame section (at least on Linux) needs an extra four bytes padded + // with zeroes added at the end. For MachO objects, this section has a + // slightly different name, so this won't have any effect for MachO objects. + if (Name == ".eh_frame") + PaddingSize = 4; - unsigned Allocate; + uintptr_t Allocate; unsigned SectionID = Sections.size(); uint8_t *Addr; const char *pData = 0; @@ -269,10 +428,11 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, // Some sections, such as debug info, don't need to be loaded for execution. // Leave those where they are. if (IsRequired) { - Allocate = DataSize + StubBufSize; + Allocate = DataSize + PaddingSize + StubBufSize; Addr = IsCode - ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) - : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, IsReadOnly); + ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID, Name) + : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, Name, + IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); @@ -286,6 +446,13 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, else memcpy(Addr, pData, DataSize); + // Fill in any extra bytes we allocated for padding + if (PaddingSize != 0) { + memset(Addr + DataSize, 0, PaddingSize); + // Update the DataSize variable so that the stub offset is set correctly. + DataSize += PaddingSize; + } + DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", pData) @@ -396,7 +563,7 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { StubAddr++; *StubAddr = NopInstr; return Addr; - } else if (Arch == Triple::ppc64) { + } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { // PowerPC64 stub: the address points to a function descriptor // instead of the function itself. Load the function address // on r11 and sets it to control register. Also loads the function @@ -421,6 +588,10 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) { writeInt16BE(Addr+6, 0x07F1); // brc 15,%r1 // 8-byte address stored at Addr + 8 return Addr; + } else if (Arch == Triple::x86_64) { + *Addr = 0xFF; // jmp + *(Addr+1) = 0x25; // rip + // 32-bit PC-relative address of the GOT entry will be stored at Addr+2 } return Addr; } @@ -454,30 +625,52 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs, } void RuntimeDyldImpl::resolveExternalSymbols() { - StringMap::iterator i = ExternalSymbolRelocations.begin(), - e = ExternalSymbolRelocations.end(); - for (; i != e; i++) { + while(!ExternalSymbolRelocations.empty()) { + StringMap::iterator i = ExternalSymbolRelocations.begin(); + StringRef Name = i->first(); - RelocationList &Relocs = i->second; - SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name); - if (Loc == GlobalSymbolTable.end()) { - if (Name.size() == 0) { - // This is an absolute symbol, use an address of zero. - DEBUG(dbgs() << "Resolving absolute relocations." << "\n"); - resolveRelocationList(Relocs, 0); + if (Name.size() == 0) { + // This is an absolute symbol, use an address of zero. + DEBUG(dbgs() << "Resolving absolute relocations." << "\n"); + RelocationList &Relocs = i->second; + resolveRelocationList(Relocs, 0); + } else { + uint64_t Addr = 0; + SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name); + if (Loc == GlobalSymbolTable.end()) { + // This is an external symbol, try to get its address from + // MemoryManager. + Addr = MemMgr->getSymbolAddress(Name.data()); + // The call to getSymbolAddress may have caused additional modules to + // be loaded, which may have added new entries to the + // ExternalSymbolRelocations map. Consquently, we need to update our + // iterator. This is also why retrieval of the relocation list + // associated with this symbol is deferred until below this point. + // New entries may have been added to the relocation list. + i = ExternalSymbolRelocations.find(Name); } else { - // This is an external symbol, try to get its address from - // MemoryManager. - uint8_t *Addr = (uint8_t*) MemMgr->getPointerToNamedFunction(Name.data(), - true); - DEBUG(dbgs() << "Resolving relocations Name: " << Name - << "\t" << format("%p", Addr) - << "\n"); - resolveRelocationList(Relocs, (uintptr_t)Addr); + // We found the symbol in our global table. It was probably in a + // Module that we loaded previously. + SymbolLoc SymLoc = Loc->second; + Addr = getSectionLoadAddress(SymLoc.first) + SymLoc.second; } - } else { - report_fatal_error("Expected external symbol"); + + // FIXME: Implement error handling that doesn't kill the host program! + if (!Addr) + report_fatal_error("Program used external function '" + Name + + "' which could not be resolved!"); + + updateGOTEntries(Name, Addr); + DEBUG(dbgs() << "Resolving relocations Name: " << Name + << "\t" << format("0x%lx", Addr) + << "\n"); + // This list may have been updated when we called getSymbolAddress, so + // don't change this code to get the list earlier. + RelocationList &Relocs = i->second; + resolveRelocationList(Relocs, Addr); } + + ExternalSymbolRelocations.erase(i); } } @@ -499,6 +692,22 @@ RuntimeDyld::~RuntimeDyld() { delete Dyld; } +ObjectImage *RuntimeDyld::loadObject(ObjectFile *InputObject) { + if (!Dyld) { + if (InputObject->isELF()) + Dyld = new RuntimeDyldELF(MM); + else if (InputObject->isMachO()) + Dyld = new RuntimeDyldMachO(MM); + else + report_fatal_error("Incompatible object format!"); + } else { + if (!Dyld->isCompatibleFile(InputObject)) + report_fatal_error("Incompatible object format!"); + } + + return Dyld->loadObject(InputObject); +} + ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) { if (!Dyld) { sys::fs::file_magic Type = @@ -526,7 +735,10 @@ ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) { case sys::fs::file_magic::bitcode: case sys::fs::file_magic::archive: case sys::fs::file_magic::coff_object: + case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: + case sys::fs::file_magic::macho_universal_binary: + case sys::fs::file_magic::windows_resource: report_fatal_error("Incompatible object format!"); } } else { @@ -538,10 +750,14 @@ ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) { } void *RuntimeDyld::getSymbolAddress(StringRef Name) { + if (!Dyld) + return NULL; return Dyld->getSymbolAddress(Name); } uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) { + if (!Dyld) + return 0; return Dyld->getSymbolLoadAddress(Name); } @@ -563,8 +779,14 @@ StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); } -StringRef RuntimeDyld::getEHFrameSection() { - return Dyld->getEHFrameSection(); +void RuntimeDyld::registerEHFrames() { + if (Dyld) + Dyld->registerEHFrames(); +} + +void RuntimeDyld::deregisterEHFrames() { + if (Dyld) + Dyld->deregisterEHFrames(); } } // end namespace llvm