Use llvm.compiler.used insetad of llvm.used

The #[used] attribute explicitly only requires symbols to be
retained in object files, but allows the linker to drop them
if dead. This corresponds to llvm.compiler.used semantics.

The motivation to change this *now* is that https://reviews.llvm.org/D97448
starts emitting #[used] symbols into unique sections with
SHF_GNU_RETAIN flag. This triggers a bug in some version of gold,
resulting in the ARGV_INIT_ARRAY symbol part of the .init_array
section to be incorrectly placed.
This commit is contained in:
Nikita Popov 2021-08-07 17:04:32 +02:00
parent 154c8408e9
commit 7c015648dd
5 changed files with 16 additions and 8 deletions

View File

@ -157,12 +157,12 @@ pub fn compile_codegen_unit(
} }
// Finalize code coverage by injecting the coverage map. Note, the coverage map will // Finalize code coverage by injecting the coverage map. Note, the coverage map will
// also be added to the `llvm.used` variable, created next. // also be added to the `llvm.compiler.used` variable, created next.
if cx.sess().instrument_coverage() { if cx.sess().instrument_coverage() {
cx.coverageinfo_finalize(); cx.coverageinfo_finalize();
} }
// Create the llvm.used variable // Create the llvm.compiler.used variable
// This variable has type [N x i8*] and is stored in the llvm.metadata section // This variable has type [N x i8*] and is stored in the llvm.metadata section
if !cx.used_statics().borrow().is_empty() { if !cx.used_statics().borrow().is_empty() {
cx.create_used_variable() cx.create_used_variable()

View File

@ -479,7 +479,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
} }
} }
/// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. /// Add a global value to a list to be stored in the `llvm.compiler.used` variable, an array of i8*.
fn add_used_global(&self, global: &'ll Value) { fn add_used_global(&self, global: &'ll Value) {
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) }; let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
self.used_statics.borrow_mut().push(cast); self.used_statics.borrow_mut().push(cast);

View File

@ -71,8 +71,8 @@ pub struct CodegenCx<'ll, 'tcx> {
/// to constants.) /// to constants.)
pub statics_to_rauw: RefCell<Vec<(&'ll Value, &'ll Value)>>, pub statics_to_rauw: RefCell<Vec<(&'ll Value, &'ll Value)>>,
/// Statics that will be placed in the llvm.used variable /// Statics that will be placed in the llvm.compiler.used variable
/// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details /// See <https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable> for details
pub used_statics: RefCell<Vec<&'ll Value>>, pub used_statics: RefCell<Vec<&'ll Value>>,
/// Mapping of non-scalar types to llvm types and field remapping if needed. /// Mapping of non-scalar types to llvm types and field remapping if needed.
@ -447,7 +447,13 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
} }
fn create_used_variable(&self) { fn create_used_variable(&self) {
let name = cstr!("llvm.used"); // The semantics of #[used] in Rust only require the symbol to make it into the object
// file. It is explicitly allowed for the linker to strip the symbol if it is dead.
// As such, use llvm.compiler.used instead of llvm.used.
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
// sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs in
// some versions of the gold linker.
let name = cstr!("llvm.compiler.used");
let section = cstr!("llvm.metadata"); let section = cstr!("llvm.metadata");
let array = let array =
self.const_array(&self.type_ptr_to(self.type_i8()), &*self.used_statics.borrow()); self.const_array(&self.type_ptr_to(self.type_i8()), &*self.used_statics.borrow());

View File

@ -178,7 +178,7 @@ declare_features! (
/// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`.
/// This defines the behavior of panics. /// This defines the behavior of panics.
(accepted, panic_handler, "1.30.0", Some(44489), None), (accepted, panic_handler, "1.30.0", Some(44489), None),
/// Allows `#[used]` to preserve symbols (see llvm.used). /// Allows `#[used]` to preserve symbols (see llvm.compiler.used).
(accepted, used, "1.30.0", Some(40289), None), (accepted, used, "1.30.0", Some(40289), None),
/// Allows `crate` in paths. /// Allows `crate` in paths.
(accepted, crate_in_paths, "1.30.0", Some(45477), None), (accepted, crate_in_paths, "1.30.0", Some(45477), None),

View File

@ -28,9 +28,11 @@ CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8
CHECK: @__llvm_prf_nm = private constant CHECK: @__llvm_prf_nm = private constant
CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1 CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1
CHECK: @llvm.used = appending global CHECK: @llvm.compiler.used = appending global
CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*) CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*)
WINDOWS-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*) WINDOWS-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*)
CHECK-SAME: section "llvm.metadata"
CHECK: @llvm.used = appending global
CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0) CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0)
CHECK-SAME: section "llvm.metadata" CHECK-SAME: section "llvm.metadata"