Skip to content

Commit

Permalink
Auto merge of #128936 - bjorn3:fix_thin_archive_reading, r=jieyouxu
Browse files Browse the repository at this point in the history
Support reading thin archives in ArArchiveBuilder

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

Fixes #107407
Fixes #107162
#107495 has been fixed in a previous PR already.
  • Loading branch information
bors committed Aug 15, 2024
2 parents 3139ff0 + 901c9da commit d2b5aa6
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 38 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
14 changes: 5 additions & 9 deletions compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,18 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State,
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());
return ErrorCallback(toString(ObjOrErr.takeError()).c_str());
}
std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);
if (Obj == nullptr) {
return 0;
}

for (const object::BasicSymbolRef &S : Obj->symbols()) {
if (!isArchiveSymbol(S))
continue;
if (Error E = S.printName(SymName)) {
SmallString<0> ErrorBuf;
auto Error = raw_svector_ostream(ErrorBuf);
Error << E << '\0';
return ErrorCallback(Error.str().data());
return ErrorCallback(toString(std::move(E)).c_str());
}
SymName << '\0';
if (void *E = Callback(State, SymNameBuf.str().data())) {
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 d2b5aa6

Please sign in to comment.