diff options
Diffstat (limited to 'contrib/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp | 74 |
1 files changed, 62 insertions, 12 deletions
diff --git a/contrib/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/contrib/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp index f02d8981b30e..21339a3f8f3d 100644 --- a/contrib/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/contrib/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -24,6 +24,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Object/SymbolSize.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DynamicLibrary.h" @@ -33,7 +34,6 @@ #include "llvm/Support/Memory.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" @@ -206,6 +206,9 @@ public: uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) override; + TrivialMemoryManager::TLSSection + allocateTLSSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, + StringRef SectionName) override; /// If non null, records subsequent Name -> SectionID mappings. void setSectionIDsMap(SectionIDMap *SecIDMap) { @@ -252,7 +255,8 @@ public: sys::Memory::MF_WRITE, EC); if (!MB.base()) - report_fatal_error("Can't allocate enough memory: " + EC.message()); + report_fatal_error(Twine("Can't allocate enough memory: ") + + EC.message()); PreallocSlab = MB; UsePreallocation = true; @@ -282,6 +286,9 @@ private: uintptr_t SlabSize = 0; uintptr_t CurrentSlabOffset = 0; SectionIDMap *SecIDMap = nullptr; +#if defined(__x86_64__) && defined(__ELF__) + unsigned UsedTLSStorage = 0; +#endif }; uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, @@ -306,7 +313,8 @@ uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, sys::Memory::MF_WRITE, EC); if (!MB.base()) - report_fatal_error("MemoryManager allocation failed: " + EC.message()); + report_fatal_error(Twine("MemoryManager allocation failed: ") + + EC.message()); FunctionMemory.push_back(SectionInfo(SectionName, MB, SectionID)); return (uint8_t*)MB.base(); } @@ -334,11 +342,52 @@ uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, sys::Memory::MF_WRITE, EC); if (!MB.base()) - report_fatal_error("MemoryManager allocation failed: " + EC.message()); + report_fatal_error(Twine("MemoryManager allocation failed: ") + + EC.message()); DataMemory.push_back(SectionInfo(SectionName, MB, SectionID)); return (uint8_t*)MB.base(); } +// In case the execution needs TLS storage, we define a very small TLS memory +// area here that will be used in allocateTLSSection(). +#if defined(__x86_64__) && defined(__ELF__) +extern "C" { +alignas(16) __attribute__((visibility("hidden"), tls_model("initial-exec"), + used)) thread_local char LLVMRTDyldTLSSpace[16]; +} +#endif + +TrivialMemoryManager::TLSSection +TrivialMemoryManager::allocateTLSSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) { +#if defined(__x86_64__) && defined(__ELF__) + if (Size + UsedTLSStorage > sizeof(LLVMRTDyldTLSSpace)) { + return {}; + } + + // Get the offset of the TLSSpace in the TLS block by using a tpoff + // relocation here. + int64_t TLSOffset; + asm("leaq LLVMRTDyldTLSSpace@tpoff, %0" : "=r"(TLSOffset)); + + TLSSection Section; + // We use the storage directly as the initialization image. This means that + // when a new thread is spawned after this allocation, it will not be + // initialized correctly. This means, llvm-rtdyld will only support TLS in a + // single thread. + Section.InitializationImage = + reinterpret_cast<uint8_t *>(LLVMRTDyldTLSSpace + UsedTLSStorage); + Section.Offset = TLSOffset + UsedTLSStorage; + + UsedTLSStorage += Size; + + return Section; +#else + return {}; +#endif +} + static const char *ProgramName; static void ErrorAndExit(const Twine &Msg) { @@ -349,10 +398,10 @@ static void ErrorAndExit(const Twine &Msg) { static void loadDylibs() { for (const std::string &Dylib : Dylibs) { if (!sys::fs::is_regular_file(Dylib)) - report_fatal_error("Dylib not found: '" + Dylib + "'."); + report_fatal_error(Twine("Dylib not found: '") + Dylib + "'."); std::string ErrMsg; if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg)) - report_fatal_error("Error loading '" + Dylib + "': " + ErrMsg); + report_fatal_error(Twine("Error loading '") + Dylib + "': " + ErrMsg); } } @@ -413,8 +462,9 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) { } } - std::unique_ptr<DIContext> Context = - DWARFContext::create(*SymbolObj, LoadedObjInfo.get()); + std::unique_ptr<DIContext> Context = DWARFContext::create( + *SymbolObj, DWARFContext::ProcessDebugRelocations::Process, + LoadedObjInfo.get()); std::vector<std::pair<SymbolRef, uint64_t>> SymAddr = object::computeSymbolSizes(*SymbolObj); @@ -710,15 +760,15 @@ static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple, size_t EqualsIdx = Mapping.find_first_of('='); if (EqualsIdx == StringRef::npos) - report_fatal_error("Invalid dummy symbol specification '" + Mapping + - "'. Should be '<symbol name>=<addr>'"); + report_fatal_error(Twine("Invalid dummy symbol specification '") + + Mapping + "'. Should be '<symbol name>=<addr>'"); std::string Symbol = Mapping.substr(0, EqualsIdx); std::string AddrStr = Mapping.substr(EqualsIdx + 1); uint64_t Addr; if (StringRef(AddrStr).getAsInteger(0, Addr)) - report_fatal_error("Invalid symbol mapping '" + Mapping + "'."); + report_fatal_error(Twine("Invalid symbol mapping '") + Mapping + "'."); MemMgr.addDummySymbol(Symbol, Addr); } @@ -974,7 +1024,7 @@ int main(int argc, char **argv) { Timers = ShowTimes ? std::make_unique<RTDyldTimers>() : nullptr; - int Result; + int Result = 0; switch (Action) { case AC_Execute: Result = executeInput(); |