From 08671757e40d6c8844b2cf9d1a31487cf24c823f Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Wed, 9 Aug 2017 20:19:27 +0000 Subject: [PATCH] [RuntimeDyld][ORC] Add support for Thumb mode to RuntimeDyldMachOARM. This patch adds support for thumb relocations to RuntimeDyldMachOARM, and adds a target-specific flags field to JITSymbolFlags (so that on ARM we can record whether each symbol is Thumb-mode code). RuntimeDyldImpl::emitSection is modified to ensure that stubs memory is correctly aligned based on the size returned by getStubAlignment(). llvm-svn: 310517 --- include/llvm/ExecutionEngine/JITSymbol.h | 30 ++++ lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp | 8 + .../RuntimeDyld/RuntimeDyld.cpp | 40 +++-- .../RuntimeDyld/RuntimeDyldImpl.h | 38 ++++- .../RuntimeDyld/RuntimeDyldMachO.cpp | 4 +- .../RuntimeDyld/RuntimeDyldMachO.h | 3 +- .../RuntimeDyld/Targets/RuntimeDyldMachOARM.h | 144 +++++++++++++++--- .../RuntimeDyld/ARM/MachO_Thumb_Relocations.s | 51 +++++++ 8 files changed, 282 insertions(+), 36 deletions(-) create mode 100644 test/ExecutionEngine/RuntimeDyld/ARM/MachO_Thumb_Relocations.s diff --git a/include/llvm/ExecutionEngine/JITSymbol.h b/include/llvm/ExecutionEngine/JITSymbol.h index 4172f240ba3..5e661401eb6 100644 --- a/include/llvm/ExecutionEngine/JITSymbol.h +++ b/include/llvm/ExecutionEngine/JITSymbol.h @@ -40,6 +40,7 @@ using JITTargetAddress = uint64_t; class JITSymbolFlags { public: using UnderlyingType = uint8_t; + using TargetFlagsType = uint64_t; enum FlagNames : UnderlyingType { None = 0, @@ -56,6 +57,11 @@ public: /// @brief Construct a JITSymbolFlags instance from the given flags. JITSymbolFlags(FlagNames Flags) : Flags(Flags) {} + /// @brief Construct a JITSymbolFlags instance from the given flags and target + /// flags. + JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags) + : Flags(Flags), TargetFlags(TargetFlags) {} + /// @brief Return true if there was an error retrieving this symbol. bool hasError() const { return (Flags & HasError) == HasError; @@ -80,8 +86,12 @@ public: return (Flags & Exported) == Exported; } + /// @brief Implicitly convert to the underlying flags type. operator UnderlyingType&() { return Flags; } + /// @brief Return a reference to the target-specific flags. + TargetFlagsType& getTargetFlags() { return TargetFlags; } + /// Construct a JITSymbolFlags value based on the flags of the given global /// value. static JITSymbolFlags fromGlobalValue(const GlobalValue &GV); @@ -92,6 +102,26 @@ public: private: UnderlyingType Flags = None; + TargetFlagsType TargetFlags = 0; +}; + +/// @brief ARM-specific JIT symbol flags. +/// FIXME: This should be moved into a target-specific header. +class ARMJITSymbolFlags { +public: + ARMJITSymbolFlags() = default; + + enum FlagNames { + None = 0, + Thumb = 1 << 0 + }; + + operator JITSymbolFlags::TargetFlagsType&() { return Flags; } + + static ARMJITSymbolFlags fromObjectSymbol( + const object::BasicSymbolRef &Symbol); +private: + JITSymbolFlags::TargetFlagsType Flags = 0; }; /// @brief Represents a symbol that has been evaluated to an address already. diff --git a/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp b/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp index 8769dcf7374..87059ef2b88 100644 --- a/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp @@ -39,3 +39,11 @@ llvm::JITSymbolFlags::fromObjectSymbol(const object::BasicSymbolRef &Symbol) { Flags |= JITSymbolFlags::Exported; return Flags; } + +ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol( + const object::BasicSymbolRef &Symbol) { + ARMJITSymbolFlags Flags; + if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb) + Flags |= ARMJITSymbolFlags::Thumb; + return Flags; +} diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 8198836f7a0..4d1d74cf34a 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -233,7 +233,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { return NameOrErr.takeError(); // Compute JIT symbol flags. - JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(*I); + JITSymbolFlags JITSymFlags = getJITSymbolFlags(*I); // 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 @@ -616,6 +616,10 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst, } } +JITSymbolFlags RuntimeDyldImpl::getJITSymbolFlags(const BasicSymbolRef &SR) { + return JITSymbolFlags::fromObjectSymbol(SR); +} + Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, CommonSymbolList &CommonSymbols) { if (CommonSymbols.empty()) @@ -685,7 +689,7 @@ Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, Addr += AlignOffset; Offset += AlignOffset; } - JITSymbolFlags JITSymFlags = JITSymbolFlags::fromObjectSymbol(Sym); + JITSymbolFlags JITSymFlags = getJITSymbolFlags(Sym); DEBUG(dbgs() << "Allocating common symbol " << Name << " address " << format("%p", Addr) << "\n"); GlobalSymbolTable[Name] = @@ -746,8 +750,11 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj, // Code section alignment needs to be at least as high as stub alignment or // padding calculations may by incorrect when the section is remapped to a // higher alignment. - if (IsCode) + if (IsCode) { Alignment = std::max(Alignment, getStubAlignment()); + if (StubBufSize > 0) + PaddingSize += getStubAlignment() - 1; + } // Some sections, such as debug info, don't need to be loaded for execution. // Process those only if explicitly requested. @@ -771,8 +778,13 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj, // Fill in any extra bytes we allocated for padding if (PaddingSize != 0) { memset(Addr + DataSize, 0, PaddingSize); - // Update the DataSize variable so that the stub offset is set correctly. + // Update the DataSize variable to include padding. DataSize += PaddingSize; + + // Align DataSize to stub alignment if we have any stubs (PaddingSize will + // have been increased above to account for this). + if (StubBufSize > 0) + DataSize &= ~(getStubAlignment() - 1); } DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name @@ -864,7 +876,7 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr, } else if (Arch == Triple::arm || Arch == Triple::armeb) { // TODO: There is only ARM far stub now. We should add the Thumb stub, // and stubs for branches Thumb - ARM and ARM - Thumb. - writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,