Browse Source

Fix meaning of generated `.debug_loc` sections (#8753)

This commit is a fix to Wasmtime's DWARF processing transform to correct
the meaning of the `.debug_loc` section. This section's addresses are
relative to the `DW_AT_low_pc` entry located in the
`DW_TAG_compile_unit` container, but Wasmtime's construction of this
section didn't take this into account. Instead all addresses in
`.debug_loc` are relative to the start of the compiled object, not to
the start of the compile unit itself. This commit fixes this by
unconditionally describing `DW_TAG_compile_unit` locations with
`DW_AT_ranges` instead of `DW_AT_low_pc`. This ends up fixing debug
information for debug information using `.debug_loc` with multiple
codegen units.

Closes #8752
pull/8770/head
Alex Crichton 5 months ago
committed by GitHub
parent
commit
33cc4959dc
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 15
      crates/cranelift/src/debug/transform/range_info_builder.rs
  2. 14
      crates/test-programs/src/bin/dwarf_multiple_codegen_units.rs
  3. 42
      tests/all/debug/lldb.rs

15
crates/cranelift/src/debug/transform/range_info_builder.rs

@ -145,7 +145,20 @@ impl RangeInfoBuilder {
for (begin, end) in ranges { for (begin, end) in ranges {
result.extend(addr_tr.translate_ranges(*begin, *end)); result.extend(addr_tr.translate_ranges(*begin, *end));
} }
if result.len() != 1 {
// If we're seeing the ranges for a `DW_TAG_compile_unit` DIE
// then don't use `DW_AT_low_pc` and `DW_AT_high_pc`. These
// attributes, if set, will configure the base address of all
// location lists that this unit refers to. Currently this
// debug transform does not take this base address into account
// when generate the `.debug_loc` section. Consequently when a
// compile unit is configured here the `DW_AT_ranges` attribute
// is unconditionally used instead of
// `DW_AT_low_pc`/`DW_AT_high_pc`.
let is_attr_for_compile_unit =
out_unit.get(current_scope_id).tag() == gimli::DW_TAG_compile_unit;
if result.len() != 1 || is_attr_for_compile_unit {
let range_list = result let range_list = result
.iter() .iter()
.map(|tr| write::Range::StartLength { .map(|tr| write::Range::StartLength {

14
crates/test-programs/src/bin/dwarf_multiple_codegen_units.rs

@ -0,0 +1,14 @@
fn main() {
let a = 3;
foo::bar(a);
}
mod foo {
pub fn bar(x: u32) -> u32 {
let mut sum = 0;
for i in 0..x {
sum += i;
}
sum
}
}

42
tests/all/debug/lldb.rs

@ -376,4 +376,46 @@ check: exited with status = 0
fn dwarf_shared_memory() -> Result<()> { fn dwarf_shared_memory() -> Result<()> {
test_dwarf_simple(DWARF_SHARED_MEMORY, &[]) test_dwarf_simple(DWARF_SHARED_MEMORY, &[])
} }
#[test]
#[ignore]
fn dwarf_multiple_codegen_units() -> Result<()> {
for wasm in [
DWARF_MULTIPLE_CODEGEN_UNITS,
DWARF_MULTIPLE_CODEGEN_UNITS_COMPONENT,
] {
println!("testing {wasm:?}");
let output = lldb_with_script(
&["-Ccache=n", "-Oopt-level=0", "-Ddebug-info", wasm],
r#"
breakpoint set --file dwarf_multiple_codegen_units.rs --line 3
breakpoint set --file dwarf_multiple_codegen_units.rs --line 10
r
fr v
c
fr v
breakpoint delete 2
finish
c"#,
)?;
check_lldb_output(
&output,
r#"
check: Breakpoint 1: no locations (pending)
check: Breakpoint 2: no locations (pending)
check: stop reason = breakpoint 1.1
check: foo::bar(a)
check: a = 3
check: sum += i
check: x = 3
check: sum = 0
check: 1 breakpoints deleted
check: Return value: $(=.*) 3
check: exited with status = 0
"#,
)?;
}
Ok(())
}
} }

Loading…
Cancel
Save