Auto merge of #145721 - dpaoliello:ar050, r=bjorn3

Update to ar_archive_writer 0.5

This updates `ar_archive_writer` to 0.5, which in turn was updated to match LLVM 20.1.8: <https://github.com/rust-lang/ar_archive_writer/pull/24>

As part of this, I refactored part of `SymbolWrapper.cpp` to pull common code that I was about to duplicate again into a new function.

NOTE: `ar_archive_writer` does include a breaking change where it no longer supports mangling C++ mangled names for Arm64EC. Since we don't need the mangled name (it's not the "exported name" which we're trying to load from the external dll), I'm setting the `import_name` when building for Arm64EC to prevent error when failing to mangle.

r? `@bjorn3`
This commit is contained in:
bors 2025-09-01 17:50:01 +00:00
commit 7aef4bec4b
6 changed files with 84 additions and 58 deletions

View file

@ -158,11 +158,11 @@ checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
[[package]]
name = "ar_archive_writer"
version = "0.4.2"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4"
checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b"
dependencies = [
"object 0.36.7",
"object 0.37.3",
]
[[package]]

View file

@ -26,6 +26,7 @@ static LLVM_OBJECT_READER: ObjectReader = ObjectReader {
get_symbols: get_llvm_object_symbols,
is_64_bit_object_file: llvm_is_64_bit_object_file,
is_ec_object_file: llvm_is_ec_object_file,
is_any_arm64_coff: llvm_is_any_arm64_coff,
get_xcoff_member_alignment: DEFAULT_OBJECT_READER.get_xcoff_member_alignment,
};
@ -95,3 +96,7 @@ fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
}
fn llvm_is_any_arm64_coff(buf: &[u8]) -> bool {
unsafe { llvm::LLVMRustIsAnyArm64Coff(buf.as_ptr(), buf.len()) }
}

View file

@ -2686,6 +2686,8 @@ unsafe extern "C" {
pub(crate) fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
pub(crate) fn LLVMRustIsAnyArm64Coff(buf_ptr: *const u8, buf_len: usize) -> bool;
pub(crate) fn LLVMRustSetNoSanitizeAddress(Global: &Value);
pub(crate) fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
}

View file

@ -5,7 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
ar_archive_writer = "0.4.2"
ar_archive_writer = "0.5"
bitflags.workspace = true
bstr = "1.11.3"
# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version

View file

@ -40,16 +40,18 @@ pub struct ImportLibraryItem {
pub is_data: bool,
}
impl From<ImportLibraryItem> for COFFShortExport {
fn from(item: ImportLibraryItem) -> Self {
impl ImportLibraryItem {
fn into_coff_short_export(self, sess: &Session) -> COFFShortExport {
let import_name = (sess.target.arch == "arm64ec").then(|| self.name.clone());
COFFShortExport {
name: item.name,
name: self.name,
ext_name: None,
symbol_name: item.symbol_name,
alias_target: None,
ordinal: item.ordinal.unwrap_or(0),
noname: item.ordinal.is_some(),
data: item.is_data,
symbol_name: self.symbol_name,
import_name,
export_as: None,
ordinal: self.ordinal.unwrap_or(0),
noname: self.ordinal.is_some(),
data: self.is_data,
private: false,
constant: false,
}
@ -113,7 +115,8 @@ pub trait ArchiveBuilderBuilder {
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }),
};
let exports = items.into_iter().map(Into::into).collect::<Vec<_>>();
let exports =
items.into_iter().map(|item| item.into_coff_short_export(sess)).collect::<Vec<_>>();
let machine = match &*sess.target.arch {
"x86_64" => MachineTypes::AMD64,
"x86" => MachineTypes::I386,
@ -134,6 +137,7 @@ pub trait ArchiveBuilderBuilder {
// when linking a rust staticlib using `/WHOLEARCHIVE`.
// See #129020
true,
&[],
) {
sess.dcx()
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() });
@ -527,7 +531,7 @@ impl<'a> ArArchiveBuilder<'a> {
&entries,
archive_kind,
false,
/* is_ec = */ self.sess.target.arch == "arm64ec",
/* is_ec = */ Some(self.sess.target.arch == "arm64ec"),
)?;
archive_tmpfile.flush()?;
drop(archive_tmpfile);

View file

@ -103,28 +103,9 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State,
#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) {
bool withBufferAsSymbolicFile(
char *BufPtr, size_t BufLen,
std::function<bool(object::SymbolicFile &)> Callback) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(
StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false);
SmallString<0> SymNameBuf;
@ -139,29 +120,63 @@ extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) {
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 (Obj->isCOFFImportFile())
return cast<llvm::object::COFFImportFile>(&*Obj)->getMachine() !=
COFF::IMAGE_FILE_MACHINE_ARM64;
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;
return Callback(*Obj);
}
extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) {
return withBufferAsSymbolicFile(
BufPtr, BufLen, [](object::SymbolicFile &Obj) { return Obj.is64Bit(); });
}
extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) {
return withBufferAsSymbolicFile(
BufPtr, BufLen, [](object::SymbolicFile &Obj) {
// 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 (Obj.isCOFFImportFile())
return cast<llvm::object::COFFImportFile>(&Obj)->getMachine() !=
COFF::IMAGE_FILE_MACHINE_ARM64;
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;
});
}
extern "C" bool LLVMRustIsAnyArm64Coff(char *BufPtr, size_t BufLen) {
return withBufferAsSymbolicFile(
BufPtr, BufLen, [](object::SymbolicFile &Obj) {
// Code starting from this line is copied from isAnyArm64COFF in
// ArchiveWriter.cpp.
if (Obj.isCOFF())
return COFF::isAnyArm64(cast<COFFObjectFile>(&Obj)->getMachine());
if (Obj.isCOFFImportFile())
return COFF::isAnyArm64(cast<COFFImportFile>(&Obj)->getMachine());
if (Obj.isIR()) {
Expected<std::string> TripleStr =
getBitcodeTargetTriple(Obj.getMemoryBufferRef());
if (!TripleStr)
return false;
Triple T(*TripleStr);
return T.isOSWindows() && T.getArch() == Triple::aarch64;
}
return false;
});
}