Skip to content

Commit e8c623d

Browse files
committed
Auto merge of #137044 - Kobzol:ctors-detector, r=<try>
[CRATER] Detect presence of .ctors/.dtors in linked objects This PR serves for a crater run to examine the frequency of object files in the wild that use the `.ctors`/`.dtors` sections, which are problematic for LLD (#128286). I'm not sure if there are any other sections that cause problems for LLD (?). I used `readelf -S` instead of the `object` crate, because it had a problem with opening some object files (notably CUDA, although we probably won't find these in crater anyway...). If it becomes a problem, I can also scan the libraries with `object`. I'm pretty clueless about crater, so: r? `@lqd`
2 parents fc147b4 + 77891e2 commit e8c623d

File tree

1 file changed

+80
-0
lines changed
  • compiler/rustc_codegen_ssa/src/back

1 file changed

+80
-0
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+80
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,70 @@ fn link_natively(
785785
should_archive.then(|| tmpdir.join(out_filename.file_name().unwrap()).with_extension("so"));
786786
let temp_filename = archive_member.as_deref().unwrap_or(out_filename);
787787

788+
// Gather library search paths (-L)
789+
let mut library_search_dirs = vec![];
790+
walk_native_lib_search_dirs(sess, self_contained_components, None, |dir, is_framework| {
791+
if !is_framework {
792+
library_search_dirs.push(dir.to_path_buf());
793+
}
794+
ControlFlow::<()>::Continue(())
795+
});
796+
797+
// Find candidate objects to link
798+
let mut obj_candidates = vec![];
799+
800+
// Rust objects
801+
for module in &codegen_results.modules {
802+
if let Some(ref path) = module.object {
803+
obj_candidates.push(path.clone());
804+
}
805+
}
806+
807+
// eprintln!("Library dirs: {:?}", library_search_dirs);
808+
// Native libraries
809+
for native_lib in codegen_results.crate_info.native_libraries.values().flatten() {
810+
// eprintln!("native lib {}", native_lib.name);
811+
if let Some(ref path) = native_lib.filename {
812+
// eprintln!(" located at {path:?}");
813+
obj_candidates.push(PathBuf::from(path.to_string()));
814+
} else {
815+
// Try to find the library
816+
let name = native_lib.name.to_string();
817+
let candidates = &[format!("lib{name}.a"), format!("lib{name}.so")];
818+
for candidate in candidates {
819+
// eprintln!("Finding candidate {candidate}");
820+
for lib_dir in &library_search_dirs {
821+
let candidate_path = lib_dir.join(candidate);
822+
if candidate_path.is_file() {
823+
eprintln!("Found native library at {candidate_path:?}");
824+
obj_candidates.push(candidate_path);
825+
}
826+
}
827+
}
828+
}
829+
}
830+
831+
use object::read::Object;
832+
833+
// Scan native libraries, sources of .ctors/.dtors
834+
let mut problematic_objects = vec![];
835+
let sections = &[".ctors", ".dtors"];
836+
for path in obj_candidates {
837+
match std::process::Command::new("readelf").arg("-S").arg(&path).output() {
838+
Ok(output) => {
839+
let stdout = String::from_utf8_lossy(&output.stdout);
840+
for section in sections {
841+
if stdout.lines().any(|line| line.contains(section)) {
842+
problematic_objects.push((path.clone(), section.to_string()));
843+
}
844+
}
845+
}
846+
Err(error) => {
847+
eprintln!("Cannot run readelf -S: {error:?}")
848+
}
849+
}
850+
}
851+
788852
let mut cmd = linker_with_args(
789853
&linker_path,
790854
flavor,
@@ -990,6 +1054,22 @@ fn link_natively(
9901054
}
9911055
}
9921056

1057+
// Scan the built artifact, lld might keep .ctors/.dtors in it
1058+
if let Ok(data) = std::fs::read(&temp_filename) {
1059+
if let Ok(file) = object::read::File::parse(data.as_slice()) {
1060+
for section_name in sections {
1061+
if let Some(_section) = file.section_by_name(section_name) {
1062+
problematic_objects
1063+
.push((temp_filename.to_path_buf(), section_name.to_string()));
1064+
}
1065+
}
1066+
}
1067+
}
1068+
if !problematic_objects.is_empty() {
1069+
eprintln!("PROBLEMATIC OBJECtS\n{problematic_objects:?}");
1070+
panic!("{problematic_objects:?}");
1071+
}
1072+
9931073
match prog {
9941074
Ok(prog) => {
9951075
let is_msvc_link_exe = sess.target.is_like_msvc

0 commit comments

Comments
 (0)