Skip to content

Commit d2b5aa6

Browse files
committed
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 #107407 Fixes #107162 #107495 has been fixed in a previous PR already.
2 parents 3139ff0 + 901c9da commit d2b5aa6

File tree

8 files changed

+63
-38
lines changed

8 files changed

+63
-38
lines changed

compiler/rustc_codegen_llvm/src/back/archive.rs

+5-25
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@ pub struct LlvmArchiveBuilderBuilder;
106106

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

201-
fn should_use_llvm_reader(buf: &[u8]) -> bool {
202-
let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) };
203-
204-
// COFF bigobj file, msvc LTO file or import library. See
205-
// https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51
206-
let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF");
207-
208-
is_bitcode || is_unsupported_windows_obj_file
209-
}
210-
211203
#[deny(unsafe_op_in_unsafe_fn)]
212204
fn get_llvm_object_symbols(
213205
buf: &[u8],
214206
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
215207
) -> io::Result<bool> {
216-
if !should_use_llvm_reader(buf) {
217-
return (DEFAULT_OBJECT_READER.get_symbols)(buf, f);
218-
}
219-
220208
let mut state = Box::new(f);
221209

222210
let err = unsafe {
@@ -253,18 +241,10 @@ fn get_llvm_object_symbols(
253241
}
254242

255243
fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
256-
if !should_use_llvm_reader(buf) {
257-
return (DEFAULT_OBJECT_READER.is_64_bit_object_file)(buf);
258-
}
259-
260244
unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) }
261245
}
262246

263247
fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
264-
if !should_use_llvm_reader(buf) {
265-
return (DEFAULT_OBJECT_READER.is_ec_object_file)(buf);
266-
}
267-
268248
unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
269249
}
270250

compiler/rustc_codegen_ssa/src/back/archive.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,15 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
307307
let file_name = String::from_utf8(entry.name().to_vec())
308308
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
309309
if !skip(&file_name) {
310-
self.entries.push((
311-
file_name.into_bytes(),
312-
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
313-
));
310+
if entry.is_thin() {
311+
let member_path = archive_path.parent().unwrap().join(Path::new(&file_name));
312+
self.entries.push((file_name.into_bytes(), ArchiveEntry::File(member_path)));
313+
} else {
314+
self.entries.push((
315+
file_name.into_bytes(),
316+
ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() },
317+
));
318+
}
314319
}
315320
}
316321

compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,18 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State,
7777
Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
7878
getSymbolicFile(Buf->getMemBufferRef(), Context);
7979
if (!ObjOrErr) {
80-
Error E = ObjOrErr.takeError();
81-
SmallString<0> ErrorBuf;
82-
auto Error = raw_svector_ostream(ErrorBuf);
83-
Error << E << '\0';
84-
return ErrorCallback(Error.str().data());
80+
return ErrorCallback(toString(ObjOrErr.takeError()).c_str());
8581
}
8682
std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);
83+
if (Obj == nullptr) {
84+
return 0;
85+
}
8786

8887
for (const object::BasicSymbolRef &S : Obj->symbols()) {
8988
if (!isArchiveSymbol(S))
9089
continue;
9190
if (Error E = S.printName(SymName)) {
92-
SmallString<0> ErrorBuf;
93-
auto Error = raw_svector_ostream(ErrorBuf);
94-
Error << E << '\0';
95-
return ErrorCallback(Error.str().data());
91+
return ErrorCallback(toString(std::move(E)).c_str());
9692
}
9793
SymName << '\0';
9894
if (void *E = Callback(State, SymNameBuf.str().data())) {

src/tools/run-make-support/src/external_deps/llvm.rs

+6
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,12 @@ impl LlvmAr {
285285
self
286286
}
287287

288+
/// Like `obj_to_ar` except creating a thin archive.
289+
pub fn obj_to_thin_ar(&mut self) -> &mut Self {
290+
self.cmd.arg("rcus").arg("--thin");
291+
self
292+
}
293+
288294
/// Extract archive members back to files.
289295
pub fn extract(&mut self) -> &mut Self {
290296
self.cmd.arg("x");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
unsafe {
3+
rust_lib::simple_fn();
4+
}
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Regression test for https://github.com/rust-lang/rust/issues/107407 which
2+
// checks that rustc can read thin archive. Before the object crate added thin
3+
// archive support rustc would add emit object files to the staticlib and after
4+
// the object crate added thin archive support it would previously crash the
5+
// compiler due to a missing special case for thin archive members.
6+
use run_make_support::{llvm_ar, path, rfs, rust_lib_name, rustc, static_lib_name};
7+
8+
fn main() {
9+
rfs::create_dir("archive");
10+
11+
// Build a thin archive
12+
rustc().input("simple_obj.rs").emit("obj").output("archive/simple_obj.o").run();
13+
llvm_ar()
14+
.obj_to_thin_ar()
15+
.output_input(path("archive").join(static_lib_name("thin_archive")), "archive/simple_obj.o")
16+
.run();
17+
18+
// Build an rlib which includes the members of this thin archive
19+
rustc().input("rust_lib.rs").library_search_path("archive").run();
20+
21+
// Build a binary which requires a symbol from the thin archive
22+
rustc().input("bin.rs").extern_("rust_lib", rust_lib_name("rust_lib")).run();
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![crate_type = "rlib"]
2+
3+
#[link(name = "thin_archive", kind = "static")]
4+
extern "C" {
5+
pub fn simple_fn();
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#![crate_type = "staticlib"]
2+
3+
#[no_mangle]
4+
extern "C" fn simple_fn() {}

0 commit comments

Comments
 (0)