]>
Commit | Line | Data |
---|---|---|
d9579d0f AL |
1 | // .debug_gdb_scripts binary section. |
2 | ||
9fa01778 | 3 | use crate::llvm; |
d9579d0f | 4 | |
9fa01778 | 5 | use crate::builder::Builder; |
dfeec247 | 6 | use crate::common::CodegenCx; |
9fa01778 | 7 | use crate::value::Value; |
a1dfa0c6 | 8 | use rustc_codegen_ssa::traits::*; |
ba9703b0 XL |
9 | use rustc_middle::bug; |
10 | use rustc_session::config::DebugInfo; | |
d9579d0f | 11 | |
dfeec247 | 12 | use rustc_span::symbol::sym; |
d9579d0f AL |
13 | |
14 | /// Inserts a side-effect free instruction sequence that makes sure that the | |
15 | /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker. | |
9fa01778 | 16 | pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) { |
a1dfa0c6 XL |
17 | if needs_gdb_debug_scripts_section(bx) { |
18 | let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx); | |
32a655c1 SL |
19 | // Load just the first byte as that's all that's necessary to force |
20 | // LLVM to keep around the reference to the global. | |
a1dfa0c6 | 21 | let indices = [bx.const_i32(0), bx.const_i32(0)]; |
2c00a5a8 XL |
22 | let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices); |
23 | let volative_load_instruction = bx.volatile_load(element); | |
d9579d0f | 24 | unsafe { |
b039eaaf | 25 | llvm::LLVMSetAlignment(volative_load_instruction, 1); |
d9579d0f AL |
26 | } |
27 | } | |
28 | } | |
29 | ||
30 | /// Allocates the global variable responsible for the .debug_gdb_scripts binary | |
31 | /// section. | |
dfeec247 | 32 | pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) -> &'ll Value { |
b039eaaf | 33 | let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0"; |
dfeec247 | 34 | let section_var_name = &c_section_var_name[..c_section_var_name.len() - 1]; |
d9579d0f | 35 | |
dfeec247 XL |
36 | let section_var = |
37 | unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr().cast()) }; | |
d9579d0f | 38 | |
b7449926 | 39 | section_var.unwrap_or_else(|| { |
d9579d0f AL |
40 | let section_name = b".debug_gdb_scripts\0"; |
41 | let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0"; | |
42 | ||
43 | unsafe { | |
dfeec247 | 44 | let llvm_type = cx.type_array(cx.type_i8(), section_contents.len() as u64); |
d9579d0f | 45 | |
dfeec247 XL |
46 | let section_var = cx |
47 | .define_global(section_var_name, llvm_type) | |
48 | .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name)); | |
e74abb32 | 49 | llvm::LLVMSetSection(section_var, section_name.as_ptr().cast()); |
a1dfa0c6 | 50 | llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); |
d9579d0f | 51 | llvm::LLVMSetGlobalConstant(section_var, llvm::True); |
ba9703b0 | 52 | llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); |
9e0c209e | 53 | llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage); |
d9579d0f AL |
54 | // This should make sure that the whole section is not larger than |
55 | // the string it contains. Otherwise we get a warning from GDB. | |
56 | llvm::LLVMSetAlignment(section_var, 1); | |
57 | section_var | |
58 | } | |
b7449926 | 59 | }) |
d9579d0f AL |
60 | } |
61 | ||
9fa01778 | 62 | pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { |
3dfed10e XL |
63 | let omit_gdb_pretty_printer_section = cx |
64 | .tcx | |
65 | .sess | |
66 | .contains_name(&cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section); | |
d9579d0f | 67 | |
dfeec247 XL |
68 | !omit_gdb_pretty_printer_section |
69 | && cx.sess().opts.debuginfo != DebugInfo::None | |
70 | && cx.sess().target.target.options.emit_debug_gdb_scripts | |
d9579d0f | 71 | } |