//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "dyld"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "JITRegistrar.h"
#include "ObjectImageCommon.h"
+#include "RuntimeDyldCheckerImpl.h"
#include "RuntimeDyldELF.h"
#include "RuntimeDyldImpl.h"
#include "RuntimeDyldMachO.h"
using namespace llvm;
using namespace llvm::object;
+#define DEBUG_TYPE "dyld"
+
// Empty out-of-line virtual destructor as the key function.
RuntimeDyldImpl::~RuntimeDyldImpl() {}
// 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"
+ DEBUG(dbgs() << "Resolving relocations Section #" << i << "\t"
<< format("%p", (uint8_t *)Addr) << "\n");
resolveRelocationList(Relocations[i], Addr);
Relocations.erase(i);
llvm_unreachable("Attempting to remap address of unknown section!");
}
-static error_code getOffset(const SymbolRef &Sym, uint64_t &Result) {
+static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) {
uint64_t Address;
- if (error_code EC = Sym.getAddress(Address))
+ if (std::error_code EC = Sym.getAddress(Address))
return EC;
if (Address == UnknownAddressOrSize) {
const ObjectFile *Obj = Sym.getObject();
section_iterator SecI(Obj->section_begin());
- if (error_code EC = Sym.getSection(SecI))
+ if (std::error_code EC = Sym.getSection(SecI))
return EC;
if (SecI == Obj->section_end()) {
}
uint64_t SectionAddress;
- if (error_code EC = SecI->getAddress(SectionAddress))
+ if (std::error_code EC = SecI->getAddress(SectionAddress))
return EC;
Result = Address - SectionAddress;
std::unique_ptr<ObjectImage> Obj(InputObject);
if (!Obj)
- return NULL;
+ return nullptr;
// Save information about our target
Arch = (Triple::ArchType)Obj->getArch();
// Parse symbols
DEBUG(dbgs() << "Parse symbols:\n");
- for (const SymbolRef &Sym : Obj->symbols()) {
+ for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E;
+ ++I) {
object::SymbolRef::Type SymType;
StringRef Name;
- Check(Sym.getType(SymType));
- Check(Sym.getName(Name));
+ Check(I->getType(SymType));
+ Check(I->getName(Name));
- uint32_t Flags = Sym.getFlags();
+ uint32_t Flags = I->getFlags();
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(Sym.getAlignment(Align));
- uint64_t Size = 0;
- Check(Sym.getSize(Size));
- CommonSize += Size + Align;
- CommonSymbols[Sym] = CommonSymbolInfo(Size, Align);
+ if (!GlobalSymbolTable.count(Name)) {
+ uint32_t Align;
+ Check(I->getAlignment(Align));
+ uint64_t Size = 0;
+ Check(I->getSize(Size));
+ CommonSize += Size + Align;
+ CommonSymbols[*I] = CommonSymbolInfo(Size, Align);
+ }
} else {
if (SymType == object::SymbolRef::ST_Function ||
SymType == object::SymbolRef::ST_Data ||
StringRef SectionData;
bool IsCode;
section_iterator SI = Obj->end_sections();
- Check(getOffset(Sym, SectOffset));
- Check(Sym.getSection(SI));
+ Check(getOffset(*I, SectOffset));
+ Check(I->getSection(SI));
if (SI == Obj->end_sections())
continue;
Check(SI->getContents(SectionData));
// Allocate common symbols
if (CommonSize != 0)
- emitCommonSymbols(*Obj, CommonSymbols, CommonSize, LocalSymbols);
+ emitCommonSymbols(*Obj, CommonSymbols, CommonSize, GlobalSymbolTable);
// Parse and process relocations
DEBUG(dbgs() << "Parse relocations:\n");
- for (const SectionRef &Section : Obj->sections()) {
+ for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
+ SI != SE; ++SI) {
unsigned SectionID = 0;
StubMap Stubs;
- section_iterator RelocatedSection = Section.getRelocatedSection();
+ section_iterator RelocatedSection = SI->getRelocatedSection();
- relocation_iterator I = Section.relocation_begin();
- relocation_iterator E = Section.relocation_end();
+ relocation_iterator I = SI->relocation_begin();
+ relocation_iterator E = SI->relocation_end();
if (I == E && !ProcessAllSections)
continue;
for (; I != E;)
I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols,
Stubs);
+
+ // If there is an attached checker, notify it about the stubs for this
+ // section so that they can be verified.
+ if (Checker)
+ Checker->registerStubMap(Obj->getImageName(), SectionID, Stubs);
}
// Give the subclasses a chance to tie-up any loose ends.
- finalizeLoad(LocalSections);
+ finalizeLoad(*Obj, LocalSections);
return Obj.release();
}
computeAllocationSizeForSections(std::vector<uint64_t> &SectionSizes,
uint64_t Alignment) {
uint64_t TotalSize = 0;
- for (uint64_t Size : SectionSizes) {
- uint64_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment;
+ for (size_t Idx = 0, Cnt = SectionSizes.size(); Idx < Cnt; Idx++) {
+ uint64_t AlignedSize =
+ (SectionSizes[Idx] + Alignment - 1) / Alignment * Alignment;
TotalSize += AlignedSize;
}
return TotalSize;
// Collect sizes of all sections to be loaded;
// also determine the max alignment of all sections
- for (const SectionRef &Section : Obj.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));
// necessary section allocation size in loadObject by walking all the sections
// once.
unsigned StubBufSize = 0;
- for (const SectionRef &Section : Obj.sections()) {
- section_iterator RelSecI = Section.getRelocatedSection();
+ for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections();
+ SI != SE; ++SI) {
+ section_iterator RelSecI = SI->getRelocatedSection();
if (!(RelSecI == Section))
continue;
- for (const RelocationRef &Reloc : Section.relocations()) {
+ for (const RelocationRef &Reloc : SI->relocations()) {
(void)Reloc;
StubBufSize += StubSize;
}
<< format("%p", Addr) << " DataSize: " << TotalSize << "\n");
// Assign the address of each symbol
- for (const auto &Entry : CommonSymbols) {
- uint64_t Size = Entry.second.first;
- uint64_t Align = Entry.second.second;
+ for (CommonSymbolMap::const_iterator it = CommonSymbols.begin(),
+ itEnd = CommonSymbols.end(); it != itEnd; ++it) {
+ uint64_t Size = it->second.first;
+ uint64_t Align = it->second.second;
StringRef Name;
- Entry.first.getName(Name);
+ it->first.getName(Name);
if (Align) {
// This symbol has an alignment requirement.
uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align);
DEBUG(dbgs() << "Allocating common symbol " << Name << " address "
<< format("%p\n", Addr));
}
- Obj.updateSymbolAddress(Entry.first, (uint64_t)Addr);
+ Obj.updateSymbolAddress(it->first, (uint64_t)Addr);
SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset);
Offset += Size;
Addr += Size;
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) {
+uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
+ unsigned AbiVariant) {
if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) {
// This stub has to be able to access the full address space,
// since symbol lookup won't necessarily find a handy, in-range,
*StubAddr = NopInstr;
return Addr;
} 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
- // TOC in r2 and environment pointer to r11.
+ // Depending on which version of the ELF ABI is in use, we need to
+ // generate one of two variants of the stub. They both start with
+ // the same sequence to load the target address into r12.
writeInt32BE(Addr, 0x3D800000); // lis r12, highest(addr)
writeInt32BE(Addr+4, 0x618C0000); // ori r12, higher(addr)
writeInt32BE(Addr+8, 0x798C07C6); // sldi r12, r12, 32
writeInt32BE(Addr+12, 0x658C0000); // oris r12, r12, h(addr)
writeInt32BE(Addr+16, 0x618C0000); // ori r12, r12, l(addr)
- writeInt32BE(Addr+20, 0xF8410028); // std r2, 40(r1)
- writeInt32BE(Addr+24, 0xE96C0000); // ld r11, 0(r12)
- writeInt32BE(Addr+28, 0xE84C0008); // ld r2, 0(r12)
- writeInt32BE(Addr+32, 0x7D6903A6); // mtctr r11
- writeInt32BE(Addr+36, 0xE96C0010); // ld r11, 16(r2)
- writeInt32BE(Addr+40, 0x4E800420); // bctr
-
+ if (AbiVariant == 2) {
+ // PowerPC64 stub ELFv2 ABI: The address points to the function itself.
+ // The address is already in r12 as required by the ABI. Branch to it.
+ writeInt32BE(Addr+20, 0xF8410018); // std r2, 24(r1)
+ writeInt32BE(Addr+24, 0x7D8903A6); // mtctr r12
+ writeInt32BE(Addr+28, 0x4E800420); // bctr
+ } else {
+ // PowerPC64 stub ELFv1 ABI: The address points to a function descriptor.
+ // Load the function address on r11 and sets it to control register. Also
+ // loads the function TOC in r2 and environment pointer to r11.
+ writeInt32BE(Addr+20, 0xF8410028); // std r2, 40(r1)
+ writeInt32BE(Addr+24, 0xE96C0000); // ld r11, 0(r12)
+ writeInt32BE(Addr+28, 0xE84C0008); // ld r2, 0(r12)
+ writeInt32BE(Addr+32, 0x7D6903A6); // mtctr r11
+ writeInt32BE(Addr+36, 0xE96C0010); // ld r11, 16(r2)
+ writeInt32BE(Addr+40, 0x4E800420); // bctr
+ }
return Addr;
} else if (Arch == Triple::systemz) {
writeInt16BE(Addr, 0xC418); // lgrl %r1,.+8
*Addr = 0xFF; // jmp
*(Addr+1) = 0x25; // rip
// 32-bit PC-relative address of the GOT entry will be stored at Addr+2
+ } else if (Arch == Triple::x86) {
+ *Addr = 0xE9; // 32-bit pc-relative jump.
}
return 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);
}
// 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;
+ Checker = nullptr;
}
RuntimeDyld::~RuntimeDyld() { delete Dyld; }
static std::unique_ptr<RuntimeDyldELF>
-createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections) {
+createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections,
+ RuntimeDyldCheckerImpl *Checker) {
std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM));
Dyld->setProcessAllSections(ProcessAllSections);
+ Dyld->setRuntimeDyldChecker(Checker);
return Dyld;
}
static std::unique_ptr<RuntimeDyldMachO>
-createRuntimeDyldMachO(RTDyldMemoryManager *MM, bool ProcessAllSections) {
- std::unique_ptr<RuntimeDyldMachO> Dyld(new RuntimeDyldMachO(MM));
+createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM,
+ bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) {
+ std::unique_ptr<RuntimeDyldMachO> Dyld(RuntimeDyldMachO::create(Arch, MM));
Dyld->setProcessAllSections(ProcessAllSections);
+ Dyld->setRuntimeDyldChecker(Checker);
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();
+ Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker).release();
} else if (InputObject->isMachO()) {
- InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(InputObject));
+ InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(std::move(InputObject)));
if (!Dyld)
- Dyld = createRuntimeDyldMachO(MM, ProcessAllSections).release();
+ Dyld = createRuntimeDyldMachO(
+ static_cast<Triple::ArchType>(InputImage->getArch()),
+ MM, ProcessAllSections, Checker).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());
case sys::fs::file_magic::elf_core:
InputImage.reset(RuntimeDyldELF::createObjectImage(InputBuffer));
if (!Dyld)
- Dyld = createRuntimeDyldELF(MM, ProcessAllSections).release();
+ Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker).release();
break;
case sys::fs::file_magic::macho_object:
case sys::fs::file_magic::macho_executable:
case sys::fs::file_magic::macho_dsym_companion:
InputImage.reset(RuntimeDyldMachO::createObjectImage(InputBuffer));
if (!Dyld)
- Dyld = createRuntimeDyldMachO(MM, ProcessAllSections).release();
+ Dyld = createRuntimeDyldMachO(
+ static_cast<Triple::ArchType>(InputImage->getArch()),
+ MM, ProcessAllSections, Checker).release();
break;
case sys::fs::file_magic::unknown:
case sys::fs::file_magic::bitcode:
void *RuntimeDyld::getSymbolAddress(StringRef Name) {
if (!Dyld)
- return NULL;
+ return nullptr;
return Dyld->getSymbolAddress(Name);
}