Skip to content

Commit

Permalink
Auto merge of rust-lang#128936 - bjorn3:fix_thin_archive_reading, r=<…
Browse files Browse the repository at this point in the history
…try>

Support reading thin archives in ArArchiveBuilder

And switch to using ArArchiveBuilder with the LLVM backend too now that all regressions are fixed.

Fixes rust-lang#107407
Fixes rust-lang#107162
rust-lang#107495 has been fixed in a previous PR already.

try-job: dist-aarch64-msvc
  • Loading branch information
bors committed Aug 14, 2024
2 parents 355a307 + 9de0d14 commit adcf44d
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 29 deletions.
30 changes: 5 additions & 25 deletions compiler/rustc_codegen_llvm/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,11 @@ pub struct LlvmArchiveBuilderBuilder;

impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
// FIXME use ArArchiveBuilder on most targets again once reading thin archives is
// implemented
if true {
// Keeping LlvmArchiveBuilder around in case of a regression caused by using
// ArArchiveBuilder.
// FIXME(#128955) remove a couple of months after #128936 gets merged in case
// no regression is found.
if false {
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
} else {
Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
Expand Down Expand Up @@ -198,25 +200,11 @@ static LLVM_OBJECT_READER: ObjectReader = ObjectReader {
get_xcoff_member_alignment: DEFAULT_OBJECT_READER.get_xcoff_member_alignment,
};

fn should_use_llvm_reader(buf: &[u8]) -> bool {
let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) };

// COFF bigobj file, msvc LTO file or import library. See
// https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51
let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF");

is_bitcode || is_unsupported_windows_obj_file
}

#[deny(unsafe_op_in_unsafe_fn)]
fn get_llvm_object_symbols(
buf: &[u8],
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
) -> io::Result<bool> {
if !should_use_llvm_reader(buf) {
return (DEFAULT_OBJECT_READER.get_symbols)(buf, f);
}

let mut state = Box::new(f);

let err = unsafe {
Expand Down Expand Up @@ -253,18 +241,10 @@ fn get_llvm_object_symbols(
}

fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
if !should_use_llvm_reader(buf) {
return (DEFAULT_OBJECT_READER.is_64_bit_object_file)(buf);
}

unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) }
}

fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
if !should_use_llvm_reader(buf) {
return (DEFAULT_OBJECT_READER.is_ec_object_file)(buf);
}

unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
}

Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,15 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
let file_name = String::from_utf8(entry.name().to_vec())
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
if !skip(&file_name) {
self.entries.push((
file_name.into_bytes(),
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
));
if entry.is_thin() {
let member_path = archive_path.parent().unwrap().join(Path::new(&file_name));
self.entries.push((file_name.into_bytes(), ArchiveEntry::File(member_path)));
} else {
self.entries.push((
file_name.into_bytes(),
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
));
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/tools/run-make-support/src/external_deps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@ impl LlvmAr {
self
}

/// Like `obj_to_ar` except creating a thin archive.
pub fn obj_to_thin_ar(&mut self) -> &mut Self {
self.cmd.arg("rcus").arg("--thin");
self
}

/// Extract archive members back to files.
pub fn extract(&mut self) -> &mut Self {
self.cmd.arg("x");
Expand Down
5 changes: 5 additions & 0 deletions tests/run-make/staticlib-thin-archive/bin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
unsafe {
rust_lib::simple_fn();
}
}
23 changes: 23 additions & 0 deletions tests/run-make/staticlib-thin-archive/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Regression test for https://github.com/rust-lang/rust/issues/107407 which
// checks that rustc can read thin archive. Before the object crate added thin
// archive support rustc would add emit object files to the staticlib and after
// the object crate added thin archive support it would previously crash the
// compiler due to a missing special case for thin archive members.
use run_make_support::{llvm_ar, path, rfs, rust_lib_name, rustc, static_lib_name};

fn main() {
rfs::create_dir("archive");

// Build a thin archive
rustc().input("simple_obj.rs").emit("obj").output("archive/simple_obj.o").run();
llvm_ar()
.obj_to_thin_ar()
.output_input(path("archive").join(static_lib_name("thin_archive")), "archive/simple_obj.o")
.run();

// Build an rlib which includes the members of this thin archive
rustc().input("rust_lib.rs").library_search_path("archive").run();

// Build a binary which requires a symbol from the thin archive
rustc().input("bin.rs").extern_("rust_lib", rust_lib_name("rust_lib")).run();
}
6 changes: 6 additions & 0 deletions tests/run-make/staticlib-thin-archive/rust_lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![crate_type = "rlib"]

#[link(name = "thin_archive", kind = "static")]
extern "C" {
pub fn simple_fn();
}
4 changes: 4 additions & 0 deletions tests/run-make/staticlib-thin-archive/simple_obj.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#![crate_type = "staticlib"]

#[no_mangle]
extern "C" fn simple_fn() {}

0 comments on commit adcf44d

Please sign in to comment.