mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Auto merge of #128936 - bjorn3:fix_thin_archive_reading, r=jieyouxu
Support reading thin archives in ArArchiveBuilder And switch to using ArArchiveBuilder with the LLVM backend too now that all regressions are fixed. Fixes https://github.com/rust-lang/rust/issues/107407 Fixes https://github.com/rust-lang/rust/issues/107162 https://github.com/rust-lang/rust/issues/107495 has been fixed in a previous PR already.
This commit is contained in:
commit
d2b5aa6552
@ -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))
|
||||
@ -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 {
|
||||
@ -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()) }
|
||||
}
|
||||
|
||||
|
@ -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() },
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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())) {
|
||||
|
@ -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");
|
||||
|
5
tests/run-make/staticlib-thin-archive/bin.rs
Normal file
5
tests/run-make/staticlib-thin-archive/bin.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
unsafe {
|
||||
rust_lib::simple_fn();
|
||||
}
|
||||
}
|
23
tests/run-make/staticlib-thin-archive/rmake.rs
Normal file
23
tests/run-make/staticlib-thin-archive/rmake.rs
Normal file
@ -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
tests/run-make/staticlib-thin-archive/rust_lib.rs
Normal file
6
tests/run-make/staticlib-thin-archive/rust_lib.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
#[link(name = "thin_archive", kind = "static")]
|
||||
extern "C" {
|
||||
pub fn simple_fn();
|
||||
}
|
4
tests/run-make/staticlib-thin-archive/simple_obj.rs
Normal file
4
tests/run-make/staticlib-thin-archive/simple_obj.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#![crate_type = "staticlib"]
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn simple_fn() {}
|
Loading…
Reference in New Issue
Block a user