about summary refs log tree commit diff
path: root/compiler/rustc_llvm/llvm-wrapper
diff options
context:
space:
mode:
authorTrevor Gross <t.gross35@gmail.com>2024-07-16 16:15:13 -0500
committerGitHub <noreply@github.com>2024-07-16 16:15:13 -0500
commit63f239c89f661dc1e1157ab730e71197e55a12f0 (patch)
tree7b2cacb34ecee93b12e2bb1c23a84cbe1c988b25 /compiler/rustc_llvm/llvm-wrapper
parent16b569057e4d1591b4bee05f10df34000308dedc (diff)
parentcd3f2f68c042e2957fff85ca89ba10cb0f2f12b3 (diff)
downloadrust-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.cpp136
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;
+}