1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-24 21:42:54 +02:00
llvm-mirror/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp

575 lines
21 KiB
C++
Raw Normal View History

2012-01-17 00:50:58 +01:00
//===-- 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 "llvm/ExecutionEngine/RuntimeDyld.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"
using namespace llvm;
using namespace llvm::object;
// Empty out-of-line virtual destructor as the key function.
RuntimeDyldImpl::~RuntimeDyldImpl() {}
namespace llvm {
StringRef RuntimeDyldImpl::getEHFrameSection() {
return StringRef();
}
MCJIT lazy relocation resolution and symbol address re-assignment. Add handling for tracking the relocations on symbols and resolving them. Keep track of the relocations even after they are resolved so that if the RuntimeDyld client moves the object, it can update the address and any relocations to that object will be updated. For our trival object file load/run test harness (llvm-rtdyld), this enables relocations between functions located in the same object module. It should be trivially extendable to load multiple objects with mutual references. As a simple example, the following now works (running on x86_64 Darwin 10.6): $ cat t.c int bar() { return 65; } int main() { return bar(); } $ clang t.c -fno-asynchronous-unwind-tables -o t.o -c $ otool -vt t.o t.o: (__TEXT,__text) section _bar: 0000000000000000 pushq %rbp 0000000000000001 movq %rsp,%rbp 0000000000000004 movl $0x00000041,%eax 0000000000000009 popq %rbp 000000000000000a ret 000000000000000b nopl 0x00(%rax,%rax) _main: 0000000000000010 pushq %rbp 0000000000000011 movq %rsp,%rbp 0000000000000014 subq $0x10,%rsp 0000000000000018 movl $0x00000000,0xfc(%rbp) 000000000000001f callq 0x00000024 0000000000000024 addq $0x10,%rsp 0000000000000028 popq %rbp 0000000000000029 ret $ llvm-rtdyld t.o -debug-only=dyld ; echo $? Function sym: '_bar' @ 0 Function sym: '_main' @ 16 Extracting function: _bar from [0, 15] allocated to 0x100153000 Extracting function: _main from [16, 41] allocated to 0x100154000 Relocation at '_main' + 16 from '_bar(Word1: 0x2d000000) Resolving relocation at '_main' + 16 (0x100154010) from '_bar (0x100153000)(pcrel, type: 2, Size: 4). loaded '_main' at: 0x100154000 65 $ llvm-svn: 129388
2011-04-12 23:20:41 +02:00
// Resolve the relocations for all symbols we currently know about.
void RuntimeDyldImpl::resolveRelocations() {
// 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);
}
MCJIT lazy relocation resolution and symbol address re-assignment. Add handling for tracking the relocations on symbols and resolving them. Keep track of the relocations even after they are resolved so that if the RuntimeDyld client moves the object, it can update the address and any relocations to that object will be updated. For our trival object file load/run test harness (llvm-rtdyld), this enables relocations between functions located in the same object module. It should be trivially extendable to load multiple objects with mutual references. As a simple example, the following now works (running on x86_64 Darwin 10.6): $ cat t.c int bar() { return 65; } int main() { return bar(); } $ clang t.c -fno-asynchronous-unwind-tables -o t.o -c $ otool -vt t.o t.o: (__TEXT,__text) section _bar: 0000000000000000 pushq %rbp 0000000000000001 movq %rsp,%rbp 0000000000000004 movl $0x00000041,%eax 0000000000000009 popq %rbp 000000000000000a ret 000000000000000b nopl 0x00(%rax,%rax) _main: 0000000000000010 pushq %rbp 0000000000000011 movq %rsp,%rbp 0000000000000014 subq $0x10,%rsp 0000000000000018 movl $0x00000000,0xfc(%rbp) 000000000000001f callq 0x00000024 0000000000000024 addq $0x10,%rsp 0000000000000028 popq %rbp 0000000000000029 ret $ llvm-rtdyld t.o -debug-only=dyld ; echo $? Function sym: '_bar' @ 0 Function sym: '_main' @ 16 Extracting function: _bar from [0, 15] allocated to 0x100153000 Extracting function: _main from [16, 41] allocated to 0x100154000 Relocation at '_main' + 16 from '_bar(Word1: 0x2d000000) Resolving relocation at '_main' + 16 (0x100154010) from '_bar (0x100153000)(pcrel, type: 2, Size: 4). loaded '_main' at: 0x100154000 65 $ llvm-svn: 129388
2011-04-12 23:20:41 +02:00
}
void RuntimeDyldImpl::mapSectionAddress(const 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!");
}
// Subclasses can implement this method to create specialized image instances.
// The caller owns the pointer that is returned.
ObjectImage *RuntimeDyldImpl::createObjectImage(ObjectBuffer *InputBuffer) {
return new ObjectImageCommon(InputBuffer);
}
ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) {
OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer));
if (!obj)
report_fatal_error("Unable to create object image from memory buffer!");
Arch = (Triple::ArchType)obj->getArch();
// Symbols found in this object
StringMap<SymbolLoc> LocalSymbols;
// Used sections from the object file
ObjSectionToIDMap LocalSections;
// Common symbols requiring allocation, with their sizes and alignments
CommonSymbolMap CommonSymbols;
// 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);
object::SymbolRef::Type SymType;
StringRef Name;
Check(i->getType(SymType));
Check(i->getName(Name));
uint32_t flags;
Check(i->getFlags(flags));
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));
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 ||
SymType == object::SymbolRef::ST_Unknown) {
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() +
(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));
GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset);
}
}
DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n");
}
// Allocate common symbols
if (CommonSize != 0)
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;
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);
// If it's the first relocation in this section, find its SectionID
if (isFirstRelocation) {
SectionID =
findOrEmitSection(*obj, *RelocatedSection, true, LocalSections);
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
isFirstRelocation = false;
}
processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols,
Stubs);
}
}
return obj.take();
}
void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
const CommonSymbolMap &CommonSymbols,
uint64_t TotalSize,
SymbolTableMap &SymbolTable) {
// Allocate memory for the section
unsigned SectionID = Sections.size();
uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void*),
SectionID, false);
if (!Addr)
report_fatal_error("Unable to allocate memory for common symbols!");
uint64_t Offset = 0;
Sections.push_back(SectionEntry(StringRef(), Addr, TotalSize, 0));
memset(Addr, 0, TotalSize);
DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID
<< " new addr: " << format("%p", Addr)
<< " DataSize: " << TotalSize
<< "\n");
// Assign the address of each symbol
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;
it->first.getName(Name);
if (Align) {
// This symbol has an alignment requirement.
uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align);
Addr += AlignOffset;
Offset += AlignOffset;
DEBUG(dbgs() << "Allocating common symbol " << Name << " address " <<
format("%p\n", Addr));
}
Obj.updateSymbolAddress(it->first, (uint64_t)Addr);
SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset);
Offset += Size;
Addr += Size;
}
}
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));
Check(Section.getAlignment(Alignment64));
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
bool IsRequired;
bool IsVirtual;
bool IsZeroInit;
bool IsReadOnly;
uint64_t DataSize;
PowerPC: Initial support for PowerPC64 MCJIT This patch adds initial support for MCJIT for PPC64-elf-abi. The TOC relocation and ODP handling is implemented. It fixes the following ExecutionEngine testcases: ExecutionEngine/2003-01-04-ArgumentBug.ll ExecutionEngine/2003-01-04-LoopTest.ll ExecutionEngine/2003-01-04-PhiTest.ll ExecutionEngine/2003-01-09-SARTest.ll ExecutionEngine/2003-01-10-FUCOM.ll ExecutionEngine/2003-01-15-AlignmentTest.ll ExecutionEngine/2003-05-11-PHIRegAllocBug.ll ExecutionEngine/2003-06-04-bzip2-bug.ll ExecutionEngine/2003-06-05-PHIBug.ll ExecutionEngine/2003-08-15-AllocaAssertion.ll ExecutionEngine/2003-08-21-EnvironmentTest.ll ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll ExecutionEngine/simplesttest.ll ExecutionEngine/simpletest.ll ExecutionEngine/stubs.ll ExecutionEngine/test-arith.ll ExecutionEngine/test-branch.ll ExecutionEngine/test-call-no-external-funcs.ll ExecutionEngine/test-cast.ll ExecutionEngine/test-common-symbols.ll ExecutionEngine/test-constantexpr.ll ExecutionEngine/test-fp-no-external-funcs.ll ExecutionEngine/test-fp.ll ExecutionEngine/test-global-init-nonzero.ll ExecutionEngine/test-global.ll ExecutionEngine/test-loadstore.ll ExecutionEngine/test-local.ll ExecutionEngine/test-logical.ll ExecutionEngine/test-loop.ll ExecutionEngine/test-phi.ll ExecutionEngine/test-ret.ll ExecutionEngine/test-return.ll ExecutionEngine/test-setcond-fp.ll ExecutionEngine/test-setcond-int.ll ExecutionEngine/test-shift.ll llvm-svn: 166678
2012-10-25 15:13:48 +02:00
StringRef Name;
Check(Section.isRequiredForExecution(IsRequired));
Check(Section.isVirtual(IsVirtual));
Check(Section.isZeroInit(IsZeroInit));
Check(Section.isReadOnlyData(IsReadOnly));
Check(Section.getSize(DataSize));
PowerPC: Initial support for PowerPC64 MCJIT This patch adds initial support for MCJIT for PPC64-elf-abi. The TOC relocation and ODP handling is implemented. It fixes the following ExecutionEngine testcases: ExecutionEngine/2003-01-04-ArgumentBug.ll ExecutionEngine/2003-01-04-LoopTest.ll ExecutionEngine/2003-01-04-PhiTest.ll ExecutionEngine/2003-01-09-SARTest.ll ExecutionEngine/2003-01-10-FUCOM.ll ExecutionEngine/2003-01-15-AlignmentTest.ll ExecutionEngine/2003-05-11-PHIRegAllocBug.ll ExecutionEngine/2003-06-04-bzip2-bug.ll ExecutionEngine/2003-06-05-PHIBug.ll ExecutionEngine/2003-08-15-AllocaAssertion.ll ExecutionEngine/2003-08-21-EnvironmentTest.ll ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll ExecutionEngine/simplesttest.ll ExecutionEngine/simpletest.ll ExecutionEngine/stubs.ll ExecutionEngine/test-arith.ll ExecutionEngine/test-branch.ll ExecutionEngine/test-call-no-external-funcs.ll ExecutionEngine/test-cast.ll ExecutionEngine/test-common-symbols.ll ExecutionEngine/test-constantexpr.ll ExecutionEngine/test-fp-no-external-funcs.ll ExecutionEngine/test-fp.ll ExecutionEngine/test-global-init-nonzero.ll ExecutionEngine/test-global.ll ExecutionEngine/test-loadstore.ll ExecutionEngine/test-local.ll ExecutionEngine/test-logical.ll ExecutionEngine/test-loop.ll ExecutionEngine/test-phi.ll ExecutionEngine/test-ret.ll ExecutionEngine/test-return.ll ExecutionEngine/test-setcond-fp.ll ExecutionEngine/test-setcond-int.ll ExecutionEngine/test-shift.ll llvm-svn: 166678
2012-10-25 15:13:48 +02:00
Check(Section.getName(Name));
if (StubSize > 0) {
unsigned StubAlignment = getStubAlignment();
unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
if (StubAlignment > EndAlignment)
StubBufSize += StubAlignment - EndAlignment;
}
unsigned Allocate;
unsigned SectionID = Sections.size();
uint8_t *Addr;
const char *pData = 0;
// Some sections, such as debug info, don't need to be loaded for execution.
// Leave those where they are.
if (IsRequired) {
Allocate = DataSize + StubBufSize;
Addr = IsCode
? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID)
: MemMgr->allocateDataSection(Allocate, Alignment, SectionID, IsReadOnly);
if (!Addr)
report_fatal_error("Unable to allocate section memory!");
// Virtual sections have no data in the object image, so leave pData = 0
if (!IsVirtual)
pData = data.data();
// Zero-initialize or copy the data from the image
if (IsZeroInit || IsVirtual)
memset(Addr, 0, DataSize);
else
memcpy(Addr, pData, DataSize);
DEBUG(dbgs() << "emitSection SectionID: " << SectionID
PowerPC: Initial support for PowerPC64 MCJIT This patch adds initial support for MCJIT for PPC64-elf-abi. The TOC relocation and ODP handling is implemented. It fixes the following ExecutionEngine testcases: ExecutionEngine/2003-01-04-ArgumentBug.ll ExecutionEngine/2003-01-04-LoopTest.ll ExecutionEngine/2003-01-04-PhiTest.ll ExecutionEngine/2003-01-09-SARTest.ll ExecutionEngine/2003-01-10-FUCOM.ll ExecutionEngine/2003-01-15-AlignmentTest.ll ExecutionEngine/2003-05-11-PHIRegAllocBug.ll ExecutionEngine/2003-06-04-bzip2-bug.ll ExecutionEngine/2003-06-05-PHIBug.ll ExecutionEngine/2003-08-15-AllocaAssertion.ll ExecutionEngine/2003-08-21-EnvironmentTest.ll ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll ExecutionEngine/simplesttest.ll ExecutionEngine/simpletest.ll ExecutionEngine/stubs.ll ExecutionEngine/test-arith.ll ExecutionEngine/test-branch.ll ExecutionEngine/test-call-no-external-funcs.ll ExecutionEngine/test-cast.ll ExecutionEngine/test-common-symbols.ll ExecutionEngine/test-constantexpr.ll ExecutionEngine/test-fp-no-external-funcs.ll ExecutionEngine/test-fp.ll ExecutionEngine/test-global-init-nonzero.ll ExecutionEngine/test-global.ll ExecutionEngine/test-loadstore.ll ExecutionEngine/test-local.ll ExecutionEngine/test-logical.ll ExecutionEngine/test-loop.ll ExecutionEngine/test-phi.ll ExecutionEngine/test-ret.ll ExecutionEngine/test-return.ll ExecutionEngine/test-setcond-fp.ll ExecutionEngine/test-setcond-int.ll ExecutionEngine/test-shift.ll llvm-svn: 166678
2012-10-25 15:13:48 +02:00
<< " Name: " << Name
<< " obj addr: " << format("%p", pData)
<< " new addr: " << format("%p", Addr)
<< " DataSize: " << DataSize
<< " StubBufSize: " << StubBufSize
<< " Allocate: " << Allocate
<< "\n");
Obj.updateSectionAddress(Section, (uint64_t)Addr);
}
else {
// Even if we didn't load the section, we need to record an entry for it
// to handle later processing (and by 'handle' I mean don't do anything
// with these sections).
Allocate = 0;
Addr = 0;
DEBUG(dbgs() << "emitSection SectionID: " << SectionID
PowerPC: Initial support for PowerPC64 MCJIT This patch adds initial support for MCJIT for PPC64-elf-abi. The TOC relocation and ODP handling is implemented. It fixes the following ExecutionEngine testcases: ExecutionEngine/2003-01-04-ArgumentBug.ll ExecutionEngine/2003-01-04-LoopTest.ll ExecutionEngine/2003-01-04-PhiTest.ll ExecutionEngine/2003-01-09-SARTest.ll ExecutionEngine/2003-01-10-FUCOM.ll ExecutionEngine/2003-01-15-AlignmentTest.ll ExecutionEngine/2003-05-11-PHIRegAllocBug.ll ExecutionEngine/2003-06-04-bzip2-bug.ll ExecutionEngine/2003-06-05-PHIBug.ll ExecutionEngine/2003-08-15-AllocaAssertion.ll ExecutionEngine/2003-08-21-EnvironmentTest.ll ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll ExecutionEngine/simplesttest.ll ExecutionEngine/simpletest.ll ExecutionEngine/stubs.ll ExecutionEngine/test-arith.ll ExecutionEngine/test-branch.ll ExecutionEngine/test-call-no-external-funcs.ll ExecutionEngine/test-cast.ll ExecutionEngine/test-common-symbols.ll ExecutionEngine/test-constantexpr.ll ExecutionEngine/test-fp-no-external-funcs.ll ExecutionEngine/test-fp.ll ExecutionEngine/test-global-init-nonzero.ll ExecutionEngine/test-global.ll ExecutionEngine/test-loadstore.ll ExecutionEngine/test-local.ll ExecutionEngine/test-logical.ll ExecutionEngine/test-loop.ll ExecutionEngine/test-phi.ll ExecutionEngine/test-ret.ll ExecutionEngine/test-return.ll ExecutionEngine/test-setcond-fp.ll ExecutionEngine/test-setcond-int.ll ExecutionEngine/test-shift.ll llvm-svn: 166678
2012-10-25 15:13:48 +02:00
<< " Name: " << Name
<< " obj addr: " << format("%p", data.data())
<< " new addr: 0"
<< " DataSize: " << DataSize
<< " StubBufSize: " << StubBufSize
<< " Allocate: " << Allocate
<< "\n");
}
Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
return SectionID;
}
unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj,
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(Obj, Section, IsCode);
LocalSections[Section] = SectionID;
}
return SectionID;
}
void RuntimeDyldImpl::addRelocationForSection(const RelocationEntry &RE,
unsigned SectionID) {
Relocations[SectionID].push_back(RE);
}
void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE,
StringRef SymbolName) {
// Relocation by symbol. If the symbol is found in the global symbol table,
// create an appropriate section relocation. Otherwise, add it to
// ExternalSymbolRelocations.
SymbolTableMap::const_iterator Loc =
GlobalSymbolTable.find(SymbolName);
if (Loc == GlobalSymbolTable.end()) {
ExternalSymbolRelocations[SymbolName].push_back(RE);
} else {
// Copy the RE since we want to modify its addend.
RelocationEntry RECopy = RE;
RECopy.Addend += Loc->second.second;
Relocations[Loc->second.first].push_back(RECopy);
}
}
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
if (Arch == Triple::aarch64) {
// 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.
uint32_t *StubAddr = (uint32_t*)Addr;
// Stub can use ip0 (== x16) to calculate address
*StubAddr = 0xd2e00010; // movz ip0, #:abs_g3:<addr>
StubAddr++;
*StubAddr = 0xf2c00010; // movk ip0, #:abs_g2_nc:<addr>
StubAddr++;
*StubAddr = 0xf2a00010; // movk ip0, #:abs_g1_nc:<addr>
StubAddr++;
*StubAddr = 0xf2800010; // movk ip0, #:abs_g0_nc:<addr>
StubAddr++;
*StubAddr = 0xd61f0200; // br ip0
return Addr;
} else if (Arch == Triple::arm) {
// 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;
*StubAddr = 0xe51ff004; // ldr pc,<label>
return (uint8_t*)++StubAddr;
} else if (Arch == Triple::mipsel || Arch == Triple::mips) {
uint32_t *StubAddr = (uint32_t*)Addr;
// 0: 3c190000 lui t9,%hi(addr).
// 4: 27390000 addiu t9,t9,%lo(addr).
// 8: 03200008 jr t9.
// c: 00000000 nop.
const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
const unsigned JrT9Instr = 0x03200008, NopInstr = 0x0;
*StubAddr = LuiT9Instr;
StubAddr++;
*StubAddr = AdduiT9Instr;
StubAddr++;
*StubAddr = JrT9Instr;
StubAddr++;
*StubAddr = NopInstr;
PowerPC: Initial support for PowerPC64 MCJIT This patch adds initial support for MCJIT for PPC64-elf-abi. The TOC relocation and ODP handling is implemented. It fixes the following ExecutionEngine testcases: ExecutionEngine/2003-01-04-ArgumentBug.ll ExecutionEngine/2003-01-04-LoopTest.ll ExecutionEngine/2003-01-04-PhiTest.ll ExecutionEngine/2003-01-09-SARTest.ll ExecutionEngine/2003-01-10-FUCOM.ll ExecutionEngine/2003-01-15-AlignmentTest.ll ExecutionEngine/2003-05-11-PHIRegAllocBug.ll ExecutionEngine/2003-06-04-bzip2-bug.ll ExecutionEngine/2003-06-05-PHIBug.ll ExecutionEngine/2003-08-15-AllocaAssertion.ll ExecutionEngine/2003-08-21-EnvironmentTest.ll ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll ExecutionEngine/simplesttest.ll ExecutionEngine/simpletest.ll ExecutionEngine/stubs.ll ExecutionEngine/test-arith.ll ExecutionEngine/test-branch.ll ExecutionEngine/test-call-no-external-funcs.ll ExecutionEngine/test-cast.ll ExecutionEngine/test-common-symbols.ll ExecutionEngine/test-constantexpr.ll ExecutionEngine/test-fp-no-external-funcs.ll ExecutionEngine/test-fp.ll ExecutionEngine/test-global-init-nonzero.ll ExecutionEngine/test-global.ll ExecutionEngine/test-loadstore.ll ExecutionEngine/test-local.ll ExecutionEngine/test-logical.ll ExecutionEngine/test-loop.ll ExecutionEngine/test-phi.ll ExecutionEngine/test-ret.ll ExecutionEngine/test-return.ll ExecutionEngine/test-setcond-fp.ll ExecutionEngine/test-setcond-int.ll ExecutionEngine/test-shift.ll llvm-svn: 166678
2012-10-25 15:13:48 +02:00
return Addr;
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
PowerPC: Initial support for PowerPC64 MCJIT This patch adds initial support for MCJIT for PPC64-elf-abi. The TOC relocation and ODP handling is implemented. It fixes the following ExecutionEngine testcases: ExecutionEngine/2003-01-04-ArgumentBug.ll ExecutionEngine/2003-01-04-LoopTest.ll ExecutionEngine/2003-01-04-PhiTest.ll ExecutionEngine/2003-01-09-SARTest.ll ExecutionEngine/2003-01-10-FUCOM.ll ExecutionEngine/2003-01-15-AlignmentTest.ll ExecutionEngine/2003-05-11-PHIRegAllocBug.ll ExecutionEngine/2003-06-04-bzip2-bug.ll ExecutionEngine/2003-06-05-PHIBug.ll ExecutionEngine/2003-08-15-AllocaAssertion.ll ExecutionEngine/2003-08-21-EnvironmentTest.ll ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll ExecutionEngine/simplesttest.ll ExecutionEngine/simpletest.ll ExecutionEngine/stubs.ll ExecutionEngine/test-arith.ll ExecutionEngine/test-branch.ll ExecutionEngine/test-call-no-external-funcs.ll ExecutionEngine/test-cast.ll ExecutionEngine/test-common-symbols.ll ExecutionEngine/test-constantexpr.ll ExecutionEngine/test-fp-no-external-funcs.ll ExecutionEngine/test-fp.ll ExecutionEngine/test-global-init-nonzero.ll ExecutionEngine/test-global.ll ExecutionEngine/test-loadstore.ll ExecutionEngine/test-local.ll ExecutionEngine/test-logical.ll ExecutionEngine/test-loop.ll ExecutionEngine/test-phi.ll ExecutionEngine/test-ret.ll ExecutionEngine/test-return.ll ExecutionEngine/test-setcond-fp.ll ExecutionEngine/test-setcond-int.ll ExecutionEngine/test-shift.ll llvm-svn: 166678
2012-10-25 15:13:48 +02:00
// 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.
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
return Addr;
} else if (Arch == Triple::systemz) {
writeInt16BE(Addr, 0xC418); // lgrl %r1,.+8
writeInt16BE(Addr+2, 0x0000);
writeInt16BE(Addr+4, 0x0004);
writeInt16BE(Addr+6, 0x07F1); // brc 15,%r1
// 8-byte address stored at Addr + 8
return Addr;
}
return Addr;
}
// Assign an address to a symbol name and resolve all the relocations
// associated with it.
void RuntimeDyldImpl::reassignSectionAddress(unsigned SectionID,
uint64_t Addr) {
// The address to use for relocation resolution is not
// the address of the local section buffer. We must be doing
// a remote execution environment of some sort. Relocations can't
// be applied until all the sections have been moved. The client must
// trigger this with a call to MCJIT::finalize() or
// RuntimeDyld::resolveRelocations().
//
// Addr is a uint64_t because we can't assume the pointer width
// of the target is the same as that of the host. Just use a generic
// "big enough" type.
Sections[SectionID].LoadAddress = Addr;
}
void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
uint64_t Value) {
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)
continue;
resolveRelocation(RE, Value);
}
}
void RuntimeDyldImpl::resolveExternalSymbols() {
StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin(),
e = ExternalSymbolRelocations.end();
for (; i != e; i++) {
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);
2013-02-20 19:24:34 +01:00
} 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);
}
} else {
report_fatal_error("Expected external symbol");
}
}
}
//===----------------------------------------------------------------------===//
// RuntimeDyld class implementation
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
// FIXME: There's a potential issue lurking here if a single instance of
// RuntimeDyld is used to load multiple objects. The current implementation
// associates a single memory manager with a RuntimeDyld instance. Even
// 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;
MM = mm;
}
RuntimeDyld::~RuntimeDyld() {
delete Dyld;
}
ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) {
if (!Dyld) {
sys::fs::file_magic Type =
sys::fs::identify_magic(InputBuffer->getBuffer());
switch (Type) {
case sys::fs::file_magic::elf_relocatable:
case sys::fs::file_magic::elf_executable:
case sys::fs::file_magic::elf_shared_object:
case sys::fs::file_magic::elf_core:
Dyld = new RuntimeDyldELF(MM);
break;
case sys::fs::file_magic::macho_object:
case sys::fs::file_magic::macho_executable:
case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib:
case sys::fs::file_magic::macho_core:
case sys::fs::file_magic::macho_preload_executable:
case sys::fs::file_magic::macho_dynamically_linked_shared_lib:
case sys::fs::file_magic::macho_dynamic_linker:
case sys::fs::file_magic::macho_bundle:
case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
case sys::fs::file_magic::macho_dsym_companion:
Dyld = new RuntimeDyldMachO(MM);
break;
case sys::fs::file_magic::unknown:
case sys::fs::file_magic::bitcode:
case sys::fs::file_magic::archive:
case sys::fs::file_magic::coff_object:
case sys::fs::file_magic::pecoff_executable:
case sys::fs::file_magic::macho_universal_binary:
report_fatal_error("Incompatible object format!");
}
} else {
if (!Dyld->isCompatibleFormat(InputBuffer))
report_fatal_error("Incompatible object format!");
}
return Dyld->loadObject(InputBuffer);
}
void *RuntimeDyld::getSymbolAddress(StringRef Name) {
return Dyld->getSymbolAddress(Name);
}
uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) {
return Dyld->getSymbolLoadAddress(Name);
}
MCJIT lazy relocation resolution and symbol address re-assignment. Add handling for tracking the relocations on symbols and resolving them. Keep track of the relocations even after they are resolved so that if the RuntimeDyld client moves the object, it can update the address and any relocations to that object will be updated. For our trival object file load/run test harness (llvm-rtdyld), this enables relocations between functions located in the same object module. It should be trivially extendable to load multiple objects with mutual references. As a simple example, the following now works (running on x86_64 Darwin 10.6): $ cat t.c int bar() { return 65; } int main() { return bar(); } $ clang t.c -fno-asynchronous-unwind-tables -o t.o -c $ otool -vt t.o t.o: (__TEXT,__text) section _bar: 0000000000000000 pushq %rbp 0000000000000001 movq %rsp,%rbp 0000000000000004 movl $0x00000041,%eax 0000000000000009 popq %rbp 000000000000000a ret 000000000000000b nopl 0x00(%rax,%rax) _main: 0000000000000010 pushq %rbp 0000000000000011 movq %rsp,%rbp 0000000000000014 subq $0x10,%rsp 0000000000000018 movl $0x00000000,0xfc(%rbp) 000000000000001f callq 0x00000024 0000000000000024 addq $0x10,%rsp 0000000000000028 popq %rbp 0000000000000029 ret $ llvm-rtdyld t.o -debug-only=dyld ; echo $? Function sym: '_bar' @ 0 Function sym: '_main' @ 16 Extracting function: _bar from [0, 15] allocated to 0x100153000 Extracting function: _main from [16, 41] allocated to 0x100154000 Relocation at '_main' + 16 from '_bar(Word1: 0x2d000000) Resolving relocation at '_main' + 16 (0x100154010) from '_bar (0x100153000)(pcrel, type: 2, Size: 4). loaded '_main' at: 0x100154000 65 $ llvm-svn: 129388
2011-04-12 23:20:41 +02:00
void RuntimeDyld::resolveRelocations() {
Dyld->resolveRelocations();
}
void RuntimeDyld::reassignSectionAddress(unsigned SectionID,
uint64_t Addr) {
Dyld->reassignSectionAddress(SectionID, Addr);
MCJIT lazy relocation resolution and symbol address re-assignment. Add handling for tracking the relocations on symbols and resolving them. Keep track of the relocations even after they are resolved so that if the RuntimeDyld client moves the object, it can update the address and any relocations to that object will be updated. For our trival object file load/run test harness (llvm-rtdyld), this enables relocations between functions located in the same object module. It should be trivially extendable to load multiple objects with mutual references. As a simple example, the following now works (running on x86_64 Darwin 10.6): $ cat t.c int bar() { return 65; } int main() { return bar(); } $ clang t.c -fno-asynchronous-unwind-tables -o t.o -c $ otool -vt t.o t.o: (__TEXT,__text) section _bar: 0000000000000000 pushq %rbp 0000000000000001 movq %rsp,%rbp 0000000000000004 movl $0x00000041,%eax 0000000000000009 popq %rbp 000000000000000a ret 000000000000000b nopl 0x00(%rax,%rax) _main: 0000000000000010 pushq %rbp 0000000000000011 movq %rsp,%rbp 0000000000000014 subq $0x10,%rsp 0000000000000018 movl $0x00000000,0xfc(%rbp) 000000000000001f callq 0x00000024 0000000000000024 addq $0x10,%rsp 0000000000000028 popq %rbp 0000000000000029 ret $ llvm-rtdyld t.o -debug-only=dyld ; echo $? Function sym: '_bar' @ 0 Function sym: '_main' @ 16 Extracting function: _bar from [0, 15] allocated to 0x100153000 Extracting function: _main from [16, 41] allocated to 0x100154000 Relocation at '_main' + 16 from '_bar(Word1: 0x2d000000) Resolving relocation at '_main' + 16 (0x100154010) from '_bar (0x100153000)(pcrel, type: 2, Size: 4). loaded '_main' at: 0x100154000 65 $ llvm-svn: 129388
2011-04-12 23:20:41 +02:00
}
void RuntimeDyld::mapSectionAddress(const void *LocalAddress,
uint64_t TargetAddress) {
Dyld->mapSectionAddress(LocalAddress, TargetAddress);
}
2011-03-22 19:22:27 +01:00
StringRef RuntimeDyld::getErrorString() {
return Dyld->getErrorString();
}
StringRef RuntimeDyld::getEHFrameSection() {
return Dyld->getEHFrameSection();
}
} // end namespace llvm