mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +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 {
|
impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
|
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
|
// Keeping LlvmArchiveBuilder around in case of a regression caused by using
|
||||||
// implemented
|
// ArArchiveBuilder.
|
||||||
if true {
|
// 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() })
|
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
|
||||||
} else {
|
} else {
|
||||||
Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
|
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,
|
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)]
|
#[deny(unsafe_op_in_unsafe_fn)]
|
||||||
fn get_llvm_object_symbols(
|
fn get_llvm_object_symbols(
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
|
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
|
||||||
) -> io::Result<bool> {
|
) -> io::Result<bool> {
|
||||||
if !should_use_llvm_reader(buf) {
|
|
||||||
return (DEFAULT_OBJECT_READER.get_symbols)(buf, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut state = Box::new(f);
|
let mut state = Box::new(f);
|
||||||
|
|
||||||
let err = unsafe {
|
let err = unsafe {
|
||||||
@ -253,18 +241,10 @@ fn get_llvm_object_symbols(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
|
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()) }
|
unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
|
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()) }
|
unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,12 +307,17 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
|
|||||||
let file_name = String::from_utf8(entry.name().to_vec())
|
let file_name = String::from_utf8(entry.name().to_vec())
|
||||||
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
|
||||||
if !skip(&file_name) {
|
if !skip(&file_name) {
|
||||||
|
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((
|
self.entries.push((
|
||||||
file_name.into_bytes(),
|
file_name.into_bytes(),
|
||||||
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
|
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.src_archives.push((archive_path, archive_map));
|
self.src_archives.push((archive_path, archive_map));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -77,22 +77,18 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State,
|
|||||||
Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
|
Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
|
||||||
getSymbolicFile(Buf->getMemBufferRef(), Context);
|
getSymbolicFile(Buf->getMemBufferRef(), Context);
|
||||||
if (!ObjOrErr) {
|
if (!ObjOrErr) {
|
||||||
Error E = ObjOrErr.takeError();
|
return ErrorCallback(toString(ObjOrErr.takeError()).c_str());
|
||||||
SmallString<0> ErrorBuf;
|
|
||||||
auto Error = raw_svector_ostream(ErrorBuf);
|
|
||||||
Error << E << '\0';
|
|
||||||
return ErrorCallback(Error.str().data());
|
|
||||||
}
|
}
|
||||||
std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);
|
std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);
|
||||||
|
if (Obj == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (const object::BasicSymbolRef &S : Obj->symbols()) {
|
for (const object::BasicSymbolRef &S : Obj->symbols()) {
|
||||||
if (!isArchiveSymbol(S))
|
if (!isArchiveSymbol(S))
|
||||||
continue;
|
continue;
|
||||||
if (Error E = S.printName(SymName)) {
|
if (Error E = S.printName(SymName)) {
|
||||||
SmallString<0> ErrorBuf;
|
return ErrorCallback(toString(std::move(E)).c_str());
|
||||||
auto Error = raw_svector_ostream(ErrorBuf);
|
|
||||||
Error << E << '\0';
|
|
||||||
return ErrorCallback(Error.str().data());
|
|
||||||
}
|
}
|
||||||
SymName << '\0';
|
SymName << '\0';
|
||||||
if (void *E = Callback(State, SymNameBuf.str().data())) {
|
if (void *E = Callback(State, SymNameBuf.str().data())) {
|
||||||
|
@ -285,6 +285,12 @@ impl LlvmAr {
|
|||||||
self
|
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.
|
/// Extract archive members back to files.
|
||||||
pub fn extract(&mut self) -> &mut Self {
|
pub fn extract(&mut self) -> &mut Self {
|
||||||
self.cmd.arg("x");
|
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