2012-01-17 07:50:58 +08:00
|
|
|
//===-- RuntimeDyld.cpp - Run-time dynamic linker for MC-JIT ----*- C++ -*-===//
|
2011-03-22 06:15:52 +08:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
2014-11-26 23:27:39 +08:00
|
|
|
#include "JITRegistrar.h"
|
|
|
|
#include "ObjectImageCommon.h"
|
[MCJIT] Refactor and add stub inspection to the RuntimeDyldChecker framework.
This patch introduces a 'stub_addr' builtin that can be used to find the address
of the stub for a given (<file>, <section>, <symbol>) tuple. This address can be
used both to verify the contents of stubs (by loading from the returned address)
and to verify references to stubs (by comparing against the returned address).
Example (1) - Verifying stub contents:
Load 8 bytes (assuming a 64-bit target) from the stub for 'x' in the __text
section of f.o, and compare that value against the addres of 'x'.
# rtdyld-check: *{8}(stub_addr(f.o, __text, x) = x
Example (2) - Verifying references to stubs:
Decode the immediate of the instruction at label 'l', and verify that it's
equal to the offset from the next instruction's PC to the stub for 'y' in the
__text section of f.o (i.e. it's the correct PC-rel difference).
# rtdyld-check: decode_operand(l, 4) = stub_addr(f.o, __text, y) - next_pc(l)
l:
movq y@GOTPCREL(%rip), %rax
Since stub inspection requires cooperation with RuntimeDyldImpl this patch
pimpl-ifies RuntimeDyldChecker. Its implementation is moved in to a new class,
RuntimeDyldCheckerImpl, that has access to the definition of RuntimeDyldImpl.
llvm-svn: 213698
2014-07-23 06:47:39 +08:00
|
|
|
#include "RuntimeDyldCheckerImpl.h"
|
2012-01-22 15:05:02 +08:00
|
|
|
#include "RuntimeDyldELF.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "RuntimeDyldImpl.h"
|
2012-01-22 15:05:02 +08:00
|
|
|
#include "RuntimeDyldMachO.h"
|
2014-01-07 19:48:04 +08:00
|
|
|
#include "llvm/Object/ELF.h"
|
2012-10-29 18:47:04 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2013-10-22 01:42:06 +08:00
|
|
|
#include "llvm/Support/MutexGuard.h"
|
2012-01-22 15:05:02 +08:00
|
|
|
|
2011-03-22 06:15:52 +08:00
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::object;
|
|
|
|
|
2014-04-22 11:04:17 +08:00
|
|
|
#define DEBUG_TYPE "dyld"
|
|
|
|
|
2011-04-06 07:54:31 +08:00
|
|
|
// Empty out-of-line virtual destructor as the key function.
|
2011-07-13 15:57:58 +08:00
|
|
|
RuntimeDyldImpl::~RuntimeDyldImpl() {}
|
2011-04-06 07:54:31 +08:00
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
// Pin the JITRegistrar's and ObjectImage*'s vtables to this file.
|
|
|
|
void JITRegistrar::anchor() {}
|
|
|
|
void ObjectImage::anchor() {}
|
|
|
|
void ObjectImageCommon::anchor() {}
|
2013-11-19 08:57:56 +08:00
|
|
|
|
2011-03-22 06:15:52 +08:00
|
|
|
namespace llvm {
|
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
void RuntimeDyldImpl::registerEHFrames() {}
|
2013-05-06 04:43:10 +08:00
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
void RuntimeDyldImpl::deregisterEHFrames() {}
|
2013-10-16 08:14:21 +08:00
|
|
|
|
2014-08-26 22:22:05 +08:00
|
|
|
#ifndef NDEBUG
|
2014-08-26 06:19:14 +08:00
|
|
|
static void dumpSectionMemory(const SectionEntry &S, StringRef State) {
|
|
|
|
dbgs() << "----- Contents of section " << S.Name << " " << State << " -----";
|
|
|
|
|
2014-10-02 05:57:47 +08:00
|
|
|
if (S.Address == nullptr) {
|
|
|
|
dbgs() << "\n <section not emitted>\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-08-26 06:19:14 +08:00
|
|
|
const unsigned ColsPerRow = 16;
|
2014-08-26 02:37:38 +08:00
|
|
|
|
|
|
|
uint8_t *DataAddr = S.Address;
|
|
|
|
uint64_t LoadAddr = S.LoadAddress;
|
|
|
|
|
2014-09-19 00:43:24 +08:00
|
|
|
unsigned StartPadding = LoadAddr & (ColsPerRow - 1);
|
2014-08-26 02:37:38 +08:00
|
|
|
unsigned BytesRemaining = S.Size;
|
|
|
|
|
|
|
|
if (StartPadding) {
|
2014-09-24 03:20:57 +08:00
|
|
|
dbgs() << "\n" << format("0x%016" PRIx64, LoadAddr & ~(ColsPerRow - 1)) << ":";
|
2014-08-26 02:37:38 +08:00
|
|
|
while (StartPadding--)
|
|
|
|
dbgs() << " ";
|
|
|
|
}
|
|
|
|
|
|
|
|
while (BytesRemaining > 0) {
|
2014-08-26 06:19:14 +08:00
|
|
|
if ((LoadAddr & (ColsPerRow - 1)) == 0)
|
2014-08-28 12:25:17 +08:00
|
|
|
dbgs() << "\n" << format("0x%016" PRIx64, LoadAddr) << ":";
|
2014-08-26 02:37:38 +08:00
|
|
|
|
|
|
|
dbgs() << " " << format("%02x", *DataAddr);
|
|
|
|
|
|
|
|
++DataAddr;
|
|
|
|
++LoadAddr;
|
|
|
|
--BytesRemaining;
|
|
|
|
}
|
|
|
|
|
|
|
|
dbgs() << "\n";
|
|
|
|
}
|
2014-08-26 22:22:05 +08:00
|
|
|
#endif
|
2014-08-26 02:37:38 +08:00
|
|
|
|
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-13 05:20:41 +08:00
|
|
|
// Resolve the relocations for all symbols we currently know about.
|
|
|
|
void RuntimeDyldImpl::resolveRelocations() {
|
2013-10-22 01:42:06 +08:00
|
|
|
MutexGuard locked(lock);
|
|
|
|
|
2012-04-13 04:13:57 +08:00
|
|
|
// First, resolve relocations associated with external symbols.
|
2012-04-30 20:15:58 +08:00
|
|
|
resolveExternalSymbols();
|
2012-03-31 00:45:19 +08:00
|
|
|
|
2012-01-17 06:26:39 +08:00
|
|
|
// 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) {
|
2013-08-20 03:38:06 +08:00
|
|
|
// 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.
|
2012-11-06 04:57:16 +08:00
|
|
|
uint64_t Addr = Sections[i].LoadAddress;
|
2014-04-22 03:23:59 +08:00
|
|
|
DEBUG(dbgs() << "Resolving relocations Section #" << i << "\t"
|
2014-08-26 02:37:38 +08:00
|
|
|
<< format("0x%x", Addr) << "\n");
|
2014-08-26 06:19:14 +08:00
|
|
|
DEBUG(dumpSectionMemory(Sections[i], "before relocations"));
|
2012-11-06 04:57:16 +08:00
|
|
|
resolveRelocationList(Relocations[i], Addr);
|
2014-08-26 06:19:14 +08:00
|
|
|
DEBUG(dumpSectionMemory(Sections[i], "after relocations"));
|
2013-10-01 09:47:35 +08:00
|
|
|
Relocations.erase(i);
|
2012-01-17 06:26:39 +08:00
|
|
|
}
|
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-13 05:20:41 +08:00
|
|
|
}
|
|
|
|
|
2012-09-14 05:50:06 +08:00
|
|
|
void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress,
|
2012-01-17 07:50:55 +08:00
|
|
|
uint64_t TargetAddress) {
|
2013-10-22 01:42:06 +08:00
|
|
|
MutexGuard locked(lock);
|
2012-03-31 00:45:19 +08:00
|
|
|
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!");
|
|
|
|
}
|
|
|
|
|
2014-06-13 10:24:39 +08:00
|
|
|
static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) {
|
2014-04-21 21:45:32 +08:00
|
|
|
uint64_t Address;
|
2014-06-13 10:24:39 +08:00
|
|
|
if (std::error_code EC = Sym.getAddress(Address))
|
2014-04-21 21:45:32 +08:00
|
|
|
return EC;
|
|
|
|
|
|
|
|
if (Address == UnknownAddressOrSize) {
|
|
|
|
Result = UnknownAddressOrSize;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectFile *Obj = Sym.getObject();
|
|
|
|
section_iterator SecI(Obj->section_begin());
|
2014-06-13 10:24:39 +08:00
|
|
|
if (std::error_code EC = Sym.getSection(SecI))
|
2014-04-21 21:45:32 +08:00
|
|
|
return EC;
|
|
|
|
|
2014-10-08 23:12:20 +08:00
|
|
|
if (SecI == Obj->section_end()) {
|
|
|
|
Result = UnknownAddressOrSize;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
2014-04-21 21:45:32 +08:00
|
|
|
|
2014-10-08 23:28:58 +08:00
|
|
|
uint64_t SectionAddress = SecI->getAddress();
|
2014-04-21 21:45:32 +08:00
|
|
|
Result = Address - SectionAddress;
|
|
|
|
return object_error::success;
|
|
|
|
}
|
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
std::unique_ptr<ObjectImage>
|
|
|
|
RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> Obj) {
|
2013-10-22 01:42:06 +08:00
|
|
|
MutexGuard locked(lock);
|
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
if (!Obj)
|
|
|
|
return nullptr;
|
2012-03-31 00:45:19 +08:00
|
|
|
|
2013-10-16 04:44:55 +08:00
|
|
|
// Save information about our target
|
2014-11-26 23:27:39 +08:00
|
|
|
Arch = (Triple::ArchType)Obj->getArch();
|
|
|
|
IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian();
|
2014-03-22 04:28:42 +08:00
|
|
|
|
2014-02-13 05:30:07 +08:00
|
|
|
// 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;
|
2014-11-26 23:27:39 +08:00
|
|
|
computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW);
|
2014-02-13 05:30:07 +08:00
|
|
|
MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW);
|
|
|
|
}
|
2014-03-22 04:28:42 +08:00
|
|
|
|
2012-05-01 14:58:59 +08:00
|
|
|
// Symbols found in this object
|
|
|
|
StringMap<SymbolLoc> LocalSymbols;
|
|
|
|
// Used sections from the object file
|
|
|
|
ObjSectionToIDMap LocalSections;
|
|
|
|
|
2012-10-29 18:47:04 +08:00
|
|
|
// Common symbols requiring allocation, with their sizes and alignments
|
2012-05-01 14:58:59 +08:00
|
|
|
CommonSymbolMap CommonSymbols;
|
2012-10-29 18:47:04 +08:00
|
|
|
// Maximum required total memory to allocate all common symbols
|
2012-05-01 14:58:59 +08:00
|
|
|
uint64_t CommonSize = 0;
|
2012-03-31 00:45:19 +08:00
|
|
|
|
|
|
|
// Parse symbols
|
|
|
|
DEBUG(dbgs() << "Parse symbols:\n");
|
2014-11-26 23:27:39 +08:00
|
|
|
for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E;
|
2014-04-22 03:23:59 +08:00
|
|
|
++I) {
|
2012-03-31 00:45:19 +08:00
|
|
|
object::SymbolRef::Type SymType;
|
|
|
|
StringRef Name;
|
2014-04-22 03:23:59 +08:00
|
|
|
Check(I->getType(SymType));
|
|
|
|
Check(I->getName(Name));
|
2012-03-31 00:45:19 +08:00
|
|
|
|
2014-04-22 03:23:59 +08:00
|
|
|
uint32_t Flags = I->getFlags();
|
2012-04-13 04:13:57 +08:00
|
|
|
|
2014-02-13 05:30:07 +08:00
|
|
|
bool IsCommon = Flags & SymbolRef::SF_Common;
|
|
|
|
if (IsCommon) {
|
2012-04-13 04:13:57 +08:00
|
|
|
// Add the common symbols to a list. We'll allocate them all below.
|
2014-05-13 05:39:59 +08:00
|
|
|
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);
|
|
|
|
}
|
2012-04-13 04:13:57 +08:00
|
|
|
} else {
|
|
|
|
if (SymType == object::SymbolRef::ST_Function ||
|
2012-08-18 05:28:04 +08:00
|
|
|
SymType == object::SymbolRef::ST_Data ||
|
|
|
|
SymType == object::SymbolRef::ST_Unknown) {
|
2014-04-21 21:45:32 +08:00
|
|
|
uint64_t SectOffset;
|
2012-04-29 20:40:47 +08:00
|
|
|
StringRef SectionData;
|
2014-11-26 23:27:39 +08:00
|
|
|
section_iterator SI = Obj->end_sections();
|
2014-04-22 03:23:59 +08:00
|
|
|
Check(getOffset(*I, SectOffset));
|
|
|
|
Check(I->getSection(SI));
|
2014-11-26 23:27:39 +08:00
|
|
|
if (SI == Obj->end_sections())
|
2014-03-22 04:28:42 +08:00
|
|
|
continue;
|
2014-02-13 05:30:07 +08:00
|
|
|
Check(SI->getContents(SectionData));
|
2014-10-08 23:28:58 +08:00
|
|
|
bool IsCode = SI->isText();
|
2014-03-22 04:28:42 +08:00
|
|
|
unsigned SectionID =
|
2014-11-26 23:27:39 +08:00
|
|
|
findOrEmitSection(*Obj, *SI, IsCode, LocalSections);
|
2012-04-13 04:13:57 +08:00
|
|
|
LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset);
|
2014-04-21 21:45:32 +08:00
|
|
|
DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset)
|
|
|
|
<< " flags: " << Flags << " SID: " << SectionID);
|
2014-10-21 08:24:02 +08:00
|
|
|
GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset);
|
2012-04-13 04:13:57 +08:00
|
|
|
}
|
2012-03-31 00:45:19 +08:00
|
|
|
}
|
|
|
|
DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n");
|
|
|
|
}
|
|
|
|
|
2012-04-13 04:13:57 +08:00
|
|
|
// Allocate common symbols
|
|
|
|
if (CommonSize != 0)
|
2014-11-26 23:27:39 +08:00
|
|
|
emitCommonSymbols(*Obj, CommonSymbols, CommonSize, GlobalSymbolTable);
|
2012-04-13 04:13:57 +08:00
|
|
|
|
2012-04-29 20:40:47 +08:00
|
|
|
// Parse and process relocations
|
2012-03-31 00:45:19 +08:00
|
|
|
DEBUG(dbgs() << "Parse relocations:\n");
|
2014-11-26 23:27:39 +08:00
|
|
|
for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
|
2014-04-22 03:23:59 +08:00
|
|
|
SI != SE; ++SI) {
|
2012-03-31 00:45:19 +08:00
|
|
|
unsigned SectionID = 0;
|
|
|
|
StubMap Stubs;
|
2014-04-22 03:23:59 +08:00
|
|
|
section_iterator RelocatedSection = SI->getRelocatedSection();
|
2012-03-31 00:45:19 +08:00
|
|
|
|
2014-04-22 03:23:59 +08:00
|
|
|
relocation_iterator I = SI->relocation_begin();
|
|
|
|
relocation_iterator E = SI->relocation_end();
|
2014-04-04 06:42:22 +08:00
|
|
|
|
|
|
|
if (I == E && !ProcessAllSections)
|
2014-03-21 15:26:41 +08:00
|
|
|
continue;
|
|
|
|
|
2014-10-08 23:28:58 +08:00
|
|
|
bool IsCode = RelocatedSection->isText();
|
2014-03-21 15:26:41 +08:00
|
|
|
SectionID =
|
2014-11-26 23:27:39 +08:00
|
|
|
findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections);
|
2014-03-21 15:26:41 +08:00
|
|
|
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
|
|
|
|
|
2014-04-04 06:42:22 +08:00
|
|
|
for (; I != E;)
|
2014-11-26 23:27:39 +08:00
|
|
|
I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols,
|
2014-03-21 15:26:41 +08:00
|
|
|
Stubs);
|
[MCJIT] Refactor and add stub inspection to the RuntimeDyldChecker framework.
This patch introduces a 'stub_addr' builtin that can be used to find the address
of the stub for a given (<file>, <section>, <symbol>) tuple. This address can be
used both to verify the contents of stubs (by loading from the returned address)
and to verify references to stubs (by comparing against the returned address).
Example (1) - Verifying stub contents:
Load 8 bytes (assuming a 64-bit target) from the stub for 'x' in the __text
section of f.o, and compare that value against the addres of 'x'.
# rtdyld-check: *{8}(stub_addr(f.o, __text, x) = x
Example (2) - Verifying references to stubs:
Decode the immediate of the instruction at label 'l', and verify that it's
equal to the offset from the next instruction's PC to the stub for 'y' in the
__text section of f.o (i.e. it's the correct PC-rel difference).
# rtdyld-check: decode_operand(l, 4) = stub_addr(f.o, __text, y) - next_pc(l)
l:
movq y@GOTPCREL(%rip), %rax
Since stub inspection requires cooperation with RuntimeDyldImpl this patch
pimpl-ifies RuntimeDyldChecker. Its implementation is moved in to a new class,
RuntimeDyldCheckerImpl, that has access to the definition of RuntimeDyldImpl.
llvm-svn: 213698
2014-07-23 06:47:39 +08:00
|
|
|
|
|
|
|
// If there is an attached checker, notify it about the stubs for this
|
|
|
|
// section so that they can be verified.
|
|
|
|
if (Checker)
|
2014-11-26 23:27:39 +08:00
|
|
|
Checker->registerStubMap(Obj->getImageName(), SectionID, Stubs);
|
2012-03-31 00:45:19 +08:00
|
|
|
}
|
2012-04-17 06:12:58 +08:00
|
|
|
|
2013-08-20 07:27:43 +08:00
|
|
|
// Give the subclasses a chance to tie-up any loose ends.
|
2014-11-26 23:27:39 +08:00
|
|
|
finalizeLoad(*Obj, LocalSections);
|
2013-08-20 07:27:43 +08:00
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
return Obj;
|
2014-02-13 05:30:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// A helper method for computeTotalAllocSize.
|
2014-03-22 04:28:42 +08:00
|
|
|
// Computes the memory size required to allocate sections with the given sizes,
|
2014-02-13 05:30:07 +08:00
|
|
|
// assuming that all sections are allocated with the given alignment
|
2014-03-22 04:28:42 +08:00
|
|
|
static uint64_t
|
|
|
|
computeAllocationSizeForSections(std::vector<uint64_t> &SectionSizes,
|
|
|
|
uint64_t Alignment) {
|
2014-02-13 05:30:07 +08:00
|
|
|
uint64_t TotalSize = 0;
|
2014-04-22 03:23:59 +08:00
|
|
|
for (size_t Idx = 0, Cnt = SectionSizes.size(); Idx < Cnt; Idx++) {
|
|
|
|
uint64_t AlignedSize =
|
|
|
|
(SectionSizes[Idx] + Alignment - 1) / Alignment * Alignment;
|
2014-02-13 05:30:07 +08:00
|
|
|
TotalSize += AlignedSize;
|
|
|
|
}
|
|
|
|
return TotalSize;
|
|
|
|
}
|
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
// Compute an upper bound of the memory size that is required to load all
|
|
|
|
// sections
|
2014-11-26 23:27:39 +08:00
|
|
|
void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj,
|
2014-03-22 04:28:42 +08:00
|
|
|
uint64_t &CodeSize,
|
|
|
|
uint64_t &DataSizeRO,
|
|
|
|
uint64_t &DataSizeRW) {
|
2014-02-13 05:30:07 +08:00
|
|
|
// Compute the size of all sections required for execution
|
|
|
|
std::vector<uint64_t> CodeSectionSizes;
|
|
|
|
std::vector<uint64_t> ROSectionSizes;
|
|
|
|
std::vector<uint64_t> RWSectionSizes;
|
2014-03-22 04:28:42 +08:00
|
|
|
uint64_t MaxAlignment = sizeof(void *);
|
2014-02-13 05:30:07 +08:00
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
// Collect sizes of all sections to be loaded;
|
2014-02-13 05:30:07 +08:00
|
|
|
// also determine the max alignment of all sections
|
2014-11-26 23:27:39 +08:00
|
|
|
for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections();
|
2014-04-22 03:23:59 +08:00
|
|
|
SI != SE; ++SI) {
|
|
|
|
const SectionRef &Section = *SI;
|
|
|
|
|
2014-10-08 23:28:58 +08:00
|
|
|
bool IsRequired = Section.isRequiredForExecution();
|
2014-03-22 04:28:42 +08:00
|
|
|
|
2014-02-13 05:30:07 +08:00
|
|
|
// Consider only the sections that are required to be loaded for execution
|
|
|
|
if (IsRequired) {
|
|
|
|
StringRef Name;
|
2014-10-08 23:28:58 +08:00
|
|
|
uint64_t DataSize = Section.getSize();
|
|
|
|
uint64_t Alignment64 = Section.getAlignment();
|
|
|
|
bool IsCode = Section.isText();
|
|
|
|
bool IsReadOnly = Section.isReadOnlyData();
|
2014-02-13 05:30:07 +08:00
|
|
|
Check(Section.getName(Name));
|
2014-03-22 04:28:42 +08:00
|
|
|
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
|
|
|
|
|
2014-02-13 05:30:07 +08:00
|
|
|
uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section);
|
|
|
|
uint64_t SectionSize = DataSize + StubBufSize;
|
2014-03-22 04:28:42 +08:00
|
|
|
|
|
|
|
// The .eh_frame section (at least on Linux) needs an extra four bytes
|
|
|
|
// padded
|
2014-02-13 05:30:07 +08:00
|
|
|
// with zeroes added at the end. For MachO objects, this section has a
|
2014-03-22 04:28:42 +08:00
|
|
|
// slightly different name, so this won't have any effect for MachO
|
|
|
|
// objects.
|
2014-02-13 05:30:07 +08:00
|
|
|
if (Name == ".eh_frame")
|
|
|
|
SectionSize += 4;
|
2014-03-22 04:28:42 +08:00
|
|
|
|
2014-02-13 05:30:07 +08:00
|
|
|
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;
|
|
|
|
}
|
2014-03-22 04:28:42 +08:00
|
|
|
}
|
2014-02-13 05:30:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the size of all common symbols
|
|
|
|
uint64_t CommonSize = 0;
|
2014-11-26 23:27:39 +08:00
|
|
|
for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;
|
2014-03-22 04:28:42 +08:00
|
|
|
++I) {
|
2014-02-13 05:30:07 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
// Compute the required allocation space for each different type of sections
|
|
|
|
// (code, read-only data, read-write data) assuming that all sections are
|
2014-02-13 05:30:07 +08:00
|
|
|
// allocated with the max alignment. Note that we cannot compute with the
|
2014-03-22 04:28:42 +08:00
|
|
|
// individual alignments of the sections, because then the required size
|
2014-02-13 05:30:07 +08:00
|
|
|
// depends on the order, in which the sections are allocated.
|
|
|
|
CodeSize = computeAllocationSizeForSections(CodeSectionSizes, MaxAlignment);
|
|
|
|
DataSizeRO = computeAllocationSizeForSections(ROSectionSizes, MaxAlignment);
|
2014-03-22 04:28:42 +08:00
|
|
|
DataSizeRW = computeAllocationSizeForSections(RWSectionSizes, MaxAlignment);
|
2014-02-13 05:30:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// compute stub buffer size for the given section
|
2014-11-26 23:27:39 +08:00
|
|
|
unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj,
|
2014-02-13 05:30:07 +08:00
|
|
|
const SectionRef &Section) {
|
|
|
|
unsigned StubSize = getMaxStubSize();
|
|
|
|
if (StubSize == 0) {
|
2014-03-22 04:28:42 +08:00
|
|
|
return 0;
|
2014-02-13 05:30:07 +08:00
|
|
|
}
|
|
|
|
// 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;
|
2014-11-26 23:27:39 +08:00
|
|
|
for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections();
|
2014-04-22 03:23:59 +08:00
|
|
|
SI != SE; ++SI) {
|
|
|
|
section_iterator RelSecI = SI->getRelocatedSection();
|
2014-02-13 05:30:07 +08:00
|
|
|
if (!(RelSecI == Section))
|
|
|
|
continue;
|
|
|
|
|
2014-04-22 03:23:59 +08:00
|
|
|
for (const RelocationRef &Reloc : SI->relocations()) {
|
2014-03-14 22:22:49 +08:00
|
|
|
(void)Reloc;
|
2014-02-13 05:30:07 +08:00
|
|
|
StubBufSize += StubSize;
|
|
|
|
}
|
|
|
|
}
|
2014-03-14 22:22:49 +08:00
|
|
|
|
2014-02-13 05:30:07 +08:00
|
|
|
// Get section data size and alignment
|
2014-10-08 23:28:58 +08:00
|
|
|
uint64_t DataSize = Section.getSize();
|
|
|
|
uint64_t Alignment64 = Section.getAlignment();
|
2014-02-13 05:30:07 +08:00
|
|
|
|
|
|
|
// Add stubbuf size alignment
|
|
|
|
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
|
|
|
|
unsigned StubAlignment = getStubAlignment();
|
|
|
|
unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment);
|
|
|
|
if (StubAlignment > EndAlignment)
|
2014-03-22 04:28:42 +08:00
|
|
|
StubBufSize += StubAlignment - EndAlignment;
|
2014-02-13 05:30:07 +08:00
|
|
|
return StubBufSize;
|
2012-01-17 07:50:55 +08:00
|
|
|
}
|
|
|
|
|
2014-08-30 07:17:47 +08:00
|
|
|
uint64_t RuntimeDyldImpl::readBytesUnaligned(uint8_t *Src,
|
|
|
|
unsigned Size) const {
|
|
|
|
uint64_t Result = 0;
|
2014-09-07 10:05:26 +08:00
|
|
|
if (IsTargetLittleEndian) {
|
|
|
|
Src += Size - 1;
|
|
|
|
while (Size--)
|
|
|
|
Result = (Result << 8) | *Src--;
|
|
|
|
} else
|
|
|
|
while (Size--)
|
|
|
|
Result = (Result << 8) | *Src++;
|
2014-08-30 07:17:47 +08:00
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst,
|
|
|
|
unsigned Size) const {
|
2014-09-07 10:05:26 +08:00
|
|
|
if (IsTargetLittleEndian) {
|
|
|
|
while (Size--) {
|
|
|
|
*Dst++ = Value & 0xFF;
|
|
|
|
Value >>= 8;
|
|
|
|
}
|
2014-08-30 07:17:47 +08:00
|
|
|
} else {
|
2014-09-07 10:05:26 +08:00
|
|
|
Dst += Size - 1;
|
|
|
|
while (Size--) {
|
|
|
|
*Dst-- = Value & 0xFF;
|
|
|
|
Value >>= 8;
|
|
|
|
}
|
2014-08-30 07:17:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
|
2012-05-01 18:41:12 +08:00
|
|
|
const CommonSymbolMap &CommonSymbols,
|
|
|
|
uint64_t TotalSize,
|
|
|
|
SymbolTableMap &SymbolTable) {
|
2012-04-13 04:13:57 +08:00
|
|
|
// Allocate memory for the section
|
|
|
|
unsigned SectionID = Sections.size();
|
2014-03-22 04:28:42 +08:00
|
|
|
uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void *),
|
|
|
|
SectionID, StringRef(), false);
|
2012-04-13 04:13:57 +08:00
|
|
|
if (!Addr)
|
|
|
|
report_fatal_error("Unable to allocate memory for common symbols!");
|
|
|
|
uint64_t Offset = 0;
|
2014-08-26 02:37:38 +08:00
|
|
|
Sections.push_back(SectionEntry("<common symbols>", Addr, TotalSize, 0));
|
2012-04-13 04:13:57 +08:00
|
|
|
memset(Addr, 0, TotalSize);
|
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID << " new addr: "
|
|
|
|
<< format("%p", Addr) << " DataSize: " << TotalSize << "\n");
|
2012-04-13 04:13:57 +08:00
|
|
|
|
|
|
|
// Assign the address of each symbol
|
2014-04-22 03:23:59 +08:00
|
|
|
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;
|
2012-04-13 04:13:57 +08:00
|
|
|
StringRef Name;
|
2014-04-22 03:23:59 +08:00
|
|
|
it->first.getName(Name);
|
2012-10-29 18:47:04 +08:00
|
|
|
if (Align) {
|
|
|
|
// This symbol has an alignment requirement.
|
|
|
|
uint64_t AlignOffset = OffsetToAlignment((uint64_t)Addr, Align);
|
|
|
|
Addr += AlignOffset;
|
|
|
|
Offset += AlignOffset;
|
2014-03-22 04:28:42 +08:00
|
|
|
DEBUG(dbgs() << "Allocating common symbol " << Name << " address "
|
|
|
|
<< format("%p\n", Addr));
|
2012-10-29 18:47:04 +08:00
|
|
|
}
|
2014-11-26 23:27:39 +08:00
|
|
|
Obj.updateSymbolAddress(it->first, (uint64_t)Addr);
|
2012-05-01 18:41:12 +08:00
|
|
|
SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset);
|
2012-04-13 04:13:57 +08:00
|
|
|
Offset += Size;
|
|
|
|
Addr += Size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
|
2014-03-22 04:28:42 +08:00
|
|
|
const SectionRef &Section, bool IsCode) {
|
2012-03-31 00:45:19 +08:00
|
|
|
|
|
|
|
StringRef data;
|
|
|
|
Check(Section.getContents(data));
|
2014-10-08 23:28:58 +08:00
|
|
|
uint64_t Alignment64 = Section.getAlignment();
|
2012-03-31 00:45:19 +08:00
|
|
|
|
|
|
|
unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL;
|
2013-10-16 08:32:24 +08:00
|
|
|
unsigned PaddingSize = 0;
|
2014-02-13 05:30:07 +08:00
|
|
|
unsigned StubBufSize = 0;
|
2012-10-25 21:13:48 +08:00
|
|
|
StringRef Name;
|
2014-10-08 23:28:58 +08:00
|
|
|
bool IsRequired = Section.isRequiredForExecution();
|
|
|
|
bool IsVirtual = Section.isVirtual();
|
|
|
|
bool IsZeroInit = Section.isZeroInit();
|
|
|
|
bool IsReadOnly = Section.isReadOnlyData();
|
|
|
|
uint64_t DataSize = Section.getSize();
|
2012-10-25 21:13:48 +08:00
|
|
|
Check(Section.getName(Name));
|
2014-03-22 04:28:42 +08:00
|
|
|
|
|
|
|
StubBufSize = computeSectionStubBufSize(Obj, Section);
|
2012-04-13 04:13:57 +08:00
|
|
|
|
2013-10-16 08:32:24 +08:00
|
|
|
// 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;
|
|
|
|
|
2014-02-11 13:28:24 +08:00
|
|
|
uintptr_t Allocate;
|
2012-03-31 00:45:19 +08:00
|
|
|
unsigned SectionID = Sections.size();
|
2012-04-13 04:13:57 +08:00
|
|
|
uint8_t *Addr;
|
2014-04-24 14:44:33 +08:00
|
|
|
const char *pData = nullptr;
|
2012-04-13 04:13:57 +08:00
|
|
|
|
|
|
|
// Some sections, such as debug info, don't need to be loaded for execution.
|
|
|
|
// Leave those where they are.
|
|
|
|
if (IsRequired) {
|
2013-10-16 08:32:24 +08:00
|
|
|
Allocate = DataSize + PaddingSize + StubBufSize;
|
2014-03-22 04:28:42 +08:00
|
|
|
Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID,
|
|
|
|
Name)
|
|
|
|
: MemMgr->allocateDataSection(Allocate, Alignment, SectionID,
|
|
|
|
Name, IsReadOnly);
|
2012-04-13 04:13:57 +08:00
|
|
|
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);
|
|
|
|
|
2013-10-16 08:32:24 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name
|
2012-04-13 04:13:57 +08:00
|
|
|
<< " obj addr: " << format("%p", pData)
|
|
|
|
<< " new addr: " << format("%p", Addr)
|
2014-03-22 04:28:42 +08:00
|
|
|
<< " DataSize: " << DataSize << " StubBufSize: " << StubBufSize
|
|
|
|
<< " Allocate: " << Allocate << "\n");
|
2014-11-26 23:27:39 +08:00
|
|
|
Obj.updateSectionAddress(Section, (uint64_t)Addr);
|
2014-03-22 04:28:42 +08:00
|
|
|
} else {
|
2012-04-13 04:13:57 +08:00
|
|
|
// Even if we didn't load the section, we need to record an entry for it
|
2012-04-29 20:40:47 +08:00
|
|
|
// to handle later processing (and by 'handle' I mean don't do anything
|
|
|
|
// with these sections).
|
2012-04-13 04:13:57 +08:00
|
|
|
Allocate = 0;
|
2014-04-24 14:44:33 +08:00
|
|
|
Addr = nullptr;
|
2014-03-22 04:28:42 +08:00
|
|
|
DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name
|
|
|
|
<< " obj addr: " << format("%p", data.data()) << " new addr: 0"
|
|
|
|
<< " DataSize: " << DataSize << " StubBufSize: " << StubBufSize
|
|
|
|
<< " Allocate: " << Allocate << "\n");
|
2012-04-13 04:13:57 +08:00
|
|
|
}
|
|
|
|
|
2013-05-06 04:43:10 +08:00
|
|
|
Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData));
|
2014-09-03 13:01:46 +08:00
|
|
|
|
|
|
|
if (Checker)
|
2014-11-26 23:27:39 +08:00
|
|
|
Checker->registerSection(Obj.getImageName(), SectionID);
|
2014-09-03 13:01:46 +08:00
|
|
|
|
2012-03-31 00:45:19 +08:00
|
|
|
return SectionID;
|
|
|
|
}
|
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj,
|
2012-04-17 06:12:58 +08:00
|
|
|
const SectionRef &Section,
|
2012-03-31 00:45:19 +08:00
|
|
|
bool IsCode,
|
|
|
|
ObjSectionToIDMap &LocalSections) {
|
|
|
|
|
|
|
|
unsigned SectionID = 0;
|
|
|
|
ObjSectionToIDMap::iterator i = LocalSections.find(Section);
|
|
|
|
if (i != LocalSections.end())
|
|
|
|
SectionID = i->second;
|
|
|
|
else {
|
2012-04-17 06:12:58 +08:00
|
|
|
SectionID = emitSection(Obj, Section, IsCode);
|
2012-03-31 00:45:19 +08:00
|
|
|
LocalSections[Section] = SectionID;
|
|
|
|
}
|
|
|
|
return SectionID;
|
|
|
|
}
|
|
|
|
|
2012-05-01 18:41:12 +08:00
|
|
|
void RuntimeDyldImpl::addRelocationForSection(const RelocationEntry &RE,
|
|
|
|
unsigned SectionID) {
|
|
|
|
Relocations[SectionID].push_back(RE);
|
|
|
|
}
|
2012-03-31 00:45:19 +08:00
|
|
|
|
2012-05-01 18:41:12 +08:00
|
|
|
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.
|
2014-03-22 04:28:42 +08:00
|
|
|
SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(SymbolName);
|
2012-05-01 18:41:12 +08:00
|
|
|
if (Loc == GlobalSymbolTable.end()) {
|
|
|
|
ExternalSymbolRelocations[SymbolName].push_back(RE);
|
2012-04-30 20:15:58 +08:00
|
|
|
} else {
|
2012-05-01 18:41:12 +08:00
|
|
|
// 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);
|
2012-04-30 20:15:58 +08:00
|
|
|
}
|
2012-03-31 00:45:19 +08:00
|
|
|
}
|
|
|
|
|
2014-07-21 07:53:14 +08:00
|
|
|
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
|
|
|
|
unsigned AbiVariant) {
|
2014-07-23 20:32:47 +08:00
|
|
|
if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) {
|
2013-05-05 04:14:09 +08:00
|
|
|
// 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.
|
|
|
|
// Stub can use ip0 (== x16) to calculate address
|
2014-11-06 17:53:05 +08:00
|
|
|
writeBytesUnaligned(0xd2e00010, Addr, 4); // movz ip0, #:abs_g3:<addr>
|
|
|
|
writeBytesUnaligned(0xf2c00010, Addr+4, 4); // movk ip0, #:abs_g2_nc:<addr>
|
|
|
|
writeBytesUnaligned(0xf2a00010, Addr+8, 4); // movk ip0, #:abs_g1_nc:<addr>
|
|
|
|
writeBytesUnaligned(0xf2800010, Addr+12, 4); // movk ip0, #:abs_g0_nc:<addr>
|
|
|
|
writeBytesUnaligned(0xd61f0200, Addr+16, 4); // br ip0
|
2013-05-05 04:14:09 +08:00
|
|
|
|
|
|
|
return Addr;
|
2014-03-28 22:35:30 +08:00
|
|
|
} else if (Arch == Triple::arm || Arch == Triple::armeb) {
|
2012-08-18 05:28:04 +08:00
|
|
|
// TODO: There is only ARM far stub now. We should add the Thumb stub,
|
|
|
|
// and stubs for branches Thumb - ARM and ARM - Thumb.
|
2014-11-06 17:53:05 +08:00
|
|
|
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,<label>
|
|
|
|
return Addr + 4;
|
2012-12-04 08:08:14 +08:00
|
|
|
} else if (Arch == Triple::mipsel || Arch == Triple::mips) {
|
2012-08-18 05:28:04 +08:00
|
|
|
// 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;
|
|
|
|
|
2014-11-06 17:53:05 +08:00
|
|
|
writeBytesUnaligned(LuiT9Instr, Addr, 4);
|
|
|
|
writeBytesUnaligned(AdduiT9Instr, Addr+4, 4);
|
|
|
|
writeBytesUnaligned(JrT9Instr, Addr+8, 4);
|
|
|
|
writeBytesUnaligned(NopInstr, Addr+12, 4);
|
2012-10-25 21:13:48 +08:00
|
|
|
return Addr;
|
2013-07-26 09:35:43 +08:00
|
|
|
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
|
2014-07-21 07:53:14 +08:00
|
|
|
// 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.
|
2012-10-25 21:13:48 +08:00
|
|
|
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)
|
2014-07-21 07:53:14 +08:00
|
|
|
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
|
|
|
|
}
|
2013-05-03 22:15:35 +08:00
|
|
|
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
|
2012-03-31 00:45:19 +08:00
|
|
|
return Addr;
|
2013-08-20 07:27:43 +08:00
|
|
|
} 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
|
2014-05-13 05:39:59 +08:00
|
|
|
} else if (Arch == Triple::x86) {
|
|
|
|
*Addr = 0xE9; // 32-bit pc-relative jump.
|
2012-08-18 05:28:04 +08:00
|
|
|
}
|
|
|
|
return Addr;
|
2012-03-31 00:45:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
2012-11-06 04:57:16 +08:00
|
|
|
// 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().
|
2012-03-31 00:45:19 +08:00
|
|
|
//
|
|
|
|
// 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.
|
2014-09-04 12:19:54 +08:00
|
|
|
DEBUG(dbgs() << "Reassigning address for section "
|
|
|
|
<< SectionID << " (" << Sections[SectionID].Name << "): "
|
2014-09-24 03:20:57 +08:00
|
|
|
<< format("0x%016" PRIx64, Sections[SectionID].LoadAddress) << " -> "
|
|
|
|
<< format("0x%016" PRIx64, Addr) << "\n");
|
2012-03-31 00:45:19 +08:00
|
|
|
Sections[SectionID].LoadAddress = Addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
|
|
|
|
uint64_t Value) {
|
|
|
|
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
|
2013-04-30 01:24:34 +08:00
|
|
|
const RelocationEntry &RE = Relocs[i];
|
|
|
|
// Ignore relocations for sections that were not loaded
|
2014-04-24 14:44:33 +08:00
|
|
|
if (Sections[RE.SectionID].Address == nullptr)
|
2013-04-30 01:24:34 +08:00
|
|
|
continue;
|
|
|
|
resolveRelocation(RE, Value);
|
2012-03-31 00:45:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-30 20:15:58 +08:00
|
|
|
void RuntimeDyldImpl::resolveExternalSymbols() {
|
2014-03-22 04:28:42 +08:00
|
|
|
while (!ExternalSymbolRelocations.empty()) {
|
2013-10-01 09:47:35 +08:00
|
|
|
StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin();
|
|
|
|
|
2012-03-31 00:45:19 +08:00
|
|
|
StringRef Name = i->first();
|
2013-10-01 09:47:35 +08:00
|
|
|
if (Name.size() == 0) {
|
|
|
|
// This is an absolute symbol, use an address of zero.
|
2014-03-22 04:28:42 +08:00
|
|
|
DEBUG(dbgs() << "Resolving absolute relocations."
|
|
|
|
<< "\n");
|
2013-11-12 03:55:10 +08:00
|
|
|
RelocationList &Relocs = i->second;
|
2013-10-01 09:47:35 +08:00
|
|
|
resolveRelocationList(Relocs, 0);
|
|
|
|
} else {
|
|
|
|
uint64_t Addr = 0;
|
|
|
|
SymbolTableMap::const_iterator Loc = GlobalSymbolTable.find(Name);
|
|
|
|
if (Loc == GlobalSymbolTable.end()) {
|
2014-03-22 04:28:42 +08:00
|
|
|
// 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);
|
2013-02-21 02:24:34 +08:00
|
|
|
} else {
|
2013-10-01 09:47:35 +08:00
|
|
|
// We found the symbol in our global table. It was probably in a
|
|
|
|
// Module that we loaded previously.
|
2013-10-19 17:04:26 +08:00
|
|
|
SymbolLoc SymLoc = Loc->second;
|
2013-10-01 09:47:35 +08:00
|
|
|
Addr = getSectionLoadAddress(SymLoc.first) + SymLoc.second;
|
2013-02-21 02:09:21 +08:00
|
|
|
}
|
2013-10-01 09:47:35 +08:00
|
|
|
|
|
|
|
// FIXME: Implement error handling that doesn't kill the host program!
|
|
|
|
if (!Addr)
|
|
|
|
report_fatal_error("Program used external function '" + Name +
|
2014-03-22 04:28:42 +08:00
|
|
|
"' which could not be resolved!");
|
2013-10-01 09:47:35 +08:00
|
|
|
|
|
|
|
updateGOTEntries(Name, Addr);
|
2014-03-22 04:28:42 +08:00
|
|
|
DEBUG(dbgs() << "Resolving relocations Name: " << Name << "\t"
|
|
|
|
<< format("0x%lx", Addr) << "\n");
|
2013-11-12 03:55:10 +08:00
|
|
|
// 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;
|
2013-10-01 09:47:35 +08:00
|
|
|
resolveRelocationList(Relocs, Addr);
|
2012-03-31 00:45:19 +08:00
|
|
|
}
|
2013-10-01 09:47:35 +08:00
|
|
|
|
2013-11-12 03:55:10 +08:00
|
|
|
ExternalSymbolRelocations.erase(i);
|
2012-03-31 00:45:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-22 06:15:52 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RuntimeDyld class implementation
|
2011-07-13 15:57:58 +08:00
|
|
|
RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
|
2012-11-16 07:50:01 +08:00
|
|
|
// 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.
|
2014-04-24 14:44:33 +08:00
|
|
|
Dyld = nullptr;
|
2011-07-13 15:57:58 +08:00
|
|
|
MM = mm;
|
2014-03-21 05:06:46 +08:00
|
|
|
ProcessAllSections = false;
|
[MCJIT] Refactor and add stub inspection to the RuntimeDyldChecker framework.
This patch introduces a 'stub_addr' builtin that can be used to find the address
of the stub for a given (<file>, <section>, <symbol>) tuple. This address can be
used both to verify the contents of stubs (by loading from the returned address)
and to verify references to stubs (by comparing against the returned address).
Example (1) - Verifying stub contents:
Load 8 bytes (assuming a 64-bit target) from the stub for 'x' in the __text
section of f.o, and compare that value against the addres of 'x'.
# rtdyld-check: *{8}(stub_addr(f.o, __text, x) = x
Example (2) - Verifying references to stubs:
Decode the immediate of the instruction at label 'l', and verify that it's
equal to the offset from the next instruction's PC to the stub for 'y' in the
__text section of f.o (i.e. it's the correct PC-rel difference).
# rtdyld-check: decode_operand(l, 4) = stub_addr(f.o, __text, y) - next_pc(l)
l:
movq y@GOTPCREL(%rip), %rax
Since stub inspection requires cooperation with RuntimeDyldImpl this patch
pimpl-ifies RuntimeDyldChecker. Its implementation is moved in to a new class,
RuntimeDyldCheckerImpl, that has access to the definition of RuntimeDyldImpl.
llvm-svn: 213698
2014-07-23 06:47:39 +08:00
|
|
|
Checker = nullptr;
|
2011-03-22 06:15:52 +08:00
|
|
|
}
|
|
|
|
|
2014-09-05 02:37:29 +08:00
|
|
|
RuntimeDyld::~RuntimeDyld() {}
|
2011-03-22 06:15:52 +08:00
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
static std::unique_ptr<RuntimeDyldELF>
|
[MCJIT] Refactor and add stub inspection to the RuntimeDyldChecker framework.
This patch introduces a 'stub_addr' builtin that can be used to find the address
of the stub for a given (<file>, <section>, <symbol>) tuple. This address can be
used both to verify the contents of stubs (by loading from the returned address)
and to verify references to stubs (by comparing against the returned address).
Example (1) - Verifying stub contents:
Load 8 bytes (assuming a 64-bit target) from the stub for 'x' in the __text
section of f.o, and compare that value against the addres of 'x'.
# rtdyld-check: *{8}(stub_addr(f.o, __text, x) = x
Example (2) - Verifying references to stubs:
Decode the immediate of the instruction at label 'l', and verify that it's
equal to the offset from the next instruction's PC to the stub for 'y' in the
__text section of f.o (i.e. it's the correct PC-rel difference).
# rtdyld-check: decode_operand(l, 4) = stub_addr(f.o, __text, y) - next_pc(l)
l:
movq y@GOTPCREL(%rip), %rax
Since stub inspection requires cooperation with RuntimeDyldImpl this patch
pimpl-ifies RuntimeDyldChecker. Its implementation is moved in to a new class,
RuntimeDyldCheckerImpl, that has access to the definition of RuntimeDyldImpl.
llvm-svn: 213698
2014-07-23 06:47:39 +08:00
|
|
|
createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections,
|
|
|
|
RuntimeDyldCheckerImpl *Checker) {
|
2014-03-21 05:06:46 +08:00
|
|
|
std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM));
|
|
|
|
Dyld->setProcessAllSections(ProcessAllSections);
|
[MCJIT] Refactor and add stub inspection to the RuntimeDyldChecker framework.
This patch introduces a 'stub_addr' builtin that can be used to find the address
of the stub for a given (<file>, <section>, <symbol>) tuple. This address can be
used both to verify the contents of stubs (by loading from the returned address)
and to verify references to stubs (by comparing against the returned address).
Example (1) - Verifying stub contents:
Load 8 bytes (assuming a 64-bit target) from the stub for 'x' in the __text
section of f.o, and compare that value against the addres of 'x'.
# rtdyld-check: *{8}(stub_addr(f.o, __text, x) = x
Example (2) - Verifying references to stubs:
Decode the immediate of the instruction at label 'l', and verify that it's
equal to the offset from the next instruction's PC to the stub for 'y' in the
__text section of f.o (i.e. it's the correct PC-rel difference).
# rtdyld-check: decode_operand(l, 4) = stub_addr(f.o, __text, y) - next_pc(l)
l:
movq y@GOTPCREL(%rip), %rax
Since stub inspection requires cooperation with RuntimeDyldImpl this patch
pimpl-ifies RuntimeDyldChecker. Its implementation is moved in to a new class,
RuntimeDyldCheckerImpl, that has access to the definition of RuntimeDyldImpl.
llvm-svn: 213698
2014-07-23 06:47:39 +08:00
|
|
|
Dyld->setRuntimeDyldChecker(Checker);
|
2014-03-21 05:06:46 +08:00
|
|
|
return Dyld;
|
|
|
|
}
|
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
static std::unique_ptr<RuntimeDyldMachO>
|
2014-07-18 02:54:50 +08:00
|
|
|
createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM,
|
[MCJIT] Refactor and add stub inspection to the RuntimeDyldChecker framework.
This patch introduces a 'stub_addr' builtin that can be used to find the address
of the stub for a given (<file>, <section>, <symbol>) tuple. This address can be
used both to verify the contents of stubs (by loading from the returned address)
and to verify references to stubs (by comparing against the returned address).
Example (1) - Verifying stub contents:
Load 8 bytes (assuming a 64-bit target) from the stub for 'x' in the __text
section of f.o, and compare that value against the addres of 'x'.
# rtdyld-check: *{8}(stub_addr(f.o, __text, x) = x
Example (2) - Verifying references to stubs:
Decode the immediate of the instruction at label 'l', and verify that it's
equal to the offset from the next instruction's PC to the stub for 'y' in the
__text section of f.o (i.e. it's the correct PC-rel difference).
# rtdyld-check: decode_operand(l, 4) = stub_addr(f.o, __text, y) - next_pc(l)
l:
movq y@GOTPCREL(%rip), %rax
Since stub inspection requires cooperation with RuntimeDyldImpl this patch
pimpl-ifies RuntimeDyldChecker. Its implementation is moved in to a new class,
RuntimeDyldCheckerImpl, that has access to the definition of RuntimeDyldImpl.
llvm-svn: 213698
2014-07-23 06:47:39 +08:00
|
|
|
bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) {
|
2014-07-18 02:54:50 +08:00
|
|
|
std::unique_ptr<RuntimeDyldMachO> Dyld(RuntimeDyldMachO::create(Arch, MM));
|
2014-03-21 05:06:46 +08:00
|
|
|
Dyld->setProcessAllSections(ProcessAllSections);
|
[MCJIT] Refactor and add stub inspection to the RuntimeDyldChecker framework.
This patch introduces a 'stub_addr' builtin that can be used to find the address
of the stub for a given (<file>, <section>, <symbol>) tuple. This address can be
used both to verify the contents of stubs (by loading from the returned address)
and to verify references to stubs (by comparing against the returned address).
Example (1) - Verifying stub contents:
Load 8 bytes (assuming a 64-bit target) from the stub for 'x' in the __text
section of f.o, and compare that value against the addres of 'x'.
# rtdyld-check: *{8}(stub_addr(f.o, __text, x) = x
Example (2) - Verifying references to stubs:
Decode the immediate of the instruction at label 'l', and verify that it's
equal to the offset from the next instruction's PC to the stub for 'y' in the
__text section of f.o (i.e. it's the correct PC-rel difference).
# rtdyld-check: decode_operand(l, 4) = stub_addr(f.o, __text, y) - next_pc(l)
l:
movq y@GOTPCREL(%rip), %rax
Since stub inspection requires cooperation with RuntimeDyldImpl this patch
pimpl-ifies RuntimeDyldChecker. Its implementation is moved in to a new class,
RuntimeDyldCheckerImpl, that has access to the definition of RuntimeDyldImpl.
llvm-svn: 213698
2014-07-23 06:47:39 +08:00
|
|
|
Dyld->setRuntimeDyldChecker(Checker);
|
2014-03-21 05:06:46 +08:00
|
|
|
return Dyld;
|
|
|
|
}
|
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
std::unique_ptr<ObjectImage>
|
|
|
|
RuntimeDyld::loadObject(std::unique_ptr<ObjectFile> InputObject) {
|
|
|
|
std::unique_ptr<ObjectImage> InputImage;
|
|
|
|
|
|
|
|
ObjectFile &Obj = *InputObject;
|
|
|
|
|
|
|
|
if (InputObject->isELF()) {
|
|
|
|
InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(std::move(InputObject)));
|
|
|
|
if (!Dyld)
|
2014-09-05 02:37:29 +08:00
|
|
|
Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker);
|
2014-11-26 23:27:39 +08:00
|
|
|
} else if (InputObject->isMachO()) {
|
|
|
|
InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(std::move(InputObject)));
|
|
|
|
if (!Dyld)
|
2014-07-18 02:54:50 +08:00
|
|
|
Dyld = createRuntimeDyldMachO(
|
2014-11-26 23:27:39 +08:00
|
|
|
static_cast<Triple::ArchType>(InputImage->getArch()), MM,
|
|
|
|
ProcessAllSections, Checker);
|
|
|
|
} else
|
|
|
|
report_fatal_error("Incompatible object format!");
|
|
|
|
|
|
|
|
if (!Dyld->isCompatibleFile(&Obj))
|
|
|
|
report_fatal_error("Incompatible object format!");
|
|
|
|
|
|
|
|
return Dyld->loadObject(std::move(InputImage));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<ObjectImage>
|
|
|
|
RuntimeDyld::loadObject(std::unique_ptr<ObjectBuffer> InputBuffer) {
|
|
|
|
std::unique_ptr<ObjectImage> InputImage;
|
|
|
|
sys::fs::file_magic Type = sys::fs::identify_magic(InputBuffer->getBuffer());
|
|
|
|
auto *InputBufferPtr = InputBuffer.get();
|
|
|
|
|
|
|
|
switch (Type) {
|
|
|
|
case sys::fs::file_magic::elf:
|
|
|
|
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:
|
|
|
|
InputImage = RuntimeDyldELF::createObjectImage(std::move(InputBuffer));
|
|
|
|
if (!Dyld)
|
|
|
|
Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker);
|
|
|
|
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:
|
|
|
|
InputImage = RuntimeDyldMachO::createObjectImage(std::move(InputBuffer));
|
|
|
|
if (!Dyld)
|
|
|
|
Dyld = createRuntimeDyldMachO(
|
|
|
|
static_cast<Triple::ArchType>(InputImage->getArch()), MM,
|
|
|
|
ProcessAllSections, Checker);
|
|
|
|
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::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!");
|
2011-07-13 15:57:58 +08:00
|
|
|
}
|
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
if (!Dyld->isCompatibleFormat(InputBufferPtr))
|
2014-03-09 02:45:12 +08:00
|
|
|
report_fatal_error("Incompatible object format!");
|
|
|
|
|
2014-11-26 23:27:39 +08:00
|
|
|
return Dyld->loadObject(std::move(InputImage));
|
2011-03-22 06:15:52 +08:00
|
|
|
}
|
|
|
|
|
2014-09-06 02:00:16 +08:00
|
|
|
void *RuntimeDyld::getSymbolAddress(StringRef Name) const {
|
2013-10-01 09:47:35 +08:00
|
|
|
if (!Dyld)
|
2014-04-24 14:44:33 +08:00
|
|
|
return nullptr;
|
2011-03-22 06:15:52 +08:00
|
|
|
return Dyld->getSymbolAddress(Name);
|
|
|
|
}
|
|
|
|
|
2014-09-06 02:00:16 +08:00
|
|
|
uint64_t RuntimeDyld::getSymbolLoadAddress(StringRef Name) const {
|
2013-10-01 09:47:35 +08:00
|
|
|
if (!Dyld)
|
|
|
|
return 0;
|
2012-09-06 00:50:40 +08:00
|
|
|
return Dyld->getSymbolLoadAddress(Name);
|
|
|
|
}
|
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
void RuntimeDyld::resolveRelocations() { Dyld->resolveRelocations(); }
|
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-13 05:20:41 +08:00
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
void RuntimeDyld::reassignSectionAddress(unsigned SectionID, uint64_t Addr) {
|
2012-01-17 06:26:39 +08:00
|
|
|
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-13 05:20:41 +08:00
|
|
|
}
|
|
|
|
|
2012-09-14 05:50:06 +08:00
|
|
|
void RuntimeDyld::mapSectionAddress(const void *LocalAddress,
|
2012-01-17 07:50:55 +08:00
|
|
|
uint64_t TargetAddress) {
|
|
|
|
Dyld->mapSectionAddress(LocalAddress, TargetAddress);
|
|
|
|
}
|
|
|
|
|
2014-03-27 02:19:27 +08:00
|
|
|
bool RuntimeDyld::hasError() { return Dyld->hasError(); }
|
|
|
|
|
2014-03-22 04:28:42 +08:00
|
|
|
StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); }
|
2011-03-23 02:19:42 +08:00
|
|
|
|
2013-10-12 05:25:48 +08:00
|
|
|
void RuntimeDyld::registerEHFrames() {
|
2013-10-16 08:14:21 +08:00
|
|
|
if (Dyld)
|
|
|
|
Dyld->registerEHFrames();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RuntimeDyld::deregisterEHFrames() {
|
|
|
|
if (Dyld)
|
|
|
|
Dyld->deregisterEHFrames();
|
2013-05-06 04:43:10 +08:00
|
|
|
}
|
|
|
|
|
2011-03-22 06:15:52 +08:00
|
|
|
} // end namespace llvm
|