diff options
| author | Trevor Gross <t.gross35@gmail.com> | 2024-07-16 16:15:13 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-16 16:15:13 -0500 |
| commit | 63f239c89f661dc1e1157ab730e71197e55a12f0 (patch) | |
| tree | 7b2cacb34ecee93b12e2bb1c23a84cbe1c988b25 /compiler/rustc_llvm/llvm-wrapper | |
| parent | 16b569057e4d1591b4bee05f10df34000308dedc (diff) | |
| parent | cd3f2f68c042e2957fff85ca89ba10cb0f2f12b3 (diff) | |
| download | rust-63f239c89f661dc1e1157ab730e71197e55a12f0.tar.gz rust-63f239c89f661dc1e1157ab730e71197e55a12f0.zip | |
Rollup merge of #124033 - bjorn3:ar_archive_writer_0_3_0, r=davidtwco
Sync ar_archive_writer to LLVM 18.1.3 From LLVM 15.0.0-rc3. This adds support for COFF archives containing Arm64EC object files and has various fixes for AIX big archive files.
Diffstat (limited to 'compiler/rustc_llvm/llvm-wrapper')
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp | 136 |
1 files changed, 105 insertions, 31 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index a9d1362a338..ccf1a5429e2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -4,12 +4,16 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // Derived from: -// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h -// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp +// * https://github.com/llvm/llvm-project/blob/ef6d1ec07c693352c4a60dd58db08d2d8558f6ea/llvm/include/llvm/Object/ArchiveWriter.h +// * https://github.com/llvm/llvm-project/blob/ef6d1ec07c693352c4a60dd58db08d2d8558f6ea/llvm/lib/Object/ArchiveWriter.cpp +#include "LLVMWrapper.h" #include "SuppressLLVMWarnings.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/COFFImportFile.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ObjectFile.h" #include <llvm/Support/raw_ostream.h> @@ -34,6 +38,27 @@ static bool isArchiveSymbol(const object::BasicSymbolRef &S) { typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *); typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *); +// This function is copied from ArchiveWriter.cpp. +static Expected<std::unique_ptr<SymbolicFile>> +getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) { + const file_magic Type = identify_magic(Buf.getBuffer()); + // Don't attempt to read non-symbolic file types. + if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) + return nullptr; + if (Type == file_magic::bitcode) { + auto ObjOrErr = object::SymbolicFile::createSymbolicFile( + Buf, file_magic::bitcode, &Context); + if (!ObjOrErr) + return ObjOrErr.takeError(); + return std::move(*ObjOrErr); + } else { + auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf); + if (!ObjOrErr) + return ObjOrErr.takeError(); + return std::move(*ObjOrErr); + } +} + // Note: This is implemented in C++ instead of using the C api from Rust as // IRObjectFile doesn't implement getSymbolName, only printSymbolName, which is // inaccessible from the C api. @@ -49,36 +74,16 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State, // In the scenario when LLVMContext is populated SymbolicFile will contain a // reference to it, thus SymbolicFile should be destroyed first. LLVMContext Context; - std::unique_ptr<object::SymbolicFile> Obj; - - const file_magic Type = identify_magic(Buf->getBuffer()); - if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) { - return 0; - } - - if (Type == file_magic::bitcode) { - auto ObjOrErr = object::SymbolicFile::createSymbolicFile( - Buf->getMemBufferRef(), file_magic::bitcode, &Context); - if (!ObjOrErr) { - Error E = ObjOrErr.takeError(); - SmallString<0> ErrorBuf; - auto Error = raw_svector_ostream(ErrorBuf); - Error << E << '\0'; - return ErrorCallback(Error.str().data()); - } - Obj = std::move(*ObjOrErr); - } else { - auto ObjOrErr = - object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef()); - if (!ObjOrErr) { - Error E = ObjOrErr.takeError(); - SmallString<0> ErrorBuf; - auto Error = raw_svector_ostream(ErrorBuf); - Error << E << '\0'; - return ErrorCallback(Error.str().data()); - } - Obj = std::move(*ObjOrErr); + Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr = + getSymbolicFile(Buf->getMemBufferRef(), Context); + if (!ObjOrErr) { + Error E = ObjOrErr.takeError(); + SmallString<0> ErrorBuf; + auto Error = raw_svector_ostream(ErrorBuf); + Error << E << '\0'; + return ErrorCallback(Error.str().data()); } + std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); for (const object::BasicSymbolRef &S : Obj->symbols()) { if (!isArchiveSymbol(S)) @@ -97,3 +102,72 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State, } return 0; } + +// Encoding true and false as invalid pointer values +#define TRUE_PTR (void *)1 +#define FALSE_PTR (void *)0 + +extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) { + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer( + StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); + SmallString<0> SymNameBuf; + auto SymName = raw_svector_ostream(SymNameBuf); + + // Code starting from this line is copied from s64BitSymbolicFile in + // ArchiveWriter.cpp. + // In the scenario when LLVMContext is populated SymbolicFile will contain a + // reference to it, thus SymbolicFile should be destroyed first. + LLVMContext Context; + Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr = + getSymbolicFile(Buf->getMemBufferRef(), Context); + if (!ObjOrErr) { + return false; + } + std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); + + return Obj != nullptr ? Obj->is64Bit() : false; +} + +extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) { + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer( + StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); + SmallString<0> SymNameBuf; + auto SymName = raw_svector_ostream(SymNameBuf); + + // In the scenario when LLVMContext is populated SymbolicFile will contain a + // reference to it, thus SymbolicFile should be destroyed first. + LLVMContext Context; + Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr = + getSymbolicFile(Buf->getMemBufferRef(), Context); + if (!ObjOrErr) { + return false; + } + std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); + + if (Obj == nullptr) { + return false; + } + + // Code starting from this line is copied from isECObject in + // ArchiveWriter.cpp with an extra #if to work with LLVM 17. + if (Obj->isCOFF()) + return cast<llvm::object::COFFObjectFile>(&*Obj)->getMachine() != + COFF::IMAGE_FILE_MACHINE_ARM64; + +#if LLVM_VERSION_GE(18, 0) + if (Obj->isCOFFImportFile()) + return cast<llvm::object::COFFImportFile>(&*Obj)->getMachine() != + COFF::IMAGE_FILE_MACHINE_ARM64; +#endif + + if (Obj->isIR()) { + Expected<std::string> TripleStr = + getBitcodeTargetTriple(Obj->getMemoryBufferRef()); + if (!TripleStr) + return false; + Triple T(*TripleStr); + return T.isWindowsArm64EC() || T.getArch() == Triple::x86_64; + } + + return false; +} |
