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