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.
This commit is contained in:
commit
63f239c89f
8 changed files with 209 additions and 98 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue