Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.debug_gdb_scripts is being loaded into memory #81028

Open
jsgf opened this issue Jan 15, 2021 · 6 comments
Open

.debug_gdb_scripts is being loaded into memory #81028

jsgf opened this issue Jan 15, 2021 · 6 comments
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. I-heavy Issue: Problems and improvements with respect to binary size of generated code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@jsgf
Copy link
Contributor

jsgf commented Jan 15, 2021

If I build:

fn main() {}

with rustc -g --crate-type bin --emit obj -o t.o t.rs, and look at the output of readelf -St t.o I see:

  [27] .debug_gdb_scripts
       PROGBITS               PROGBITS         0000000000000000  0000000000000270  0
       0000000000000022 0000000000000001  0                 1
       [0000000000000032]: ALLOC, MERGE, STRINGS

According to #41627, this is not supposed to be an alloc section (ie, loaded into memory), but only present in the object file.

Having this section loaded isn't a huge problem in itself, but when combined with --link-arg -Wl,--strip-all (or --strip-debug) it triggers a crash in lld: https://bugs.llvm.org//show_bug.cgi?id=44878

There are lld fixes pending (https://reviews.llvm.org/D74510, https://reviews.llvm.org/D91291) (lld is already fixed), but it still seems like making .debug_gdb_scripts alloc is unintended.

Meta

rustc --version --verbose:

rustc 1.49.0 (e1884a8e3 2020-12-29)
binary: rustc
commit-hash: e1884a8e3c3e813aada8254edfa120e85bf5ffca
commit-date: 2020-12-29
host: x86_64-unknown-linux-gnu
release: 1.49.0

cc @eddyb @ayermolo

@jsgf jsgf added the C-bug Category: This is a bug. label Jan 15, 2021
@jsgf
Copy link
Contributor Author

jsgf commented Jan 15, 2021

This is basically a regression of issue #41626
cc @whitequark

@nagisa
Copy link
Member

nagisa commented Jan 15, 2021

somewhat relevant is #77961

I wouldn't be surprised if somebody went ahead and marked it as allocatable so that the linker preserves it in the final binary at all...

@jonas-schievink jonas-schievink added A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) A-linkage Area: linking into static, shared libraries and binaries I-heavy Issue: Problems and improvements with respect to binary size of generated code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 16, 2021
@bjorn3
Copy link
Member

bjorn3 commented Apr 15, 2021

A symbol in this section is directly referenced in the main shim using read_volatile to prevent the linker from gc'ing it.

bx.insert_reference_to_gdb_debug_scripts_section_global();

/// Inserts a side-effect free instruction sequence that makes sure that the
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) {
if needs_gdb_debug_scripts_section(bx) {
let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx);
// Load just the first byte as that's all that's necessary to force
// LLVM to keep around the reference to the global.
let indices = [bx.const_i32(0), bx.const_i32(0)];
let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
let volative_load_instruction = bx.volatile_load(element);
unsafe {
llvm::LLVMSetAlignment(volative_load_instruction, 1);
}
}
}

@jsgf
Copy link
Contributor Author

jsgf commented Apr 18, 2021

OK, so it is supposed to be alloc then.

@eddyb
Copy link
Member

eddyb commented Apr 30, 2021

That looks like an ancient way to emulate the #[used] attribute - could we maybe do that instead?

@bjorn3
Copy link
Member

bjorn3 commented Apr 30, 2021

#[used]
#[link_section = ".abc"]
#[no_mangle]
pub static FOO: u8 = 0;
fn main() {}

Does not result in an executable with an .abc section of FOO symbol. Executables never export any symbols except for main and certain symbols used by libc or created by the linker itself. Because of this --gc-sections will simply gc the .abc section.

$ readelf -sW rust_out | grep -v 0000000000000000 | grep "GLOBAL " | grep -v HIDDEN
    63: 0000000000001350     1 FUNC    GLOBAL DEFAULT   14 __libc_csu_fini
    65: 0000000000004010     0 NOTYPE  GLOBAL DEFAULT   24 _edata
    74: 00000000000012f0    93 FUNC    GLOBAL DEFAULT   14 __libc_csu_init
    75: 0000000000004018     0 NOTYPE  GLOBAL DEFAULT   25 _end
    76: 0000000000001050    43 FUNC    GLOBAL DEFAULT   14 _start
    78: 0000000000004010     0 NOTYPE  GLOBAL DEFAULT   25 __bss_start
    79: 00000000000012d0    29 FUNC    GLOBAL DEFAULT   14 main

From the linked rfc:

The part about the linker is not true (*): from the point of view of the linker static variables marked with #[used] look exactly the same as variables that have not been marked with that attribute -- those are the implemented LLVM semantics. Also ELF object files have no mechanism to prevent the linker from dropping its symbols if they are not referenced by other object files.

(*) unless "linker" is actually referring to llvm-link (?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. I-heavy Issue: Problems and improvements with respect to binary size of generated code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants