2012-01-16 23:50:58 +00:00
|
|
|
//===-- RuntimeDyld.cpp - Run-time dynamic linker for MC-JIT ----*- C++ -*-===//
|
2011-03-21 22:15:52 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2011-03-21 22:15:52 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Implementation of the MC-JIT runtime dynamic linker.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
2015-03-07 20:21:27 +00:00
|
|
|
#include "RuntimeDyldCOFF.h"
|
2012-01-22 07:05:02 +00:00
|
|
|
#include "RuntimeDyldELF.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "RuntimeDyldImpl.h"
|
2012-01-22 07:05:02 +00:00
|
|
|
#include "RuntimeDyldMachO.h"
|
2015-03-07 20:21:27 +00:00
|
|
|
#include "llvm/Object/COFF.h"
|
2017-06-06 11:49:48 +00:00
|
|
|
#include "llvm/Object/ELFObjectFile.h"
|
[Alignment] Move OffsetToAlignment to Alignment.h
Summary:
This is patch is part of a series to introduce an Alignment type.
See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html
See this patch for the introduction of the type: https://reviews.llvm.org/D64790
Reviewers: courbet, JDevlieghere, alexshap, rupprecht, jhenderson
Subscribers: sdardis, nemanjai, hiraditya, kbarton, jakehehrlich, jrtc27, MaskRay, atanasyan, jsji, seiya, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D67499
llvm-svn: 371742
2019-09-12 15:20:36 +00:00
|
|
|
#include "llvm/Support/Alignment.h"
|
2018-09-25 20:16:06 +00:00
|
|
|
#include "llvm/Support/MSVCErrorWorkarounds.h"
|
2012-10-29 10:47:04 +00:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2019-08-07 10:57:25 +00:00
|
|
|
#include <mutex>
|
2012-01-22 07:05:02 +00:00
|
|
|
|
2018-09-25 19:48:46 +00:00
|
|
|
#include <future>
|
|
|
|
|
2011-03-21 22:15:52 +00:00
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::object;
|
|
|
|
|
2014-04-22 03:04:17 +00:00
|
|
|
#define DEBUG_TYPE "dyld"
|
|
|
|
|
2016-04-27 20:24:48 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
enum RuntimeDyldErrorCode {
|
|
|
|
GenericRTDyldError = 1
|
|
|
|
};
|
|
|
|
|
2016-05-24 20:13:46 +00:00
|
|
|
// FIXME: This class is only here to support the transition to llvm::Error. It
|
|
|
|
// will be removed once this transition is complete. Clients should prefer to
|
|
|
|
// deal with the Error value directly, rather than converting to error_code.
|
2016-04-27 20:24:48 +00:00
|
|
|
class RuntimeDyldErrorCategory : public std::error_category {
|
|
|
|
public:
|
2016-10-19 23:52:38 +00:00
|
|
|
const char *name() const noexcept override { return "runtimedyld"; }
|
2016-04-27 20:24:48 +00:00
|
|
|
|
|
|
|
std::string message(int Condition) const override {
|
|
|
|
switch (static_cast<RuntimeDyldErrorCode>(Condition)) {
|
|
|
|
case GenericRTDyldError: return "Generic RuntimeDyld error";
|
|
|
|
}
|
|
|
|
llvm_unreachable("Unrecognized RuntimeDyldErrorCode");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
char RuntimeDyldError::ID = 0;
|
|
|
|
|
|
|
|
void RuntimeDyldError::log(raw_ostream &OS) const {
|
|
|
|
OS << ErrMsg << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
std::error_code RuntimeDyldError::convertToErrorCode() const {
|
2022-06-29 14:29:33 +02:00
|
|
|
static RuntimeDyldErrorCategory RTDyldErrorCategory;
|
|
|
|
return std::error_code(GenericRTDyldError, RTDyldErrorCategory);
|
2016-04-27 20:24:48 +00:00
|
|
|
}
|
|
|
|
|
2011-04-05 23:54:31 +00:00
|
|
|
// Empty out-of-line virtual destructor as the key function.
|
2022-02-06 22:18:35 -08:00
|
|
|
RuntimeDyldImpl::~RuntimeDyldImpl() = default;
|
2011-04-05 23:54:31 +00:00
|
|
|
|
2014-11-26 16:54:40 +00:00
|
|
|
// Pin LoadedObjectInfo's vtables to this file.
|
|
|
|
void RuntimeDyld::LoadedObjectInfo::anchor() {}
|
2013-11-19 00:57:56 +00:00
|
|
|
|
2011-03-21 22:15:52 +00:00
|
|
|
namespace llvm {
|
|
|
|
|
2014-03-21 20:28:42 +00:00
|
|
|
void RuntimeDyldImpl::registerEHFrames() {}
|
2013-05-05 20:43:10 +00:00
|
|
|
|
2017-05-09 21:32:18 +00:00
|
|
|
void RuntimeDyldImpl::deregisterEHFrames() {
|
|
|
|
MemMgr.deregisterEHFrames();
|
|
|
|
}
|
2013-10-16 00:14:21 +00:00
|
|
|
|
2014-08-26 14:22:05 +00:00
|
|
|
#ifndef NDEBUG
|
2014-08-25 22:19:14 +00:00
|
|
|
static void dumpSectionMemory(const SectionEntry &S, StringRef State) {
|
2015-11-23 21:47:41 +00:00
|
|
|
dbgs() << "----- Contents of section " << S.getName() << " " << State
|
|
|
|
<< " -----";
|
2014-08-25 22:19:14 +00:00
|
|
|
|
2015-11-23 21:47:41 +00:00
|
|
|
if (S.getAddress() == nullptr) {
|
2014-10-01 21:57:47 +00:00
|
|
|
dbgs() << "\n <section not emitted>\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-08-25 22:19:14 +00:00
|
|
|
const unsigned ColsPerRow = 16;
|
2014-08-25 18:37:38 +00:00
|
|
|
|
2015-11-23 21:47:41 +00:00
|
|
|
uint8_t *DataAddr = S.getAddress();
|
|
|
|
uint64_t LoadAddr = S.getLoadAddress();
|
2014-08-25 18:37:38 +00:00
|
|
|
|
2014-09-18 16:43:24 +00:00
|
|
|
unsigned StartPadding = LoadAddr & (ColsPerRow - 1);
|
2015-11-23 21:47:41 +00:00
|
|
|
unsigned BytesRemaining = S.getSize();
|
2014-08-25 18:37:38 +00:00
|
|
|
|
|
|
|
if (StartPadding) {
|
2015-03-30 05:15:57 +00:00
|
|
|
dbgs() << "\n" << format("0x%016" PRIx64,
|
|
|
|
LoadAddr & ~(uint64_t)(ColsPerRow - 1)) << ":";
|
2014-08-25 18:37:38 +00:00
|
|
|
while (StartPadding--)
|
|
|
|
dbgs() << " ";
|
|
|
|
}
|
|
|
|
|
|
|
|
while (BytesRemaining > 0) {
|
2014-08-25 22:19:14 +00:00
|
|
|
if ((LoadAddr & (ColsPerRow - 1)) == 0)
|
2014-08-28 04:25:17 +00:00
|
|
|
dbgs() << "\n" << format("0x%016" PRIx64, LoadAddr) << ":";
|
2014-08-25 18:37:38 +00:00
|
|
|
|
|
|
|
dbgs() << " " << format("%02x", *DataAddr);
|
|
|
|
|
|
|
|
++DataAddr;
|
|
|
|
++LoadAddr;
|
|
|
|
--BytesRemaining;
|
|
|
|
}
|
|
|
|
|
|
|
|
dbgs() << "\n";
|
|
|
|
}
|
2014-08-26 14:22:05 +00:00
|
|
|
#endif
|
2014-08-25 18:37:38 +00: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-12 21:20:41 +00:00
|
|
|
// Resolve the relocations for all symbols we currently know about.
|
|
|
|
void RuntimeDyldImpl::resolveRelocations() {
|
2019-08-07 10:57:25 +00:00
|
|
|
std::lock_guard<sys::Mutex> locked(lock);
|
2013-10-21 17:42:06 +00:00
|
|
|
|
2015-09-10 20:44:36 +00:00
|
|
|
// Print out the sections prior to relocation.
|
2021-12-08 20:35:39 -08:00
|
|
|
LLVM_DEBUG({
|
|
|
|
for (SectionEntry &S : Sections)
|
|
|
|
dumpSectionMemory(S, "before relocations");
|
|
|
|
});
|
2015-09-10 20:44:36 +00:00
|
|
|
|
2012-04-12 20:13:57 +00:00
|
|
|
// First, resolve relocations associated with external symbols.
|
2017-07-07 02:59:13 +00:00
|
|
|
if (auto Err = resolveExternalSymbols()) {
|
|
|
|
HasError = true;
|
|
|
|
ErrorStr = toString(std::move(Err));
|
|
|
|
}
|
2012-03-30 16:45:19 +00:00
|
|
|
|
2018-09-25 22:57:44 +00:00
|
|
|
resolveLocalRelocations();
|
|
|
|
|
|
|
|
// Print out sections after relocation.
|
2021-12-08 20:35:39 -08:00
|
|
|
LLVM_DEBUG({
|
|
|
|
for (SectionEntry &S : Sections)
|
|
|
|
dumpSectionMemory(S, "after relocations");
|
|
|
|
});
|
2018-09-25 22:57:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RuntimeDyldImpl::resolveLocalRelocations() {
|
2015-10-10 05:37:02 +00:00
|
|
|
// Iterate over all outstanding relocations
|
2021-12-08 20:35:39 -08:00
|
|
|
for (const auto &Rel : Relocations) {
|
2013-08-19 19:38:06 +00: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.
|
2021-12-08 20:35:39 -08:00
|
|
|
unsigned Idx = Rel.first;
|
2020-10-30 11:35:12 +01:00
|
|
|
uint64_t Addr = getSectionLoadAddress(Idx);
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "Resolving relocations Section #" << Idx << "\t"
|
|
|
|
<< format("%p", (uintptr_t)Addr) << "\n");
|
2021-12-08 20:35:39 -08:00
|
|
|
resolveRelocationList(Rel.second, Addr);
|
2012-01-16 22:26:39 +00:00
|
|
|
}
|
2015-10-10 05:37:02 +00:00
|
|
|
Relocations.clear();
|
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 21:20:41 +00:00
|
|
|
}
|
|
|
|
|
2012-09-13 21:50:06 +00:00
|
|
|
void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress,
|
2012-01-16 23:50:55 +00:00
|
|
|
uint64_t TargetAddress) {
|
2019-08-07 10:57:25 +00:00
|
|
|
std::lock_guard<sys::Mutex> locked(lock);
|
2012-03-30 16:45:19 +00:00
|
|
|
for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
|
2015-11-23 21:47:41 +00:00
|
|
|
if (Sections[i].getAddress() == LocalAddress) {
|
2012-03-30 16:45:19 +00:00
|
|
|
reassignSectionAddress(i, TargetAddress);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
llvm_unreachable("Attempting to remap address of unknown section!");
|
|
|
|
}
|
|
|
|
|
2016-04-27 20:24:48 +00:00
|
|
|
static Error getOffset(const SymbolRef &Sym, SectionRef Sec,
|
|
|
|
uint64_t &Result) {
|
2016-06-24 18:24:42 +00:00
|
|
|
Expected<uint64_t> AddressOrErr = Sym.getAddress();
|
|
|
|
if (!AddressOrErr)
|
|
|
|
return AddressOrErr.takeError();
|
2015-07-07 16:45:55 +00:00
|
|
|
Result = *AddressOrErr - Sec.getAddress();
|
2016-04-27 20:24:48 +00:00
|
|
|
return Error::success();
|
2014-04-21 13:45:32 +00:00
|
|
|
}
|
|
|
|
|
2016-04-27 20:24:48 +00:00
|
|
|
Expected<RuntimeDyldImpl::ObjSectionToIDMap>
|
2014-11-26 16:54:40 +00:00
|
|
|
RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
2019-08-07 10:57:25 +00:00
|
|
|
std::lock_guard<sys::Mutex> locked(lock);
|
2013-10-21 17:42:06 +00:00
|
|
|
|
2013-10-15 20:44:55 +00:00
|
|
|
// Save information about our target
|
2014-11-26 16:54:40 +00:00
|
|
|
Arch = (Triple::ArchType)Obj.getArch();
|
|
|
|
IsTargetLittleEndian = Obj.isLittleEndian();
|
2015-05-28 13:48:41 +00:00
|
|
|
setMipsABI(Obj);
|
2014-03-21 20:28:42 +00:00
|
|
|
|
2014-02-12 21:30:07 +00:00
|
|
|
// Compute the memory size required to load all sections to be loaded
|
|
|
|
// and pass this information to the memory manager
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 03:37:06 +00:00
|
|
|
if (MemMgr.needsToReserveAllocationSpace()) {
|
2016-01-10 18:51:50 +00:00
|
|
|
uint64_t CodeSize = 0, RODataSize = 0, RWDataSize = 0;
|
2022-12-01 14:50:29 +00:00
|
|
|
Align CodeAlign, RODataAlign, RWDataAlign;
|
|
|
|
if (auto Err = computeTotalAllocSize(Obj, CodeSize, CodeAlign, RODataSize,
|
|
|
|
RODataAlign, RWDataSize, RWDataAlign))
|
2020-02-10 07:06:45 -08:00
|
|
|
return std::move(Err);
|
2016-01-10 18:51:50 +00:00
|
|
|
MemMgr.reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign,
|
|
|
|
RWDataSize, RWDataAlign);
|
2014-02-12 21:30:07 +00:00
|
|
|
}
|
2014-03-21 20:28:42 +00:00
|
|
|
|
2012-05-01 06:58:59 +00:00
|
|
|
// Used sections from the object file
|
|
|
|
ObjSectionToIDMap LocalSections;
|
|
|
|
|
2012-10-29 10:47:04 +00:00
|
|
|
// Common symbols requiring allocation, with their sizes and alignments
|
2018-01-19 22:24:13 +00:00
|
|
|
CommonSymbolList CommonSymbolsToAllocate;
|
|
|
|
|
|
|
|
uint64_t CommonSize = 0;
|
|
|
|
uint32_t CommonAlign = 0;
|
|
|
|
|
|
|
|
// First, collect all weak and common symbols. We need to know if stronger
|
|
|
|
// definitions occur elsewhere.
|
2018-08-28 21:18:05 +00:00
|
|
|
JITSymbolResolver::LookupSet ResponsibilitySet;
|
2018-01-19 22:24:13 +00:00
|
|
|
{
|
2018-01-22 03:00:31 +00:00
|
|
|
JITSymbolResolver::LookupSet Symbols;
|
2018-01-19 22:24:13 +00:00
|
|
|
for (auto &Sym : Obj.symbols()) {
|
2020-04-10 20:24:21 +08:00
|
|
|
Expected<uint32_t> FlagsOrErr = Sym.getFlags();
|
|
|
|
if (!FlagsOrErr)
|
|
|
|
// TODO: Test this error.
|
|
|
|
return FlagsOrErr.takeError();
|
|
|
|
if ((*FlagsOrErr & SymbolRef::SF_Common) ||
|
|
|
|
(*FlagsOrErr & SymbolRef::SF_Weak)) {
|
2018-01-19 22:24:13 +00:00
|
|
|
// Get symbol name.
|
|
|
|
if (auto NameOrErr = Sym.getName())
|
|
|
|
Symbols.insert(*NameOrErr);
|
|
|
|
else
|
|
|
|
return NameOrErr.takeError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-28 21:18:05 +00:00
|
|
|
if (auto ResultOrErr = Resolver.getResponsibilitySet(Symbols))
|
|
|
|
ResponsibilitySet = std::move(*ResultOrErr);
|
2018-01-19 22:24:13 +00:00
|
|
|
else
|
2018-08-28 21:18:05 +00:00
|
|
|
return ResultOrErr.takeError();
|
2018-01-19 22:24:13 +00:00
|
|
|
}
|
2012-03-30 16:45:19 +00:00
|
|
|
|
|
|
|
// Parse symbols
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "Parse symbols:\n");
|
2014-11-26 16:54:40 +00:00
|
|
|
for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E;
|
2014-04-21 19:23:59 +00:00
|
|
|
++I) {
|
2020-04-10 20:24:21 +08:00
|
|
|
Expected<uint32_t> FlagsOrErr = I->getFlags();
|
|
|
|
if (!FlagsOrErr)
|
|
|
|
// TODO: Test this error.
|
|
|
|
return FlagsOrErr.takeError();
|
2012-04-12 20:13:57 +00:00
|
|
|
|
2016-11-30 01:12:07 +00:00
|
|
|
// Skip undefined symbols.
|
2020-04-10 20:24:21 +08:00
|
|
|
if (*FlagsOrErr & SymbolRef::SF_Undefined)
|
2016-11-30 01:12:07 +00:00
|
|
|
continue;
|
|
|
|
|
2018-01-19 22:24:13 +00:00
|
|
|
// Get the symbol type.
|
|
|
|
object::SymbolRef::Type SymType;
|
|
|
|
if (auto SymTypeOrErr = I->getType())
|
|
|
|
SymType = *SymTypeOrErr;
|
|
|
|
else
|
|
|
|
return SymTypeOrErr.takeError();
|
2016-04-27 20:24:48 +00:00
|
|
|
|
2018-01-19 22:24:13 +00:00
|
|
|
// Get symbol name.
|
|
|
|
StringRef Name;
|
|
|
|
if (auto NameOrErr = I->getName())
|
|
|
|
Name = *NameOrErr;
|
|
|
|
else
|
|
|
|
return NameOrErr.takeError();
|
2018-01-19 01:40:26 +00:00
|
|
|
|
2018-01-19 22:24:13 +00:00
|
|
|
// Compute JIT symbol flags.
|
2018-08-01 22:42:23 +00:00
|
|
|
auto JITSymFlags = getJITSymbolFlags(*I);
|
|
|
|
if (!JITSymFlags)
|
|
|
|
return JITSymFlags.takeError();
|
2018-01-19 22:24:13 +00:00
|
|
|
|
|
|
|
// If this is a weak definition, check to see if there's a strong one.
|
|
|
|
// If there is, skip this symbol (we won't be providing it: the strong
|
|
|
|
// definition will). If there's no strong definition, make this definition
|
|
|
|
// strong.
|
2018-08-01 22:42:23 +00:00
|
|
|
if (JITSymFlags->isWeak() || JITSymFlags->isCommon()) {
|
2018-01-19 22:24:13 +00:00
|
|
|
// First check whether there's already a definition in this instance.
|
|
|
|
if (GlobalSymbolTable.count(Name))
|
|
|
|
continue;
|
2016-04-27 20:24:48 +00:00
|
|
|
|
2018-08-28 21:18:05 +00:00
|
|
|
// If we're not responsible for this symbol, skip it.
|
|
|
|
if (!ResponsibilitySet.count(Name))
|
2018-01-19 22:24:13 +00:00
|
|
|
continue;
|
2018-08-28 21:18:05 +00:00
|
|
|
|
|
|
|
// Otherwise update the flags on the symbol to make this definition
|
|
|
|
// strong.
|
|
|
|
if (JITSymFlags->isWeak())
|
|
|
|
*JITSymFlags &= ~JITSymbolFlags::Weak;
|
|
|
|
if (JITSymFlags->isCommon()) {
|
|
|
|
*JITSymFlags &= ~JITSymbolFlags::Common;
|
|
|
|
uint32_t Align = I->getAlignment();
|
|
|
|
uint64_t Size = I->getCommonSize();
|
|
|
|
if (!CommonAlign)
|
|
|
|
CommonAlign = Align;
|
|
|
|
CommonSize = alignTo(CommonSize, Align) + Size;
|
|
|
|
CommonSymbolsToAllocate.push_back(*I);
|
|
|
|
}
|
2018-01-19 22:24:13 +00:00
|
|
|
}
|
|
|
|
|
2020-04-10 20:24:21 +08:00
|
|
|
if (*FlagsOrErr & SymbolRef::SF_Absolute &&
|
2018-01-19 22:24:13 +00:00
|
|
|
SymType != object::SymbolRef::ST_File) {
|
|
|
|
uint64_t Addr = 0;
|
|
|
|
if (auto AddrOrErr = I->getAddress())
|
|
|
|
Addr = *AddrOrErr;
|
|
|
|
else
|
|
|
|
return AddrOrErr.takeError();
|
|
|
|
|
|
|
|
unsigned SectionID = AbsoluteSymbolSection;
|
|
|
|
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name
|
|
|
|
<< " SID: " << SectionID
|
|
|
|
<< " Offset: " << format("%p", (uintptr_t)Addr)
|
2020-04-10 20:24:21 +08:00
|
|
|
<< " flags: " << *FlagsOrErr << "\n");
|
2021-01-20 17:08:47 +01:00
|
|
|
// Skip absolute symbol relocations.
|
|
|
|
if (!Name.empty()) {
|
|
|
|
auto Result = GlobalSymbolTable.insert_or_assign(
|
|
|
|
Name, SymbolTableEntry(SectionID, Addr, *JITSymFlags));
|
|
|
|
processNewSymbol(*I, Result.first->getValue());
|
|
|
|
}
|
2018-01-19 22:24:13 +00:00
|
|
|
} else if (SymType == object::SymbolRef::ST_Function ||
|
|
|
|
SymType == object::SymbolRef::ST_Data ||
|
|
|
|
SymType == object::SymbolRef::ST_Unknown ||
|
|
|
|
SymType == object::SymbolRef::ST_Other) {
|
|
|
|
|
|
|
|
section_iterator SI = Obj.section_end();
|
|
|
|
if (auto SIOrErr = I->getSection())
|
|
|
|
SI = *SIOrErr;
|
|
|
|
else
|
|
|
|
return SIOrErr.takeError();
|
2016-04-27 20:24:48 +00:00
|
|
|
|
2018-01-19 22:24:13 +00:00
|
|
|
if (SI == Obj.section_end())
|
|
|
|
continue;
|
2016-04-27 20:24:48 +00:00
|
|
|
|
2018-01-19 22:24:13 +00:00
|
|
|
// Get symbol offset.
|
|
|
|
uint64_t SectOffset;
|
|
|
|
if (auto Err = getOffset(*I, *SI, SectOffset))
|
2020-02-10 07:06:45 -08:00
|
|
|
return std::move(Err);
|
2018-01-19 01:40:26 +00:00
|
|
|
|
2018-01-19 22:24:13 +00:00
|
|
|
bool IsCode = SI->isText();
|
|
|
|
unsigned SectionID;
|
|
|
|
if (auto SectionIDOrErr =
|
|
|
|
findOrEmitSection(Obj, *SI, IsCode, LocalSections))
|
|
|
|
SectionID = *SectionIDOrErr;
|
|
|
|
else
|
|
|
|
return SectionIDOrErr.takeError();
|
2015-10-18 01:41:37 +00:00
|
|
|
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name
|
|
|
|
<< " SID: " << SectionID
|
|
|
|
<< " Offset: " << format("%p", (uintptr_t)SectOffset)
|
2020-04-10 20:24:21 +08:00
|
|
|
<< " flags: " << *FlagsOrErr << "\n");
|
2021-01-20 17:08:47 +01:00
|
|
|
// Skip absolute symbol relocations.
|
|
|
|
if (!Name.empty()) {
|
|
|
|
auto Result = GlobalSymbolTable.insert_or_assign(
|
|
|
|
Name, SymbolTableEntry(SectionID, SectOffset, *JITSymFlags));
|
|
|
|
processNewSymbol(*I, Result.first->getValue());
|
|
|
|
}
|
2012-03-30 16:45:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-12 20:13:57 +00:00
|
|
|
// Allocate common symbols
|
2018-01-19 22:24:13 +00:00
|
|
|
if (auto Err = emitCommonSymbols(Obj, CommonSymbolsToAllocate, CommonSize,
|
|
|
|
CommonAlign))
|
2020-02-10 07:06:45 -08:00
|
|
|
return std::move(Err);
|
2012-04-12 20:13:57 +00:00
|
|
|
|
2012-04-29 12:40:47 +00:00
|
|
|
// Parse and process relocations
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "Parse relocations:\n");
|
2014-11-26 16:54:40 +00:00
|
|
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
2014-04-21 19:23:59 +00:00
|
|
|
SI != SE; ++SI) {
|
2012-03-30 16:45:19 +00:00
|
|
|
StubMap Stubs;
|
|
|
|
|
2019-10-21 11:06:38 +00:00
|
|
|
Expected<section_iterator> RelSecOrErr = SI->getRelocatedSection();
|
|
|
|
if (!RelSecOrErr)
|
|
|
|
return RelSecOrErr.takeError();
|
|
|
|
|
|
|
|
section_iterator RelocatedSection = *RelSecOrErr;
|
2015-02-17 20:07:28 +00:00
|
|
|
if (RelocatedSection == SE)
|
|
|
|
continue;
|
|
|
|
|
2014-04-21 19:23:59 +00:00
|
|
|
relocation_iterator I = SI->relocation_begin();
|
|
|
|
relocation_iterator E = SI->relocation_end();
|
2014-04-03 22:42:22 +00:00
|
|
|
|
|
|
|
if (I == E && !ProcessAllSections)
|
2014-03-21 07:26:41 +00:00
|
|
|
continue;
|
|
|
|
|
2014-10-08 15:28:58 +00:00
|
|
|
bool IsCode = RelocatedSection->isText();
|
2016-04-27 20:24:48 +00:00
|
|
|
unsigned SectionID = 0;
|
|
|
|
if (auto SectionIDOrErr = findOrEmitSection(Obj, *RelocatedSection, IsCode,
|
|
|
|
LocalSections))
|
|
|
|
SectionID = *SectionIDOrErr;
|
|
|
|
else
|
|
|
|
return SectionIDOrErr.takeError();
|
|
|
|
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
|
2014-03-21 07:26:41 +00:00
|
|
|
|
2014-04-03 22:42:22 +00:00
|
|
|
for (; I != E;)
|
2016-04-27 20:24:48 +00:00
|
|
|
if (auto IOrErr = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs))
|
|
|
|
I = *IOrErr;
|
|
|
|
else
|
|
|
|
return IOrErr.takeError();
|
[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-22 22:47:39 +00:00
|
|
|
|
2019-04-08 21:50:48 +00:00
|
|
|
// If there is a NotifyStubEmitted callback set, call it to register any
|
|
|
|
// stubs created for this section.
|
|
|
|
if (NotifyStubEmitted) {
|
|
|
|
StringRef FileName = Obj.getFileName();
|
|
|
|
StringRef SectionName = Sections[SectionID].getName();
|
|
|
|
for (auto &KV : Stubs) {
|
|
|
|
|
|
|
|
auto &VR = KV.first;
|
|
|
|
uint64_t StubAddr = KV.second;
|
|
|
|
|
|
|
|
// If this is a named stub, just call NotifyStubEmitted.
|
|
|
|
if (VR.SymbolName) {
|
Simplify decoupling between RuntimeDyld/RuntimeDyldChecker, add 'got_addr' util.
This patch reduces the number of functions in the interface between RuntimeDyld
and RuntimeDyldChecker by combining "GetXAddress" and "GetXContent" functions
into "GetXInfo" functions that return a struct describing both the address and
content. The GetStubOffset function is also replaced with a pair of utilities,
GetStubInfo and GetGOTInfo, that fit the new scheme. For RuntimeDyld both of
these functions will return the same result, but for the new JITLink linker
(https://reviews.llvm.org/D58704) these will provide the addresses of PLT stubs
and GOT entries respectively.
For JITLink's use, a 'got_addr' utility has been added to the rtdyld-check
language, and the syntax of 'got_addr' and 'stub_addr' has been changed: both
functions now take two arguments, a 'stub container name' and a target symbol
name. For llvm-rtdyld/RuntimeDyld the stub container name is the object file
name and section name, separated by a slash. E.g.:
rtdyld-check: *{8}(stub_addr(foo.o/__text, y)) = y
For the upcoming llvm-jitlink utility, which creates stubs on a per-file basis
rather than a per-section basis, the container name is just the file name. E.g.:
jitlink-check: *{8}(got_addr(foo.o, y)) = y
llvm-svn: 358295
2019-04-12 18:07:28 +00:00
|
|
|
NotifyStubEmitted(FileName, SectionName, VR.SymbolName, SectionID,
|
|
|
|
StubAddr);
|
2019-04-08 21:50:48 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise we will have to try a reverse lookup on the globla symbol table.
|
|
|
|
for (auto &GSTMapEntry : GlobalSymbolTable) {
|
|
|
|
StringRef SymbolName = GSTMapEntry.first();
|
|
|
|
auto &GSTEntry = GSTMapEntry.second;
|
|
|
|
if (GSTEntry.getSectionID() == VR.SectionID &&
|
|
|
|
GSTEntry.getOffset() == VR.Offset) {
|
Simplify decoupling between RuntimeDyld/RuntimeDyldChecker, add 'got_addr' util.
This patch reduces the number of functions in the interface between RuntimeDyld
and RuntimeDyldChecker by combining "GetXAddress" and "GetXContent" functions
into "GetXInfo" functions that return a struct describing both the address and
content. The GetStubOffset function is also replaced with a pair of utilities,
GetStubInfo and GetGOTInfo, that fit the new scheme. For RuntimeDyld both of
these functions will return the same result, but for the new JITLink linker
(https://reviews.llvm.org/D58704) these will provide the addresses of PLT stubs
and GOT entries respectively.
For JITLink's use, a 'got_addr' utility has been added to the rtdyld-check
language, and the syntax of 'got_addr' and 'stub_addr' has been changed: both
functions now take two arguments, a 'stub container name' and a target symbol
name. For llvm-rtdyld/RuntimeDyld the stub container name is the object file
name and section name, separated by a slash. E.g.:
rtdyld-check: *{8}(stub_addr(foo.o/__text, y)) = y
For the upcoming llvm-jitlink utility, which creates stubs on a per-file basis
rather than a per-section basis, the container name is just the file name. E.g.:
jitlink-check: *{8}(got_addr(foo.o, y)) = y
llvm-svn: 358295
2019-04-12 18:07:28 +00:00
|
|
|
NotifyStubEmitted(FileName, SectionName, SymbolName, SectionID,
|
|
|
|
StubAddr);
|
2019-04-08 21:50:48 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-30 16:45:19 +00:00
|
|
|
}
|
2012-04-16 22:12:58 +00:00
|
|
|
|
2019-01-28 21:35:23 +00:00
|
|
|
// Process remaining sections
|
|
|
|
if (ProcessAllSections) {
|
|
|
|
LLVM_DEBUG(dbgs() << "Process remaining sections:\n");
|
|
|
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
|
|
|
SI != SE; ++SI) {
|
|
|
|
|
|
|
|
/* Ignore already loaded sections */
|
|
|
|
if (LocalSections.find(*SI) != LocalSections.end())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
bool IsCode = SI->isText();
|
|
|
|
if (auto SectionIDOrErr =
|
|
|
|
findOrEmitSection(Obj, *SI, IsCode, LocalSections))
|
|
|
|
LLVM_DEBUG(dbgs() << "\tSectionID: " << (*SectionIDOrErr) << "\n");
|
|
|
|
else
|
|
|
|
return SectionIDOrErr.takeError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-19 23:27:43 +00:00
|
|
|
// Give the subclasses a chance to tie-up any loose ends.
|
2016-04-27 20:24:48 +00:00
|
|
|
if (auto Err = finalizeLoad(Obj, LocalSections))
|
2020-02-10 07:06:45 -08:00
|
|
|
return std::move(Err);
|
2014-11-26 16:54:40 +00:00
|
|
|
|
2015-07-28 17:52:11 +00:00
|
|
|
// for (auto E : LocalSections)
|
|
|
|
// llvm::dbgs() << "Added: " << E.first.getRawDataRefImpl() << " -> " << E.second << "\n";
|
2013-08-19 23:27:43 +00:00
|
|
|
|
2015-07-28 17:52:11 +00:00
|
|
|
return LocalSections;
|
2014-02-12 21:30:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// A helper method for computeTotalAllocSize.
|
2014-03-21 20:28:42 +00:00
|
|
|
// Computes the memory size required to allocate sections with the given sizes,
|
2014-02-12 21:30:07 +00:00
|
|
|
// assuming that all sections are allocated with the given alignment
|
2014-03-21 20:28:42 +00:00
|
|
|
static uint64_t
|
|
|
|
computeAllocationSizeForSections(std::vector<uint64_t> &SectionSizes,
|
2022-12-01 14:50:29 +00:00
|
|
|
Align Alignment) {
|
2014-02-12 21:30:07 +00:00
|
|
|
uint64_t TotalSize = 0;
|
2022-12-01 14:50:29 +00:00
|
|
|
for (uint64_t SectionSize : SectionSizes)
|
|
|
|
TotalSize += alignTo(SectionSize, Alignment);
|
2014-02-12 21:30:07 +00:00
|
|
|
return TotalSize;
|
|
|
|
}
|
|
|
|
|
2015-06-26 12:44:10 +00:00
|
|
|
static bool isRequiredForExecution(const SectionRef Section) {
|
2014-12-10 20:46:55 +00:00
|
|
|
const ObjectFile *Obj = Section.getObject();
|
2015-06-26 12:44:10 +00:00
|
|
|
if (isa<object::ELFObjectFileBase>(Obj))
|
|
|
|
return ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC;
|
2015-03-07 20:21:27 +00:00
|
|
|
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj)) {
|
|
|
|
const coff_section *CoffSection = COFFObj->getCOFFSection(Section);
|
|
|
|
// Avoid loading zero-sized COFF sections.
|
|
|
|
// In PE files, VirtualSize gives the section size, and SizeOfRawData
|
2016-07-04 01:26:27 +00:00
|
|
|
// may be zero for sections with content. In Obj files, SizeOfRawData
|
2015-03-07 20:21:27 +00:00
|
|
|
// gives the section size, and VirtualSize is always zero. Hence
|
|
|
|
// the need to check for both cases below.
|
2016-07-04 01:26:14 +00:00
|
|
|
bool HasContent =
|
|
|
|
(CoffSection->VirtualSize > 0) || (CoffSection->SizeOfRawData > 0);
|
|
|
|
bool IsDiscardable =
|
|
|
|
CoffSection->Characteristics &
|
|
|
|
(COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_LNK_INFO);
|
2015-03-07 20:21:27 +00:00
|
|
|
return HasContent && !IsDiscardable;
|
|
|
|
}
|
2016-07-04 01:26:33 +00:00
|
|
|
|
2014-12-10 20:46:55 +00:00
|
|
|
assert(isa<MachOObjectFile>(Obj));
|
|
|
|
return true;
|
2015-06-26 12:44:10 +00:00
|
|
|
}
|
2014-12-10 20:46:55 +00:00
|
|
|
|
2015-06-26 12:44:10 +00:00
|
|
|
static bool isReadOnlyData(const SectionRef Section) {
|
2014-12-10 20:46:55 +00:00
|
|
|
const ObjectFile *Obj = Section.getObject();
|
2015-06-26 12:44:10 +00:00
|
|
|
if (isa<object::ELFObjectFileBase>(Obj))
|
|
|
|
return !(ELFSectionRef(Section).getFlags() &
|
2014-12-10 20:46:55 +00:00
|
|
|
(ELF::SHF_WRITE | ELF::SHF_EXECINSTR));
|
2015-03-07 20:21:27 +00:00
|
|
|
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj))
|
|
|
|
return ((COFFObj->getCOFFSection(Section)->Characteristics &
|
|
|
|
(COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
|
|
|
| COFF::IMAGE_SCN_MEM_READ
|
|
|
|
| COFF::IMAGE_SCN_MEM_WRITE))
|
|
|
|
==
|
|
|
|
(COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
|
|
|
|
| COFF::IMAGE_SCN_MEM_READ));
|
|
|
|
|
2014-12-10 20:46:55 +00:00
|
|
|
assert(isa<MachOObjectFile>(Obj));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-06-26 12:33:37 +00:00
|
|
|
static bool isZeroInit(const SectionRef Section) {
|
2014-12-10 20:46:55 +00:00
|
|
|
const ObjectFile *Obj = Section.getObject();
|
2015-06-26 12:33:37 +00:00
|
|
|
if (isa<object::ELFObjectFileBase>(Obj))
|
|
|
|
return ELFSectionRef(Section).getType() == ELF::SHT_NOBITS;
|
2015-03-07 20:21:27 +00:00
|
|
|
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj))
|
|
|
|
return COFFObj->getCOFFSection(Section)->Characteristics &
|
|
|
|
COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
|
2014-12-10 20:46:55 +00:00
|
|
|
|
|
|
|
auto *MachO = cast<MachOObjectFile>(Obj);
|
|
|
|
unsigned SectionType = MachO->getSectionType(Section);
|
|
|
|
return SectionType == MachO::S_ZEROFILL ||
|
|
|
|
SectionType == MachO::S_GB_ZEROFILL;
|
|
|
|
}
|
|
|
|
|
2021-08-27 15:51:58 +02:00
|
|
|
static bool isTLS(const SectionRef Section) {
|
|
|
|
const ObjectFile *Obj = Section.getObject();
|
|
|
|
if (isa<object::ELFObjectFileBase>(Obj))
|
|
|
|
return ELFSectionRef(Section).getFlags() & ELF::SHF_TLS;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-03-21 20:28:42 +00:00
|
|
|
// Compute an upper bound of the memory size that is required to load all
|
|
|
|
// sections
|
2022-12-01 14:50:29 +00:00
|
|
|
Error RuntimeDyldImpl::computeTotalAllocSize(
|
|
|
|
const ObjectFile &Obj, uint64_t &CodeSize, Align &CodeAlign,
|
|
|
|
uint64_t &RODataSize, Align &RODataAlign, uint64_t &RWDataSize,
|
|
|
|
Align &RWDataAlign) {
|
2014-02-12 21:30:07 +00: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-21 20:28:42 +00:00
|
|
|
// Collect sizes of all sections to be loaded;
|
2014-02-12 21:30:07 +00:00
|
|
|
// also determine the max alignment of all sections
|
2014-11-26 16:54:40 +00:00
|
|
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
2014-04-21 19:23:59 +00:00
|
|
|
SI != SE; ++SI) {
|
|
|
|
const SectionRef &Section = *SI;
|
|
|
|
|
2017-04-04 17:03:49 +00:00
|
|
|
bool IsRequired = isRequiredForExecution(Section) || ProcessAllSections;
|
2014-03-21 20:28:42 +00:00
|
|
|
|
2014-02-12 21:30:07 +00:00
|
|
|
// Consider only the sections that are required to be loaded for execution
|
|
|
|
if (IsRequired) {
|
2014-10-08 15:28:58 +00:00
|
|
|
uint64_t DataSize = Section.getSize();
|
2022-12-01 14:50:29 +00:00
|
|
|
Align Alignment = Section.getAlignment();
|
2014-10-08 15:28:58 +00:00
|
|
|
bool IsCode = Section.isText();
|
2014-12-10 20:46:55 +00:00
|
|
|
bool IsReadOnly = isReadOnlyData(Section);
|
2021-08-27 15:51:58 +02:00
|
|
|
bool IsTLS = isTLS(Section);
|
2016-04-27 20:24:48 +00:00
|
|
|
|
2019-08-14 11:10:11 +00:00
|
|
|
Expected<StringRef> NameOrErr = Section.getName();
|
|
|
|
if (!NameOrErr)
|
|
|
|
return NameOrErr.takeError();
|
|
|
|
StringRef Name = *NameOrErr;
|
2014-03-21 20:28:42 +00:00
|
|
|
|
2014-02-12 21:30:07 +00:00
|
|
|
uint64_t StubBufSize = computeSectionStubBufSize(Obj, Section);
|
2019-05-30 20:58:28 +00:00
|
|
|
|
|
|
|
uint64_t PaddingSize = 0;
|
|
|
|
if (Name == ".eh_frame")
|
|
|
|
PaddingSize += 4;
|
|
|
|
if (StubBufSize != 0)
|
2022-12-01 14:50:29 +00:00
|
|
|
PaddingSize += getStubAlignment().value() - 1;
|
2019-05-30 20:58:28 +00:00
|
|
|
|
|
|
|
uint64_t SectionSize = DataSize + PaddingSize + StubBufSize;
|
2014-03-21 20:28:42 +00:00
|
|
|
|
|
|
|
// The .eh_frame section (at least on Linux) needs an extra four bytes
|
|
|
|
// padded
|
2014-02-12 21:30:07 +00:00
|
|
|
// with zeroes added at the end. For MachO objects, this section has a
|
2014-03-21 20:28:42 +00:00
|
|
|
// slightly different name, so this won't have any effect for MachO
|
|
|
|
// objects.
|
2014-02-12 21:30:07 +00:00
|
|
|
if (Name == ".eh_frame")
|
|
|
|
SectionSize += 4;
|
2014-03-21 20:28:42 +00:00
|
|
|
|
2015-04-07 06:27:56 +00:00
|
|
|
if (!SectionSize)
|
|
|
|
SectionSize = 1;
|
|
|
|
|
|
|
|
if (IsCode) {
|
2016-01-10 18:51:50 +00:00
|
|
|
CodeAlign = std::max(CodeAlign, Alignment);
|
2015-04-07 06:27:56 +00:00
|
|
|
CodeSectionSizes.push_back(SectionSize);
|
|
|
|
} else if (IsReadOnly) {
|
2016-01-10 18:51:50 +00:00
|
|
|
RODataAlign = std::max(RODataAlign, Alignment);
|
2015-04-07 06:27:56 +00:00
|
|
|
ROSectionSizes.push_back(SectionSize);
|
2021-08-27 15:51:58 +02:00
|
|
|
} else if (!IsTLS) {
|
2016-01-10 18:51:50 +00:00
|
|
|
RWDataAlign = std::max(RWDataAlign, Alignment);
|
2015-04-07 06:27:56 +00:00
|
|
|
RWSectionSizes.push_back(SectionSize);
|
|
|
|
}
|
2014-02-12 21:30:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-06 15:31:28 +00:00
|
|
|
// Compute Global Offset Table size. If it is not zero we
|
|
|
|
// also update alignment, which is equal to a size of a
|
|
|
|
// single GOT entry.
|
|
|
|
if (unsigned GotSize = computeGOTSize(Obj)) {
|
|
|
|
RWSectionSizes.push_back(GotSize);
|
2022-12-01 14:50:29 +00:00
|
|
|
RWDataAlign = std::max(RWDataAlign, Align(getGOTEntrySize()));
|
2017-02-06 15:31:28 +00:00
|
|
|
}
|
|
|
|
|
2014-02-12 21:30:07 +00:00
|
|
|
// Compute the size of all common symbols
|
|
|
|
uint64_t CommonSize = 0;
|
2022-12-01 14:50:29 +00:00
|
|
|
Align CommonAlign;
|
2014-11-26 16:54:40 +00:00
|
|
|
for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E;
|
2014-03-21 20:28:42 +00:00
|
|
|
++I) {
|
2020-04-10 20:24:21 +08:00
|
|
|
Expected<uint32_t> FlagsOrErr = I->getFlags();
|
|
|
|
if (!FlagsOrErr)
|
|
|
|
// TODO: Test this error.
|
|
|
|
return FlagsOrErr.takeError();
|
|
|
|
if (*FlagsOrErr & SymbolRef::SF_Common) {
|
2014-02-12 21:30:07 +00:00
|
|
|
// Add the common symbols to a list. We'll allocate them all below.
|
2015-06-24 10:20:30 +00:00
|
|
|
uint64_t Size = I->getCommonSize();
|
2022-12-01 14:50:29 +00:00
|
|
|
Align Alignment = Align(I->getAlignment());
|
2016-04-21 20:08:06 +00:00
|
|
|
// If this is the first common symbol, use its alignment as the alignment
|
|
|
|
// for the common symbols section.
|
|
|
|
if (CommonSize == 0)
|
2022-12-01 14:50:29 +00:00
|
|
|
CommonAlign = Alignment;
|
|
|
|
CommonSize = alignTo(CommonSize, Alignment) + Size;
|
2014-02-12 21:30:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (CommonSize != 0) {
|
|
|
|
RWSectionSizes.push_back(CommonSize);
|
2016-04-21 20:08:06 +00:00
|
|
|
RWDataAlign = std::max(RWDataAlign, CommonAlign);
|
2014-02-12 21:30:07 +00:00
|
|
|
}
|
|
|
|
|
2021-01-20 17:08:47 +01:00
|
|
|
if (!CodeSectionSizes.empty()) {
|
|
|
|
// Add 64 bytes for a potential IFunc resolver stub
|
|
|
|
CodeSectionSizes.push_back(64);
|
|
|
|
}
|
|
|
|
|
2014-03-21 20:28:42 +00: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-12 21:30:07 +00:00
|
|
|
// allocated with the max alignment. Note that we cannot compute with the
|
2014-03-21 20:28:42 +00:00
|
|
|
// individual alignments of the sections, because then the required size
|
2014-02-12 21:30:07 +00:00
|
|
|
// depends on the order, in which the sections are allocated.
|
2016-01-10 18:51:50 +00:00
|
|
|
CodeSize = computeAllocationSizeForSections(CodeSectionSizes, CodeAlign);
|
|
|
|
RODataSize = computeAllocationSizeForSections(ROSectionSizes, RODataAlign);
|
|
|
|
RWDataSize = computeAllocationSizeForSections(RWSectionSizes, RWDataAlign);
|
2016-04-27 20:24:48 +00:00
|
|
|
|
|
|
|
return Error::success();
|
2014-02-12 21:30:07 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 15:31:28 +00:00
|
|
|
// compute GOT size
|
|
|
|
unsigned RuntimeDyldImpl::computeGOTSize(const ObjectFile &Obj) {
|
|
|
|
size_t GotEntrySize = getGOTEntrySize();
|
|
|
|
if (!GotEntrySize)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
size_t GotSize = 0;
|
|
|
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
|
|
|
SI != SE; ++SI) {
|
|
|
|
|
|
|
|
for (const RelocationRef &Reloc : SI->relocations())
|
|
|
|
if (relocationNeedsGot(Reloc))
|
|
|
|
GotSize += GotEntrySize;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GotSize;
|
|
|
|
}
|
|
|
|
|
2014-02-12 21:30:07 +00:00
|
|
|
// compute stub buffer size for the given section
|
2014-11-26 16:54:40 +00:00
|
|
|
unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj,
|
2014-02-12 21:30:07 +00:00
|
|
|
const SectionRef &Section) {
|
2021-05-17 17:18:15 -07:00
|
|
|
if (!MemMgr.allowStubAllocation()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-02-12 21:30:07 +00:00
|
|
|
unsigned StubSize = getMaxStubSize();
|
|
|
|
if (StubSize == 0) {
|
2014-03-21 20:28:42 +00:00
|
|
|
return 0;
|
2014-02-12 21:30:07 +00: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 16:54:40 +00:00
|
|
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
2014-04-21 19:23:59 +00:00
|
|
|
SI != SE; ++SI) {
|
2019-10-21 11:06:38 +00:00
|
|
|
|
|
|
|
Expected<section_iterator> RelSecOrErr = SI->getRelocatedSection();
|
|
|
|
if (!RelSecOrErr)
|
2021-10-06 12:04:30 +01:00
|
|
|
report_fatal_error(Twine(toString(RelSecOrErr.takeError())));
|
2019-10-21 11:06:38 +00:00
|
|
|
|
|
|
|
section_iterator RelSecI = *RelSecOrErr;
|
2014-02-12 21:30:07 +00:00
|
|
|
if (!(RelSecI == Section))
|
|
|
|
continue;
|
|
|
|
|
2024-09-02 12:34:12 +01:00
|
|
|
for (const RelocationRef &Reloc : SI->relocations()) {
|
2015-11-23 21:47:51 +00:00
|
|
|
if (relocationNeedsStub(Reloc))
|
|
|
|
StubBufSize += StubSize;
|
2024-09-02 12:34:12 +01:00
|
|
|
if (relocationNeedsDLLImportStub(Reloc))
|
|
|
|
StubBufSize = sizeAfterAddingDLLImportStub(StubBufSize);
|
|
|
|
}
|
2014-02-12 21:30:07 +00:00
|
|
|
}
|
2014-03-14 14:22:49 +00:00
|
|
|
|
2014-02-12 21:30:07 +00:00
|
|
|
// Get section data size and alignment
|
2014-10-08 15:28:58 +00:00
|
|
|
uint64_t DataSize = Section.getSize();
|
2022-12-01 14:50:29 +00:00
|
|
|
Align Alignment = Section.getAlignment();
|
2014-02-12 21:30:07 +00:00
|
|
|
|
|
|
|
// Add stubbuf size alignment
|
2022-12-01 14:50:29 +00:00
|
|
|
Align StubAlignment = getStubAlignment();
|
|
|
|
Align EndAlignment = commonAlignment(Alignment, DataSize);
|
2014-02-12 21:30:07 +00:00
|
|
|
if (StubAlignment > EndAlignment)
|
2022-12-01 14:50:29 +00:00
|
|
|
StubBufSize += StubAlignment.value() - EndAlignment.value();
|
2014-02-12 21:30:07 +00:00
|
|
|
return StubBufSize;
|
2012-01-16 23:50:55 +00:00
|
|
|
}
|
|
|
|
|
2014-08-29 23:17:47 +00:00
|
|
|
uint64_t RuntimeDyldImpl::readBytesUnaligned(uint8_t *Src,
|
|
|
|
unsigned Size) const {
|
|
|
|
uint64_t Result = 0;
|
2014-09-07 02:05:26 +00:00
|
|
|
if (IsTargetLittleEndian) {
|
|
|
|
Src += Size - 1;
|
|
|
|
while (Size--)
|
|
|
|
Result = (Result << 8) | *Src--;
|
|
|
|
} else
|
|
|
|
while (Size--)
|
|
|
|
Result = (Result << 8) | *Src++;
|
2014-08-29 23:17:47 +00:00
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst,
|
|
|
|
unsigned Size) const {
|
2014-09-07 02:05:26 +00:00
|
|
|
if (IsTargetLittleEndian) {
|
|
|
|
while (Size--) {
|
|
|
|
*Dst++ = Value & 0xFF;
|
|
|
|
Value >>= 8;
|
|
|
|
}
|
2014-08-29 23:17:47 +00:00
|
|
|
} else {
|
2014-09-07 02:05:26 +00:00
|
|
|
Dst += Size - 1;
|
|
|
|
while (Size--) {
|
|
|
|
*Dst-- = Value & 0xFF;
|
|
|
|
Value >>= 8;
|
|
|
|
}
|
2014-08-29 23:17:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-01 22:42:23 +00:00
|
|
|
Expected<JITSymbolFlags>
|
|
|
|
RuntimeDyldImpl::getJITSymbolFlags(const SymbolRef &SR) {
|
2017-08-09 20:19:27 +00:00
|
|
|
return JITSymbolFlags::fromObjectSymbol(SR);
|
|
|
|
}
|
|
|
|
|
2016-04-27 20:24:48 +00:00
|
|
|
Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
|
2018-01-19 22:24:13 +00:00
|
|
|
CommonSymbolList &SymbolsToAllocate,
|
|
|
|
uint64_t CommonSize,
|
|
|
|
uint32_t CommonAlign) {
|
|
|
|
if (SymbolsToAllocate.empty())
|
2016-04-27 20:24:48 +00:00
|
|
|
return Error::success();
|
2015-01-17 00:55:05 +00:00
|
|
|
|
2012-04-12 20:13:57 +00:00
|
|
|
// Allocate memory for the section
|
|
|
|
unsigned SectionID = Sections.size();
|
2016-07-04 01:26:21 +00:00
|
|
|
uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, CommonAlign, SectionID,
|
|
|
|
"<common symbols>", false);
|
2012-04-12 20:13:57 +00:00
|
|
|
if (!Addr)
|
|
|
|
report_fatal_error("Unable to allocate memory for common symbols!");
|
|
|
|
uint64_t Offset = 0;
|
2015-11-23 21:47:46 +00:00
|
|
|
Sections.push_back(
|
|
|
|
SectionEntry("<common symbols>", Addr, CommonSize, CommonSize, 0));
|
2015-01-17 00:55:05 +00:00
|
|
|
memset(Addr, 0, CommonSize);
|
2012-04-12 20:13:57 +00:00
|
|
|
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID
|
|
|
|
<< " new addr: " << format("%p", Addr)
|
|
|
|
<< " DataSize: " << CommonSize << "\n");
|
2012-04-12 20:13:57 +00:00
|
|
|
|
|
|
|
// Assign the address of each symbol
|
2015-01-17 00:55:05 +00:00
|
|
|
for (auto &Sym : SymbolsToAllocate) {
|
2019-09-27 12:54:21 +00:00
|
|
|
uint32_t Alignment = Sym.getAlignment();
|
2015-06-24 10:20:30 +00:00
|
|
|
uint64_t Size = Sym.getCommonSize();
|
2016-04-27 20:24:48 +00:00
|
|
|
StringRef Name;
|
|
|
|
if (auto NameOrErr = Sym.getName())
|
|
|
|
Name = *NameOrErr;
|
|
|
|
else
|
|
|
|
return NameOrErr.takeError();
|
2019-09-27 12:54:21 +00:00
|
|
|
if (Alignment) {
|
2012-10-29 10:47:04 +00:00
|
|
|
// This symbol has an alignment requirement.
|
[Alignment] Move OffsetToAlignment to Alignment.h
Summary:
This is patch is part of a series to introduce an Alignment type.
See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html
See this patch for the introduction of the type: https://reviews.llvm.org/D64790
Reviewers: courbet, JDevlieghere, alexshap, rupprecht, jhenderson
Subscribers: sdardis, nemanjai, hiraditya, kbarton, jakehehrlich, jrtc27, MaskRay, atanasyan, jsji, seiya, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D67499
llvm-svn: 371742
2019-09-12 15:20:36 +00:00
|
|
|
uint64_t AlignOffset =
|
2019-09-27 12:54:21 +00:00
|
|
|
offsetToAlignment((uint64_t)Addr, Align(Alignment));
|
2012-10-29 10:47:04 +00:00
|
|
|
Addr += AlignOffset;
|
|
|
|
Offset += AlignOffset;
|
|
|
|
}
|
2018-08-01 22:42:23 +00:00
|
|
|
auto JITSymFlags = getJITSymbolFlags(Sym);
|
|
|
|
|
|
|
|
if (!JITSymFlags)
|
|
|
|
return JITSymFlags.takeError();
|
|
|
|
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "Allocating common symbol " << Name << " address "
|
|
|
|
<< format("%p", Addr) << "\n");
|
2020-11-06 14:08:30 -05:00
|
|
|
if (!Name.empty()) // Skip absolute symbol relocations.
|
|
|
|
GlobalSymbolTable[Name] =
|
|
|
|
SymbolTableEntry(SectionID, Offset, std::move(*JITSymFlags));
|
2012-04-12 20:13:57 +00:00
|
|
|
Offset += Size;
|
|
|
|
Addr += Size;
|
|
|
|
}
|
2015-08-13 15:12:49 +00:00
|
|
|
|
2016-04-27 20:24:48 +00:00
|
|
|
return Error::success();
|
|
|
|
}
|
2012-03-30 16:45:19 +00:00
|
|
|
|
2016-04-27 20:24:48 +00:00
|
|
|
Expected<unsigned>
|
|
|
|
RuntimeDyldImpl::emitSection(const ObjectFile &Obj,
|
|
|
|
const SectionRef &Section,
|
|
|
|
bool IsCode) {
|
2012-03-30 16:45:19 +00:00
|
|
|
StringRef data;
|
2022-12-01 14:50:29 +00:00
|
|
|
Align Alignment = Section.getAlignment();
|
2012-03-30 16:45:19 +00:00
|
|
|
|
2013-10-16 00:32:24 +00:00
|
|
|
unsigned PaddingSize = 0;
|
2014-02-12 21:30:07 +00:00
|
|
|
unsigned StubBufSize = 0;
|
2017-05-17 08:47:28 +00:00
|
|
|
bool IsRequired = isRequiredForExecution(Section);
|
2014-10-08 15:28:58 +00:00
|
|
|
bool IsVirtual = Section.isVirtual();
|
2014-12-10 20:46:55 +00:00
|
|
|
bool IsZeroInit = isZeroInit(Section);
|
|
|
|
bool IsReadOnly = isReadOnlyData(Section);
|
2021-08-27 15:51:58 +02:00
|
|
|
bool IsTLS = isTLS(Section);
|
2014-10-08 15:28:58 +00:00
|
|
|
uint64_t DataSize = Section.getSize();
|
2016-04-27 20:24:48 +00:00
|
|
|
|
2019-08-14 11:10:11 +00:00
|
|
|
Expected<StringRef> NameOrErr = Section.getName();
|
|
|
|
if (!NameOrErr)
|
|
|
|
return NameOrErr.takeError();
|
|
|
|
StringRef Name = *NameOrErr;
|
2014-03-21 20:28:42 +00:00
|
|
|
|
|
|
|
StubBufSize = computeSectionStubBufSize(Obj, Section);
|
2012-04-12 20:13:57 +00:00
|
|
|
|
2013-10-16 00:32:24 +00: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 05:28:24 +00:00
|
|
|
uintptr_t Allocate;
|
2012-03-30 16:45:19 +00:00
|
|
|
unsigned SectionID = Sections.size();
|
2012-04-12 20:13:57 +00:00
|
|
|
uint8_t *Addr;
|
2021-08-27 15:51:58 +02:00
|
|
|
uint64_t LoadAddress = 0;
|
2014-04-24 06:44:33 +00:00
|
|
|
const char *pData = nullptr;
|
2012-04-12 20:13:57 +00:00
|
|
|
|
2015-10-15 06:41:45 +00:00
|
|
|
// If this section contains any bits (i.e. isn't a virtual or bss section),
|
|
|
|
// grab a reference to them.
|
|
|
|
if (!IsVirtual && !IsZeroInit) {
|
|
|
|
// In either case, set the location of the unrelocated section in memory,
|
|
|
|
// since we still process relocations for it even if we're not applying them.
|
2019-05-16 13:24:04 +00:00
|
|
|
if (Expected<StringRef> E = Section.getContents())
|
|
|
|
data = *E;
|
|
|
|
else
|
|
|
|
return E.takeError();
|
2015-05-01 20:21:45 +00:00
|
|
|
pData = data.data();
|
2015-10-15 06:41:45 +00:00
|
|
|
}
|
2015-05-01 20:21:45 +00:00
|
|
|
|
2019-05-30 19:59:20 +00:00
|
|
|
// If there are any stubs then the section alignment needs to be at least as
|
|
|
|
// high as stub alignment or padding calculations may by incorrect when the
|
|
|
|
// section is remapped.
|
|
|
|
if (StubBufSize != 0) {
|
2015-08-14 06:26:42 +00:00
|
|
|
Alignment = std::max(Alignment, getStubAlignment());
|
2022-12-01 14:50:29 +00:00
|
|
|
PaddingSize += getStubAlignment().value() - 1;
|
2017-08-09 20:19:27 +00:00
|
|
|
}
|
2015-08-14 06:26:42 +00:00
|
|
|
|
2012-04-12 20:13:57 +00:00
|
|
|
// Some sections, such as debug info, don't need to be loaded for execution.
|
2017-05-17 08:47:28 +00:00
|
|
|
// Process those only if explicitly requested.
|
|
|
|
if (IsRequired || ProcessAllSections) {
|
2013-10-16 00:32:24 +00:00
|
|
|
Allocate = DataSize + PaddingSize + StubBufSize;
|
2015-04-07 06:27:56 +00:00
|
|
|
if (!Allocate)
|
|
|
|
Allocate = 1;
|
2021-08-27 15:51:58 +02:00
|
|
|
if (IsTLS) {
|
2022-12-01 14:50:29 +00:00
|
|
|
auto TLSSection = MemMgr.allocateTLSSection(Allocate, Alignment.value(),
|
|
|
|
SectionID, Name);
|
2021-08-27 15:51:58 +02:00
|
|
|
Addr = TLSSection.InitializationImage;
|
|
|
|
LoadAddress = TLSSection.Offset;
|
|
|
|
} else if (IsCode) {
|
2022-12-01 14:50:29 +00:00
|
|
|
Addr = MemMgr.allocateCodeSection(Allocate, Alignment.value(), SectionID,
|
|
|
|
Name);
|
2021-08-27 15:51:58 +02:00
|
|
|
} else {
|
2022-12-01 14:50:29 +00:00
|
|
|
Addr = MemMgr.allocateDataSection(Allocate, Alignment.value(), SectionID,
|
|
|
|
Name, IsReadOnly);
|
2021-08-27 15:51:58 +02:00
|
|
|
}
|
2012-04-12 20:13:57 +00:00
|
|
|
if (!Addr)
|
|
|
|
report_fatal_error("Unable to allocate section memory!");
|
|
|
|
|
|
|
|
// Zero-initialize or copy the data from the image
|
|
|
|
if (IsZeroInit || IsVirtual)
|
|
|
|
memset(Addr, 0, DataSize);
|
|
|
|
else
|
|
|
|
memcpy(Addr, pData, DataSize);
|
|
|
|
|
2013-10-16 00:32:24 +00:00
|
|
|
// Fill in any extra bytes we allocated for padding
|
|
|
|
if (PaddingSize != 0) {
|
|
|
|
memset(Addr + DataSize, 0, PaddingSize);
|
2017-08-09 20:19:27 +00:00
|
|
|
// Update the DataSize variable to include padding.
|
2013-10-16 00:32:24 +00:00
|
|
|
DataSize += PaddingSize;
|
2017-08-09 20:19:27 +00:00
|
|
|
|
|
|
|
// Align DataSize to stub alignment if we have any stubs (PaddingSize will
|
|
|
|
// have been increased above to account for this).
|
|
|
|
if (StubBufSize > 0)
|
2022-12-01 14:50:29 +00:00
|
|
|
DataSize &= -(uint64_t)getStubAlignment().value();
|
2013-10-16 00:32:24 +00:00
|
|
|
}
|
|
|
|
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: "
|
|
|
|
<< Name << " obj addr: " << format("%p", pData)
|
|
|
|
<< " new addr: " << format("%p", Addr) << " DataSize: "
|
|
|
|
<< DataSize << " StubBufSize: " << StubBufSize
|
|
|
|
<< " Allocate: " << Allocate << "\n");
|
2014-03-21 20:28:42 +00:00
|
|
|
} else {
|
2012-04-12 20:13:57 +00:00
|
|
|
// Even if we didn't load the section, we need to record an entry for it
|
2012-04-29 12:40:47 +00:00
|
|
|
// to handle later processing (and by 'handle' I mean don't do anything
|
|
|
|
// with these sections).
|
2012-04-12 20:13:57 +00:00
|
|
|
Allocate = 0;
|
2014-04-24 06:44:33 +00:00
|
|
|
Addr = nullptr;
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_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-12 20:13:57 +00:00
|
|
|
}
|
|
|
|
|
2015-11-23 21:47:46 +00:00
|
|
|
Sections.push_back(
|
|
|
|
SectionEntry(Name, Addr, DataSize, Allocate, (uintptr_t)pData));
|
2014-09-03 05:01:46 +00:00
|
|
|
|
2021-08-27 15:51:58 +02:00
|
|
|
// The load address of a TLS section is not equal to the address of its
|
|
|
|
// initialization image
|
|
|
|
if (IsTLS)
|
|
|
|
Sections.back().setLoadAddress(LoadAddress);
|
2017-05-17 08:47:28 +00:00
|
|
|
// Debug info sections are linked as if their load address was zero
|
|
|
|
if (!IsRequired)
|
|
|
|
Sections.back().setLoadAddress(0);
|
|
|
|
|
2012-03-30 16:45:19 +00:00
|
|
|
return SectionID;
|
|
|
|
}
|
|
|
|
|
2016-04-27 20:24:48 +00:00
|
|
|
Expected<unsigned>
|
|
|
|
RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj,
|
|
|
|
const SectionRef &Section,
|
|
|
|
bool IsCode,
|
|
|
|
ObjSectionToIDMap &LocalSections) {
|
2012-03-30 16:45:19 +00:00
|
|
|
|
|
|
|
unsigned SectionID = 0;
|
|
|
|
ObjSectionToIDMap::iterator i = LocalSections.find(Section);
|
|
|
|
if (i != LocalSections.end())
|
|
|
|
SectionID = i->second;
|
|
|
|
else {
|
2016-04-27 20:24:48 +00:00
|
|
|
if (auto SectionIDOrErr = emitSection(Obj, Section, IsCode))
|
|
|
|
SectionID = *SectionIDOrErr;
|
|
|
|
else
|
|
|
|
return SectionIDOrErr.takeError();
|
2012-03-30 16:45:19 +00:00
|
|
|
LocalSections[Section] = SectionID;
|
|
|
|
}
|
|
|
|
return SectionID;
|
|
|
|
}
|
|
|
|
|
2012-05-01 10:41:12 +00:00
|
|
|
void RuntimeDyldImpl::addRelocationForSection(const RelocationEntry &RE,
|
|
|
|
unsigned SectionID) {
|
|
|
|
Relocations[SectionID].push_back(RE);
|
|
|
|
}
|
2012-03-30 16:45:19 +00:00
|
|
|
|
2012-05-01 10:41:12 +00: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.
|
2015-01-16 23:13:56 +00:00
|
|
|
RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(SymbolName);
|
2012-05-01 10:41:12 +00:00
|
|
|
if (Loc == GlobalSymbolTable.end()) {
|
|
|
|
ExternalSymbolRelocations[SymbolName].push_back(RE);
|
2012-04-30 12:15:58 +00:00
|
|
|
} else {
|
2020-11-06 14:08:30 -05:00
|
|
|
assert(!SymbolName.empty() &&
|
|
|
|
"Empty symbol should not be in GlobalSymbolTable");
|
2012-05-01 10:41:12 +00:00
|
|
|
// Copy the RE since we want to modify its addend.
|
|
|
|
RelocationEntry RECopy = RE;
|
2015-01-16 23:13:56 +00:00
|
|
|
const auto &SymInfo = Loc->second;
|
|
|
|
RECopy.Addend += SymInfo.getOffset();
|
|
|
|
Relocations[SymInfo.getSectionID()].push_back(RECopy);
|
2012-04-30 12:15:58 +00:00
|
|
|
}
|
2012-03-30 16:45:19 +00:00
|
|
|
}
|
|
|
|
|
2014-07-20 23:53:14 +00:00
|
|
|
uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
|
|
|
|
unsigned AbiVariant) {
|
2019-09-12 10:22:23 +00:00
|
|
|
if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be ||
|
|
|
|
Arch == Triple::aarch64_32) {
|
2013-05-04 20:14:09 +00: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 09:53:05 +00: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-04 20:14:09 +00:00
|
|
|
|
|
|
|
return Addr;
|
2014-03-28 14:35:30 +00:00
|
|
|
} else if (Arch == Triple::arm || Arch == Triple::armeb) {
|
2012-08-17 21:28:04 +00:00
|
|
|
// TODO: There is only ARM far stub now. We should add the Thumb stub,
|
|
|
|
// and stubs for branches Thumb - ARM and ARM - Thumb.
|
2017-08-09 20:19:27 +00:00
|
|
|
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc, [pc, #-4]
|
2014-11-06 09:53:05 +00:00
|
|
|
return Addr + 4;
|
2024-11-08 10:42:31 +08:00
|
|
|
} else if (Arch == Triple::loongarch64) {
|
|
|
|
// lu12i.w $t0, %abs_hi20(addr)
|
|
|
|
// ori $t0, $t0, %abs_lo12(addr)
|
|
|
|
// lu32i.d $t0, %abs64_lo20(addr)
|
|
|
|
// lu52i.d $t0, $t0, %abs64_lo12(addr)
|
|
|
|
// jr $t0
|
|
|
|
writeBytesUnaligned(0x1400000c, Addr, 4);
|
|
|
|
writeBytesUnaligned(0x0380018c, Addr + 4, 4);
|
|
|
|
writeBytesUnaligned(0x1600000c, Addr + 8, 4);
|
|
|
|
writeBytesUnaligned(0x0300018c, Addr + 12, 4);
|
|
|
|
writeBytesUnaligned(0x4c000180, Addr + 16, 4);
|
|
|
|
return Addr;
|
2017-10-22 09:47:41 +00:00
|
|
|
} else if (IsMipsO32ABI || IsMipsN32ABI) {
|
2012-08-17 21:28:04 +00: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;
|
2016-07-15 12:56:37 +00:00
|
|
|
const unsigned NopInstr = 0x0;
|
|
|
|
unsigned JrT9Instr = 0x03200008;
|
2017-10-22 09:47:41 +00:00
|
|
|
if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_32R6 ||
|
|
|
|
(AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_64R6)
|
|
|
|
JrT9Instr = 0x03200009;
|
2012-08-17 21:28:04 +00:00
|
|
|
|
2014-11-06 09:53:05 +00:00
|
|
|
writeBytesUnaligned(LuiT9Instr, Addr, 4);
|
2017-10-22 09:47:41 +00:00
|
|
|
writeBytesUnaligned(AdduiT9Instr, Addr + 4, 4);
|
|
|
|
writeBytesUnaligned(JrT9Instr, Addr + 8, 4);
|
|
|
|
writeBytesUnaligned(NopInstr, Addr + 12, 4);
|
|
|
|
return Addr;
|
|
|
|
} else if (IsMipsN64ABI) {
|
|
|
|
// 0: 3c190000 lui t9,%highest(addr).
|
|
|
|
// 4: 67390000 daddiu t9,t9,%higher(addr).
|
|
|
|
// 8: 0019CC38 dsll t9,t9,16.
|
|
|
|
// c: 67390000 daddiu t9,t9,%hi(addr).
|
|
|
|
// 10: 0019CC38 dsll t9,t9,16.
|
|
|
|
// 14: 67390000 daddiu t9,t9,%lo(addr).
|
|
|
|
// 18: 03200008 jr t9.
|
|
|
|
// 1c: 00000000 nop.
|
|
|
|
const unsigned LuiT9Instr = 0x3c190000, DaddiuT9Instr = 0x67390000,
|
|
|
|
DsllT9Instr = 0x19CC38;
|
|
|
|
const unsigned NopInstr = 0x0;
|
|
|
|
unsigned JrT9Instr = 0x03200008;
|
|
|
|
if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_64R6)
|
|
|
|
JrT9Instr = 0x03200009;
|
|
|
|
|
|
|
|
writeBytesUnaligned(LuiT9Instr, Addr, 4);
|
|
|
|
writeBytesUnaligned(DaddiuT9Instr, Addr + 4, 4);
|
|
|
|
writeBytesUnaligned(DsllT9Instr, Addr + 8, 4);
|
|
|
|
writeBytesUnaligned(DaddiuT9Instr, Addr + 12, 4);
|
|
|
|
writeBytesUnaligned(DsllT9Instr, Addr + 16, 4);
|
|
|
|
writeBytesUnaligned(DaddiuT9Instr, Addr + 20, 4);
|
|
|
|
writeBytesUnaligned(JrT9Instr, Addr + 24, 4);
|
|
|
|
writeBytesUnaligned(NopInstr, Addr + 28, 4);
|
2012-10-25 13:13:48 +00:00
|
|
|
return Addr;
|
2013-07-26 01:35:43 +00:00
|
|
|
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
|
2014-07-20 23:53:14 +00: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 13:13:48 +00: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-20 23:53:14 +00: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 14:15:35 +00: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-30 16:45:19 +00:00
|
|
|
return Addr;
|
2013-08-19 23:27:43 +00: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-12 21:39:59 +00:00
|
|
|
} else if (Arch == Triple::x86) {
|
|
|
|
*Addr = 0xE9; // 32-bit pc-relative jump.
|
2012-08-17 21:28:04 +00:00
|
|
|
}
|
|
|
|
return Addr;
|
2012-03-30 16:45:19 +00: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-05 20:57:16 +00: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-30 16:45:19 +00: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.
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(
|
|
|
|
dbgs() << "Reassigning address for section " << SectionID << " ("
|
|
|
|
<< Sections[SectionID].getName() << "): "
|
|
|
|
<< format("0x%016" PRIx64, Sections[SectionID].getLoadAddress())
|
|
|
|
<< " -> " << format("0x%016" PRIx64, Addr) << "\n");
|
2015-11-23 21:47:41 +00:00
|
|
|
Sections[SectionID].setLoadAddress(Addr);
|
2012-03-30 16:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
|
|
|
|
uint64_t Value) {
|
2024-07-10 16:11:07 +09:00
|
|
|
for (const RelocationEntry &RE : Relocs) {
|
2013-04-29 17:24:34 +00:00
|
|
|
// Ignore relocations for sections that were not loaded
|
2020-10-30 11:35:12 +01:00
|
|
|
if (RE.SectionID != AbsoluteSymbolSection &&
|
|
|
|
Sections[RE.SectionID].getAddress() == nullptr)
|
2013-04-29 17:24:34 +00:00
|
|
|
continue;
|
|
|
|
resolveRelocation(RE, Value);
|
2012-03-30 16:45:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-25 19:48:46 +00:00
|
|
|
void RuntimeDyldImpl::applyExternalSymbolRelocations(
|
|
|
|
const StringMap<JITEvaluatedSymbol> ExternalSymbolMap) {
|
2021-03-11 16:49:12 -08:00
|
|
|
for (auto &RelocKV : ExternalSymbolRelocations) {
|
|
|
|
StringRef Name = RelocKV.first();
|
|
|
|
RelocationList &Relocs = RelocKV.second;
|
2013-10-01 01:47:35 +00:00
|
|
|
if (Name.size() == 0) {
|
|
|
|
// This is an absolute symbol, use an address of zero.
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "Resolving absolute relocations."
|
|
|
|
<< "\n");
|
2013-10-01 01:47:35 +00:00
|
|
|
resolveRelocationList(Relocs, 0);
|
|
|
|
} else {
|
|
|
|
uint64_t Addr = 0;
|
2017-08-09 20:19:27 +00:00
|
|
|
JITSymbolFlags Flags;
|
2015-01-16 23:13:56 +00:00
|
|
|
RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name);
|
2013-10-01 01:47:35 +00:00
|
|
|
if (Loc == GlobalSymbolTable.end()) {
|
2018-01-19 22:24:13 +00:00
|
|
|
auto RRI = ExternalSymbolMap.find(Name);
|
|
|
|
assert(RRI != ExternalSymbolMap.end() && "No result for symbol");
|
|
|
|
Addr = RRI->second.getAddress();
|
|
|
|
Flags = RRI->second.getFlags();
|
2013-02-20 18:24:34 +00:00
|
|
|
} else {
|
2013-10-01 01:47:35 +00:00
|
|
|
// We found the symbol in our global table. It was probably in a
|
|
|
|
// Module that we loaded previously.
|
2015-01-16 23:13:56 +00:00
|
|
|
const auto &SymInfo = Loc->second;
|
|
|
|
Addr = getSectionLoadAddress(SymInfo.getSectionID()) +
|
|
|
|
SymInfo.getOffset();
|
2017-08-09 20:19:27 +00:00
|
|
|
Flags = SymInfo.getFlags();
|
2013-02-20 18:09:21 +00:00
|
|
|
}
|
2013-10-01 01:47:35 +00:00
|
|
|
|
|
|
|
// FIXME: Implement error handling that doesn't kill the host program!
|
2021-05-17 17:18:15 -07:00
|
|
|
if (!Addr && !Resolver.allowsZeroSymbols())
|
2021-10-06 12:04:30 +01:00
|
|
|
report_fatal_error(Twine("Program used external function '") + Name +
|
2014-03-21 20:28:42 +00:00
|
|
|
"' which could not be resolved!");
|
2013-10-01 01:47:35 +00:00
|
|
|
|
2015-07-04 01:35:26 +00:00
|
|
|
// If Resolver returned UINT64_MAX, the client wants to handle this symbol
|
|
|
|
// manually and we shouldn't resolve its relocations.
|
|
|
|
if (Addr != UINT64_MAX) {
|
2017-08-09 20:19:27 +00:00
|
|
|
|
|
|
|
// Tweak the address based on the symbol flags if necessary.
|
|
|
|
// For example, this is used by RuntimeDyldMachOARM to toggle the low bit
|
|
|
|
// if the target symbol is Thumb.
|
|
|
|
Addr = modifyAddressBasedOnFlags(Addr, Flags);
|
|
|
|
|
2018-05-14 12:53:11 +00:00
|
|
|
LLVM_DEBUG(dbgs() << "Resolving relocations Name: " << Name << "\t"
|
|
|
|
<< format("0x%lx", Addr) << "\n");
|
2015-07-04 01:35:26 +00:00
|
|
|
resolveRelocationList(Relocs, Addr);
|
|
|
|
}
|
2012-03-30 16:45:19 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-11 16:49:12 -08:00
|
|
|
ExternalSymbolRelocations.clear();
|
2018-09-25 19:48:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Error RuntimeDyldImpl::resolveExternalSymbols() {
|
|
|
|
StringMap<JITEvaluatedSymbol> ExternalSymbolMap;
|
|
|
|
|
|
|
|
// Resolution can trigger emission of more symbols, so iterate until
|
|
|
|
// we've resolved *everything*.
|
|
|
|
{
|
|
|
|
JITSymbolResolver::LookupSet ResolvedSymbols;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
JITSymbolResolver::LookupSet NewSymbols;
|
|
|
|
|
|
|
|
for (auto &RelocKV : ExternalSymbolRelocations) {
|
|
|
|
StringRef Name = RelocKV.first();
|
|
|
|
if (!Name.empty() && !GlobalSymbolTable.count(Name) &&
|
|
|
|
!ResolvedSymbols.count(Name))
|
|
|
|
NewSymbols.insert(Name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NewSymbols.empty())
|
|
|
|
break;
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
using ExpectedLookupResult =
|
2018-09-25 20:48:57 +00:00
|
|
|
MSVCPExpected<JITSymbolResolver::LookupResult>;
|
2018-09-25 19:48:46 +00:00
|
|
|
#else
|
|
|
|
using ExpectedLookupResult = Expected<JITSymbolResolver::LookupResult>;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
auto NewSymbolsP = std::make_shared<std::promise<ExpectedLookupResult>>();
|
|
|
|
auto NewSymbolsF = NewSymbolsP->get_future();
|
|
|
|
Resolver.lookup(NewSymbols,
|
|
|
|
[=](Expected<JITSymbolResolver::LookupResult> Result) {
|
|
|
|
NewSymbolsP->set_value(std::move(Result));
|
|
|
|
});
|
|
|
|
|
|
|
|
auto NewResolverResults = NewSymbolsF.get();
|
|
|
|
|
|
|
|
if (!NewResolverResults)
|
|
|
|
return NewResolverResults.takeError();
|
|
|
|
|
|
|
|
assert(NewResolverResults->size() == NewSymbols.size() &&
|
|
|
|
"Should have errored on unresolved symbols");
|
|
|
|
|
|
|
|
for (auto &RRKV : *NewResolverResults) {
|
|
|
|
assert(!ResolvedSymbols.count(RRKV.first) && "Redundant resolution?");
|
|
|
|
ExternalSymbolMap.insert(RRKV);
|
|
|
|
ResolvedSymbols.insert(RRKV.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
applyExternalSymbolRelocations(ExternalSymbolMap);
|
2017-07-07 02:59:13 +00:00
|
|
|
|
|
|
|
return Error::success();
|
2012-03-30 16:45:19 +00:00
|
|
|
}
|
|
|
|
|
2018-09-25 22:57:44 +00:00
|
|
|
void RuntimeDyldImpl::finalizeAsync(
|
2019-09-13 11:35:33 +00:00
|
|
|
std::unique_ptr<RuntimeDyldImpl> This,
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
unique_function<void(object::OwningBinary<object::ObjectFile>,
|
|
|
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)>
|
2020-03-19 16:14:18 -07:00
|
|
|
OnEmitted,
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
object::OwningBinary<object::ObjectFile> O,
|
|
|
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info) {
|
2018-09-25 22:57:44 +00:00
|
|
|
|
|
|
|
auto SharedThis = std::shared_ptr<RuntimeDyldImpl>(std::move(This));
|
|
|
|
auto PostResolveContinuation =
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
[SharedThis, OnEmitted = std::move(OnEmitted), O = std::move(O),
|
|
|
|
Info = std::move(Info)](
|
2019-09-13 11:35:33 +00:00
|
|
|
Expected<JITSymbolResolver::LookupResult> Result) mutable {
|
2018-09-25 22:57:44 +00:00
|
|
|
if (!Result) {
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
OnEmitted(std::move(O), std::move(Info), Result.takeError());
|
2018-09-25 22:57:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Copy the result into a StringMap, where the keys are held by value.
|
|
|
|
StringMap<JITEvaluatedSymbol> Resolved;
|
|
|
|
for (auto &KV : *Result)
|
|
|
|
Resolved[KV.first] = KV.second;
|
|
|
|
|
|
|
|
SharedThis->applyExternalSymbolRelocations(Resolved);
|
|
|
|
SharedThis->resolveLocalRelocations();
|
|
|
|
SharedThis->registerEHFrames();
|
|
|
|
std::string ErrMsg;
|
|
|
|
if (SharedThis->MemMgr.finalizeMemory(&ErrMsg))
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
OnEmitted(std::move(O), std::move(Info),
|
2020-03-19 16:14:18 -07:00
|
|
|
make_error<StringError>(std::move(ErrMsg),
|
2018-09-25 22:57:44 +00:00
|
|
|
inconvertibleErrorCode()));
|
|
|
|
else
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
OnEmitted(std::move(O), std::move(Info), Error::success());
|
2018-09-25 22:57:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
JITSymbolResolver::LookupSet Symbols;
|
|
|
|
|
|
|
|
for (auto &RelocKV : SharedThis->ExternalSymbolRelocations) {
|
|
|
|
StringRef Name = RelocKV.first();
|
2020-11-06 14:08:30 -05:00
|
|
|
if (Name.empty()) // Skip absolute symbol relocations.
|
|
|
|
continue;
|
2018-09-25 22:57:44 +00:00
|
|
|
assert(!SharedThis->GlobalSymbolTable.count(Name) &&
|
|
|
|
"Name already processed. RuntimeDyld instances can not be re-used "
|
|
|
|
"when finalizing with finalizeAsync.");
|
|
|
|
Symbols.insert(Name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Symbols.empty()) {
|
2019-09-13 11:35:33 +00:00
|
|
|
SharedThis->Resolver.lookup(Symbols, std::move(PostResolveContinuation));
|
2018-09-25 22:57:44 +00:00
|
|
|
} else
|
|
|
|
PostResolveContinuation(std::map<StringRef, JITEvaluatedSymbol>());
|
|
|
|
}
|
|
|
|
|
2011-03-21 22:15:52 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RuntimeDyld class implementation
|
2014-11-26 16:54:40 +00:00
|
|
|
|
|
|
|
uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress(
|
2015-07-28 17:52:11 +00:00
|
|
|
const object::SectionRef &Sec) const {
|
|
|
|
|
|
|
|
auto I = ObjSecToIDMap.find(Sec);
|
2015-11-23 21:47:41 +00:00
|
|
|
if (I != ObjSecToIDMap.end())
|
|
|
|
return RTDyld.Sections[I->second].getLoadAddress();
|
2014-11-26 16:54:40 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-08-27 15:51:58 +02:00
|
|
|
RuntimeDyld::MemoryManager::TLSSection
|
|
|
|
RuntimeDyld::MemoryManager::allocateTLSSection(uintptr_t Size,
|
|
|
|
unsigned Alignment,
|
|
|
|
unsigned SectionID,
|
|
|
|
StringRef SectionName) {
|
|
|
|
report_fatal_error("allocation of TLS not implemented");
|
|
|
|
}
|
|
|
|
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 03:37:06 +00:00
|
|
|
void RuntimeDyld::MemoryManager::anchor() {}
|
2016-08-01 20:49:11 +00:00
|
|
|
void JITSymbolResolver::anchor() {}
|
2018-01-19 22:24:13 +00:00
|
|
|
void LegacyJITSymbolResolver::anchor() {}
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 03:37:06 +00:00
|
|
|
|
|
|
|
RuntimeDyld::RuntimeDyld(RuntimeDyld::MemoryManager &MemMgr,
|
2016-08-01 20:49:11 +00:00
|
|
|
JITSymbolResolver &Resolver)
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 03:37:06 +00:00
|
|
|
: MemMgr(MemMgr), Resolver(Resolver) {
|
2012-11-15 23:50:01 +00: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 06:44:33 +00:00
|
|
|
Dyld = nullptr;
|
2014-03-20 21:06:46 +00:00
|
|
|
ProcessAllSections = false;
|
2011-03-21 22:15:52 +00:00
|
|
|
}
|
|
|
|
|
2022-02-06 22:18:35 -08:00
|
|
|
RuntimeDyld::~RuntimeDyld() = default;
|
2011-03-21 22:15:52 +00:00
|
|
|
|
2015-03-07 20:21:27 +00:00
|
|
|
static std::unique_ptr<RuntimeDyldCOFF>
|
2019-04-08 21:50:48 +00:00
|
|
|
createRuntimeDyldCOFF(
|
|
|
|
Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
|
|
|
|
JITSymbolResolver &Resolver, bool ProcessAllSections,
|
|
|
|
RuntimeDyld::NotifyStubEmittedFunction NotifyStubEmitted) {
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 03:37:06 +00:00
|
|
|
std::unique_ptr<RuntimeDyldCOFF> Dyld =
|
|
|
|
RuntimeDyldCOFF::create(Arch, MM, Resolver);
|
2015-03-07 20:21:27 +00:00
|
|
|
Dyld->setProcessAllSections(ProcessAllSections);
|
2019-04-08 21:50:48 +00:00
|
|
|
Dyld->setNotifyStubEmitted(std::move(NotifyStubEmitted));
|
2015-03-07 20:21:27 +00:00
|
|
|
return Dyld;
|
|
|
|
}
|
|
|
|
|
2014-03-21 20:28:42 +00:00
|
|
|
static std::unique_ptr<RuntimeDyldELF>
|
2016-12-13 11:39:18 +00:00
|
|
|
createRuntimeDyldELF(Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
|
2016-08-01 20:49:11 +00:00
|
|
|
JITSymbolResolver &Resolver, bool ProcessAllSections,
|
2019-04-08 21:50:48 +00:00
|
|
|
RuntimeDyld::NotifyStubEmittedFunction NotifyStubEmitted) {
|
2016-12-13 11:39:18 +00:00
|
|
|
std::unique_ptr<RuntimeDyldELF> Dyld =
|
|
|
|
RuntimeDyldELF::create(Arch, MM, Resolver);
|
2014-03-20 21:06:46 +00:00
|
|
|
Dyld->setProcessAllSections(ProcessAllSections);
|
2019-04-08 21:50:48 +00:00
|
|
|
Dyld->setNotifyStubEmitted(std::move(NotifyStubEmitted));
|
2014-03-20 21:06:46 +00:00
|
|
|
return Dyld;
|
|
|
|
}
|
|
|
|
|
2014-03-21 20:28:42 +00:00
|
|
|
static std::unique_ptr<RuntimeDyldMachO>
|
2019-04-08 21:50:48 +00:00
|
|
|
createRuntimeDyldMachO(
|
|
|
|
Triple::ArchType Arch, RuntimeDyld::MemoryManager &MM,
|
|
|
|
JITSymbolResolver &Resolver,
|
|
|
|
bool ProcessAllSections,
|
|
|
|
RuntimeDyld::NotifyStubEmittedFunction NotifyStubEmitted) {
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 03:37:06 +00:00
|
|
|
std::unique_ptr<RuntimeDyldMachO> Dyld =
|
|
|
|
RuntimeDyldMachO::create(Arch, MM, Resolver);
|
2014-03-20 21:06:46 +00:00
|
|
|
Dyld->setProcessAllSections(ProcessAllSections);
|
2019-04-08 21:50:48 +00:00
|
|
|
Dyld->setNotifyStubEmitted(std::move(NotifyStubEmitted));
|
2014-03-20 21:06:46 +00:00
|
|
|
return Dyld;
|
|
|
|
}
|
|
|
|
|
2014-11-26 16:54:40 +00:00
|
|
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
|
|
|
|
RuntimeDyld::loadObject(const ObjectFile &Obj) {
|
|
|
|
if (!Dyld) {
|
|
|
|
if (Obj.isELF())
|
2016-12-13 11:39:18 +00:00
|
|
|
Dyld =
|
|
|
|
createRuntimeDyldELF(static_cast<Triple::ArchType>(Obj.getArch()),
|
2019-04-08 21:50:48 +00:00
|
|
|
MemMgr, Resolver, ProcessAllSections,
|
|
|
|
std::move(NotifyStubEmitted));
|
2014-11-26 16:54:40 +00:00
|
|
|
else if (Obj.isMachO())
|
2014-07-17 18:54:50 +00:00
|
|
|
Dyld = createRuntimeDyldMachO(
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 03:37:06 +00:00
|
|
|
static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver,
|
2019-04-08 21:50:48 +00:00
|
|
|
ProcessAllSections, std::move(NotifyStubEmitted));
|
2015-03-07 20:21:27 +00:00
|
|
|
else if (Obj.isCOFF())
|
|
|
|
Dyld = createRuntimeDyldCOFF(
|
[MCJIT][Orc] Refactor RTDyldMemoryManager, weave RuntimeDyld::SymbolInfo through
MCJIT.
This patch decouples the two responsibilities of the RTDyldMemoryManager class,
memory management and symbol resolution, into two new classes:
RuntimeDyld::MemoryManager and RuntimeDyld::SymbolResolver.
The symbol resolution interface is modified slightly, from:
uint64_t getSymbolAddress(const std::string &Name);
to:
RuntimeDyld::SymbolInfo findSymbol(const std::string &Name);
The latter passes symbol flags along with symbol addresses, allowing RuntimeDyld
and others to reason about non-strong/non-exported symbols.
The memory management interface removes the following method:
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &) {}
as it is not related to memory management. (Note: Backwards compatibility *is*
maintained for this method in MCJIT and OrcMCJITReplacement, see below).
The RTDyldMemoryManager class remains in-tree for backwards compatibility.
It inherits directly from RuntimeDyld::SymbolResolver, and indirectly from
RuntimeDyld::MemoryManager via the new MCJITMemoryManager class, which
just subclasses RuntimeDyld::MemoryManager and reintroduces the
notifyObjectLoaded method for backwards compatibility).
The EngineBuilder class retains the existing method:
EngineBuilder&
setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
and includes two new methods:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
Clients should use EITHER:
A single call to setMCJITMemoryManager with an RTDyldMemoryManager.
OR (exclusive)
One call each to each of setMemoryManager and setSymbolResolver.
This patch should be fully compatible with existing uses of RTDyldMemoryManager.
If it is not it should be considered a bug, and the patch either fixed or
reverted.
If clients find the new API to be an improvement the goal will be to deprecate
and eventually remove the RTDyldMemoryManager class in favor of the new classes.
llvm-svn: 233509
2015-03-30 03:37:06 +00:00
|
|
|
static_cast<Triple::ArchType>(Obj.getArch()), MemMgr, Resolver,
|
2019-04-08 21:50:48 +00:00
|
|
|
ProcessAllSections, std::move(NotifyStubEmitted));
|
2014-11-26 16:54:40 +00:00
|
|
|
else
|
|
|
|
report_fatal_error("Incompatible object format!");
|
2011-07-13 07:57:58 +00:00
|
|
|
}
|
|
|
|
|
2014-11-26 16:54:40 +00:00
|
|
|
if (!Dyld->isCompatibleFile(Obj))
|
2014-03-08 18:45:12 +00:00
|
|
|
report_fatal_error("Incompatible object format!");
|
|
|
|
|
2016-01-10 23:59:41 +00:00
|
|
|
auto LoadedObjInfo = Dyld->loadObject(Obj);
|
|
|
|
MemMgr.notifyObjectLoaded(*this, Obj);
|
|
|
|
return LoadedObjInfo;
|
2011-03-21 22:15:52 +00:00
|
|
|
}
|
|
|
|
|
2015-03-11 00:43:26 +00:00
|
|
|
void *RuntimeDyld::getSymbolLocalAddress(StringRef Name) const {
|
2013-10-01 01:47:35 +00:00
|
|
|
if (!Dyld)
|
2014-04-24 06:44:33 +00:00
|
|
|
return nullptr;
|
2015-03-11 00:43:26 +00:00
|
|
|
return Dyld->getSymbolLocalAddress(Name);
|
2011-03-21 22:15:52 +00:00
|
|
|
}
|
|
|
|
|
2019-04-08 21:50:48 +00:00
|
|
|
unsigned RuntimeDyld::getSymbolSectionID(StringRef Name) const {
|
|
|
|
assert(Dyld && "No RuntimeDyld instance attached");
|
|
|
|
return Dyld->getSymbolSectionID(Name);
|
|
|
|
}
|
|
|
|
|
2016-08-01 20:49:11 +00:00
|
|
|
JITEvaluatedSymbol RuntimeDyld::getSymbol(StringRef Name) const {
|
2013-10-01 01:47:35 +00:00
|
|
|
if (!Dyld)
|
2015-03-11 00:43:26 +00:00
|
|
|
return nullptr;
|
|
|
|
return Dyld->getSymbol(Name);
|
2015-01-16 23:13:56 +00:00
|
|
|
}
|
|
|
|
|
2018-03-14 06:25:07 +00:00
|
|
|
std::map<StringRef, JITEvaluatedSymbol> RuntimeDyld::getSymbolTable() const {
|
|
|
|
if (!Dyld)
|
2018-03-14 06:39:49 +00:00
|
|
|
return std::map<StringRef, JITEvaluatedSymbol>();
|
2018-03-14 06:25:07 +00:00
|
|
|
return Dyld->getSymbolTable();
|
|
|
|
}
|
|
|
|
|
2014-03-21 20:28:42 +00: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-12 21:20:41 +00:00
|
|
|
|
2014-03-21 20:28:42 +00:00
|
|
|
void RuntimeDyld::reassignSectionAddress(unsigned SectionID, uint64_t Addr) {
|
2012-01-16 22:26:39 +00: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-12 21:20:41 +00:00
|
|
|
}
|
|
|
|
|
2012-09-13 21:50:06 +00:00
|
|
|
void RuntimeDyld::mapSectionAddress(const void *LocalAddress,
|
2012-01-16 23:50:55 +00:00
|
|
|
uint64_t TargetAddress) {
|
|
|
|
Dyld->mapSectionAddress(LocalAddress, TargetAddress);
|
|
|
|
}
|
|
|
|
|
2014-03-26 18:19:27 +00:00
|
|
|
bool RuntimeDyld::hasError() { return Dyld->hasError(); }
|
|
|
|
|
2014-03-21 20:28:42 +00:00
|
|
|
StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); }
|
2011-03-22 18:19:42 +00:00
|
|
|
|
2016-01-09 19:50:40 +00:00
|
|
|
void RuntimeDyld::finalizeWithMemoryManagerLocking() {
|
|
|
|
bool MemoryFinalizationLocked = MemMgr.FinalizationLocked;
|
|
|
|
MemMgr.FinalizationLocked = true;
|
|
|
|
resolveRelocations();
|
|
|
|
registerEHFrames();
|
|
|
|
if (!MemoryFinalizationLocked) {
|
|
|
|
MemMgr.finalizeMemory();
|
|
|
|
MemMgr.FinalizationLocked = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-08 21:50:48 +00:00
|
|
|
StringRef RuntimeDyld::getSectionContent(unsigned SectionID) const {
|
|
|
|
assert(Dyld && "No Dyld instance attached");
|
|
|
|
return Dyld->getSectionContent(SectionID);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t RuntimeDyld::getSectionLoadAddress(unsigned SectionID) const {
|
|
|
|
assert(Dyld && "No Dyld instance attached");
|
|
|
|
return Dyld->getSectionLoadAddress(SectionID);
|
|
|
|
}
|
|
|
|
|
2013-10-11 21:25:48 +00:00
|
|
|
void RuntimeDyld::registerEHFrames() {
|
2013-10-16 00:14:21 +00:00
|
|
|
if (Dyld)
|
|
|
|
Dyld->registerEHFrames();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RuntimeDyld::deregisterEHFrames() {
|
|
|
|
if (Dyld)
|
|
|
|
Dyld->deregisterEHFrames();
|
2013-05-05 20:43:10 +00:00
|
|
|
}
|
2018-09-25 22:57:44 +00:00
|
|
|
// FIXME: Kill this with fire once we have a new JIT linker: this is only here
|
|
|
|
// so that we can re-use RuntimeDyld's implementation without twisting the
|
|
|
|
// interface any further for ORC's purposes.
|
2020-03-19 16:14:18 -07:00
|
|
|
void jitLinkForORC(
|
|
|
|
object::OwningBinary<object::ObjectFile> O,
|
|
|
|
RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver,
|
|
|
|
bool ProcessAllSections,
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
unique_function<Error(const object::ObjectFile &Obj,
|
|
|
|
RuntimeDyld::LoadedObjectInfo &LoadedObj,
|
|
|
|
std::map<StringRef, JITEvaluatedSymbol>)>
|
2020-03-19 16:14:18 -07:00
|
|
|
OnLoaded,
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
unique_function<void(object::OwningBinary<object::ObjectFile>,
|
|
|
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)>
|
2020-03-19 16:14:18 -07:00
|
|
|
OnEmitted) {
|
2018-09-25 22:57:44 +00:00
|
|
|
|
|
|
|
RuntimeDyld RTDyld(MemMgr, Resolver);
|
|
|
|
RTDyld.setProcessAllSections(ProcessAllSections);
|
|
|
|
|
2020-03-19 16:14:18 -07:00
|
|
|
auto Info = RTDyld.loadObject(*O.getBinary());
|
2018-09-25 22:57:44 +00:00
|
|
|
|
|
|
|
if (RTDyld.hasError()) {
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
OnEmitted(std::move(O), std::move(Info),
|
|
|
|
make_error<StringError>(RTDyld.getErrorString(),
|
|
|
|
inconvertibleErrorCode()));
|
2018-09-25 22:57:44 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-04 11:06:48 +02:00
|
|
|
if (auto Err = OnLoaded(*O.getBinary(), *Info, RTDyld.getSymbolTable())) {
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
OnEmitted(std::move(O), std::move(Info), std::move(Err));
|
2024-07-04 11:06:48 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-09-25 22:57:44 +00:00
|
|
|
|
|
|
|
RuntimeDyldImpl::finalizeAsync(std::move(RTDyld.Dyld), std::move(OnEmitted),
|
[ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.
Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.
Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.
Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.
RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.
The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).
This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-09-11 09:50:41 -07:00
|
|
|
std::move(O), std::move(Info));
|
2018-09-25 22:57:44 +00:00
|
|
|
}
|
2013-05-05 20:43:10 +00:00
|
|
|
|
2011-03-21 22:15:52 +00:00
|
|
|
} // end namespace llvm
|