//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "dyld"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "JITRegistrar.h"
#include "ObjectImageCommon.h"
using namespace llvm;
using namespace llvm::object;
+#define DEBUG_TYPE "dyld"
+
// Empty out-of-line virtual destructor as the key function.
RuntimeDyldImpl::~RuntimeDyldImpl() {}
llvm_unreachable("Attempting to remap address of unknown section!");
}
+static error_code getOffset(const SymbolRef &Sym, uint64_t &Result) {
+ uint64_t Address;
+ if (error_code EC = Sym.getAddress(Address))
+ return EC;
+
+ if (Address == UnknownAddressOrSize) {
+ Result = UnknownAddressOrSize;
+ return object_error::success;
+ }
+
+ const ObjectFile *Obj = Sym.getObject();
+ section_iterator SecI(Obj->section_begin());
+ if (error_code EC = Sym.getSection(SecI))
+ return EC;
+
+ if (SecI == Obj->section_end()) {
+ Result = UnknownAddressOrSize;
+ return object_error::success;
+ }
+
+ uint64_t SectionAddress;
+ if (error_code EC = SecI->getAddress(SectionAddress))
+ return EC;
+
+ Result = Address - SectionAddress;
+ return object_error::success;
+}
+
ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) {
MutexGuard locked(lock);
std::unique_ptr<ObjectImage> Obj(InputObject);
if (!Obj)
- return NULL;
+ return nullptr;
// Save information about our target
Arch = (Triple::ArchType)Obj->getArch();
if (SymType == object::SymbolRef::ST_Function ||
SymType == object::SymbolRef::ST_Data ||
SymType == object::SymbolRef::ST_Unknown) {
- uint64_t FileOffset;
+ uint64_t SectOffset;
StringRef SectionData;
bool IsCode;
section_iterator SI = Obj->end_sections();
- Check(I->getFileOffset(FileOffset));
+ Check(getOffset(*I, SectOffset));
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 *)Obj->getData().data() + (uintptr_t)FileOffset;
- uintptr_t SectOffset =
- (uintptr_t)(SymPtr - (const uint8_t *)SectionData.begin());
unsigned SectionID =
findOrEmitSection(*Obj, *SI, IsCode, LocalSections);
LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
- DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset)
- << " flags: " << Flags << " SID: " << SectionID
- << " Offset: " << format("%p", SectOffset));
+ DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset)
+ << " flags: " << Flags << " SID: " << SectionID);
GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset);
}
}
StubMap Stubs;
section_iterator RelocatedSection = SI->getRelocatedSection();
- if (SI->relocation_empty() && !ProcessAllSections)
+ relocation_iterator I = SI->relocation_begin();
+ relocation_iterator E = SI->relocation_end();
+
+ if (I == E && !ProcessAllSections)
continue;
bool IsCode = false;
findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections);
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
- for (relocation_iterator I = SI->relocation_begin(),
- E = SI->relocation_end(); I != E;)
+ for (; I != E;)
I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols,
Stubs);
}
uintptr_t Allocate;
unsigned SectionID = Sections.size();
uint8_t *Addr;
- const char *pData = 0;
+ const char *pData = nullptr;
// Some sections, such as debug info, don't need to be loaded for execution.
// Leave those where they are.
// to handle later processing (and by 'handle' I mean don't do anything
// with these sections).
Allocate = 0;
- Addr = 0;
+ Addr = nullptr;
DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name
<< " obj addr: " << format("%p", data.data()) << " new addr: 0"
<< " DataSize: " << DataSize << " StubBufSize: " << StubBufSize
}
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
- if (Arch == Triple::aarch64) {
+ if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be ||
+ Arch == Triple::arm64 || Arch == Triple::arm64_be) {
// This stub has to be able to access the full address space,
// since symbol lookup won't necessarily find a handy, in-range,
// PLT stub for functions which could be anywhere.
*StubAddr = 0xd61f0200; // br ip0
return Addr;
- } else if (Arch == Triple::arm) {
+ } else if (Arch == Triple::arm || Arch == Triple::armeb) {
// TODO: There is only ARM far stub now. We should add the Thumb stub,
// and stubs for branches Thumb - ARM and ARM - Thumb.
uint32_t *StubAddr = (uint32_t *)Addr;
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
const RelocationEntry &RE = Relocs[i];
// Ignore relocations for sections that were not loaded
- if (Sections[RE.SectionID].Address == 0)
+ if (Sections[RE.SectionID].Address == nullptr)
continue;
resolveRelocation(RE, Value);
}
}
void RuntimeDyldImpl::resolveExternalSymbols() {
+ StringMap<RelocationList> ProcessedSymbols;
+
while (!ExternalSymbolRelocations.empty()) {
StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin();
resolveRelocationList(Relocs, Addr);
}
+ ProcessedSymbols[i->first()] = i->second;
ExternalSymbolRelocations.erase(i);
}
+
+ // Restore the relocation entries that were consumed in the loop above:
+ //
+ // FIXME: Replace the following loop with:
+ // std::swap(ProcessedSymbols, ExternalSymbolRelocations)
+ // once StringMap has copy and move construction.
+ for (StringMap<RelocationList>::iterator I = ProcessedSymbols.begin(),
+ E = ProcessedSymbols.end();
+ I != E; ++I) {
+ ExternalSymbolRelocations[I->first()] = I->second;
+ }
}
//===----------------------------------------------------------------------===//
// though the public class spawns a new 'impl' instance for each load,
// they share a single memory manager. This can become a problem when page
// permissions are applied.
- Dyld = 0;
+ Dyld = nullptr;
MM = mm;
ProcessAllSections = false;
}
return Dyld;
}
-ObjectImage *RuntimeDyld::loadObject(ObjectFile *InputObject) {
+ObjectImage *RuntimeDyld::loadObject(std::unique_ptr<ObjectFile> InputObject) {
std::unique_ptr<ObjectImage> InputImage;
+ ObjectFile &Obj = *InputObject;
+
if (InputObject->isELF()) {
- InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(InputObject));
+ InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(std::move(InputObject)));
if (!Dyld)
Dyld = createRuntimeDyldELF(MM, ProcessAllSections).release();
} else if (InputObject->isMachO()) {
- InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(InputObject));
+ InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(std::move(InputObject)));
if (!Dyld)
Dyld = createRuntimeDyldMachO(MM, ProcessAllSections).release();
} else
report_fatal_error("Incompatible object format!");
- if (!Dyld->isCompatibleFile(InputObject))
+ if (!Dyld->isCompatibleFile(&Obj))
report_fatal_error("Incompatible object format!");
Dyld->loadObject(InputImage.get());
void *RuntimeDyld::getSymbolAddress(StringRef Name) {
if (!Dyld)
- return NULL;
+ return nullptr;
return Dyld->getSymbolAddress(Name);
}
Dyld->mapSectionAddress(LocalAddress, TargetAddress);
}
+bool RuntimeDyld::hasError() { return Dyld->hasError(); }
+
StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); }
void RuntimeDyld::registerEHFrames() {