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
6 changed files with 84 additions and 58 deletions
+3 -3
View File
@@ -158,11 +158,11 @@ checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
[[package]] [[package]]
name = "ar_archive_writer" name = "ar_archive_writer"
version = "0.4.2" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4" checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b"
dependencies = [ dependencies = [
"object 0.36.7", "object 0.37.3",
] ]
[[package]] [[package]]
@@ -26,6 +26,7 @@ fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder +
get_symbols: get_llvm_object_symbols, get_symbols: get_llvm_object_symbols,
is_64_bit_object_file: llvm_is_64_bit_object_file, is_64_bit_object_file: llvm_is_64_bit_object_file,
is_ec_object_file: llvm_is_ec_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, 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 { fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) } 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()) }
}
@@ -2686,6 +2686,8 @@ pub(crate) fn LLVMRustGetSymbols(
pub(crate) fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool; 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 LLVMRustSetNoSanitizeAddress(Global: &Value);
pub(crate) fn LLVMRustSetNoSanitizeHWAddress(Global: &Value); pub(crate) fn LLVMRustSetNoSanitizeHWAddress(Global: &Value);
} }
+1 -1
View File
@@ -5,7 +5,7 @@ edition = "2024"
[dependencies] [dependencies]
# tidy-alphabetical-start # tidy-alphabetical-start
ar_archive_writer = "0.4.2" ar_archive_writer = "0.5"
bitflags.workspace = true bitflags.workspace = true
bstr = "1.11.3" bstr = "1.11.3"
# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version # `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version
+14 -10
View File
@@ -40,16 +40,18 @@ pub struct ImportLibraryItem {
pub is_data: bool, pub is_data: bool,
} }
impl From<ImportLibraryItem> for COFFShortExport { impl ImportLibraryItem {
fn from(item: ImportLibraryItem) -> Self { fn into_coff_short_export(self, sess: &Session) -> COFFShortExport {
let import_name = (sess.target.arch == "arm64ec").then(|| self.name.clone());
COFFShortExport { COFFShortExport {
name: item.name, name: self.name,
ext_name: None, ext_name: None,
symbol_name: item.symbol_name, symbol_name: self.symbol_name,
alias_target: None, import_name,
ordinal: item.ordinal.unwrap_or(0), export_as: None,
noname: item.ordinal.is_some(), ordinal: self.ordinal.unwrap_or(0),
data: item.is_data, noname: self.ordinal.is_some(),
data: self.is_data,
private: false, private: false,
constant: false, constant: false,
} }
@@ -113,7 +115,8 @@ fn create_dll_import_lib(
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }), .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 { let machine = match &*sess.target.arch {
"x86_64" => MachineTypes::AMD64, "x86_64" => MachineTypes::AMD64,
"x86" => MachineTypes::I386, "x86" => MachineTypes::I386,
@@ -134,6 +137,7 @@ fn create_dll_import_lib(
// when linking a rust staticlib using `/WHOLEARCHIVE`. // when linking a rust staticlib using `/WHOLEARCHIVE`.
// See #129020 // See #129020
true, true,
&[],
) { ) {
sess.dcx() sess.dcx()
.emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }); .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() });
@@ -527,7 +531,7 @@ fn build_inner(self, output: &Path) -> io::Result<bool> {
&entries, &entries,
archive_kind, archive_kind,
false, false,
/* is_ec = */ self.sess.target.arch == "arm64ec", /* is_ec = */ Some(self.sess.target.arch == "arm64ec"),
)?; )?;
archive_tmpfile.flush()?; archive_tmpfile.flush()?;
drop(archive_tmpfile); drop(archive_tmpfile);
@@ -103,28 +103,9 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State,
#define TRUE_PTR (void *)1 #define TRUE_PTR (void *)1
#define FALSE_PTR (void *)0 #define FALSE_PTR (void *)0
extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) { bool withBufferAsSymbolicFile(
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer( char *BufPtr, size_t BufLen,
StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); std::function<bool(object::SymbolicFile &)> Callback) {
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( std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(
StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false);
SmallString<0> SymNameBuf; SmallString<0> SymNameBuf;
@@ -139,29 +120,63 @@ extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) {
return false; return false;
} }
std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);
if (Obj == nullptr) { if (Obj == nullptr) {
return false; return false;
} }
return Callback(*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()) extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) {
return cast<llvm::object::COFFObjectFile>(&*Obj)->getMachine() != return withBufferAsSymbolicFile(
COFF::IMAGE_FILE_MACHINE_ARM64; BufPtr, BufLen, [](object::SymbolicFile &Obj) { return Obj.is64Bit(); });
}
if (Obj->isCOFFImportFile())
return cast<llvm::object::COFFImportFile>(&*Obj)->getMachine() != extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) {
COFF::IMAGE_FILE_MACHINE_ARM64; return withBufferAsSymbolicFile(
BufPtr, BufLen, [](object::SymbolicFile &Obj) {
if (Obj->isIR()) { // Code starting from this line is copied from isECObject in
Expected<std::string> TripleStr = // ArchiveWriter.cpp with an extra #if to work with LLVM 17.
getBitcodeTargetTriple(Obj->getMemoryBufferRef()); if (Obj.isCOFF())
if (!TripleStr) return cast<llvm::object::COFFObjectFile>(&Obj)->getMachine() !=
return false; COFF::IMAGE_FILE_MACHINE_ARM64;
Triple T(*TripleStr);
return T.isWindowsArm64EC() || T.getArch() == Triple::x86_64; if (Obj.isCOFFImportFile())
} return cast<llvm::object::COFFImportFile>(&Obj)->getMachine() !=
COFF::IMAGE_FILE_MACHINE_ARM64;
return false;
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;
});
} }