Skip to content

Commit

Permalink
Add tests for tombstones (#328)
Browse files Browse the repository at this point in the history
This covers some but not all cases of tombstones.
In particular, we don't have a test for a DW_LNE_set_address
tombstone in the middle of a line number sequence.

This also handles an integer overflow for a tombstone address
in DW_AT_low_pc. We already did the right thing in release builds.
  • Loading branch information
philipc authored Sep 15, 2024
1 parent 5d10d81 commit 3989031
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ jobs:
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
with:
submodules: true
- name: Set env (macOS)
if: matrix.os == 'macOS-latest'
run: |
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "testinput"]
path = testinput
url = https://github.com/gimli-rs/object-testfiles
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ name = "output_equivalence"
harness = false
required-features = ["bin"]

[[test]]
name = "testinput"
harness = false
required-features = ["bin"]

[[test]]
name = "correctness"
required-features = ["loader", "fallible-iterator"]
Expand Down
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,10 @@ impl<R: gimli::Reader> RangeAttributes<R> {
} else if let (Some(begin), Some(end)) = (self.low_pc, self.high_pc) {
add_range(gimli::Range { begin, end });
} else if let (Some(begin), Some(size)) = (self.low_pc, self.size) {
add_range(gimli::Range {
begin,
end: begin + size,
});
// If `begin` is a -1 tombstone, this will overflow and the check in
// `add_range` will ignore it.
let end = begin.wrapping_add(size);
add_range(gimli::Range { begin, end });
}
Ok(added_any)
}
Expand Down
1 change: 1 addition & 0 deletions testinput
Submodule testinput added at 76d453
6 changes: 6 additions & 0 deletions testoutput/dwarf/tombstone-loc-0
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
0x0000000000001040
main
/object/testfiles/dwarf/tombstone.cpp:9
0x0000000000001044
main
/object/testfiles/dwarf/tombstone.cpp:14
6 changes: 6 additions & 0 deletions testoutput/dwarf/tombstone-loc-1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
0x0000000000001740
main
/object/testfiles/dwarf/tombstone.cpp:9
0x0000000000001744
main
/object/testfiles/dwarf/tombstone.cpp:14
12 changes: 12 additions & 0 deletions testoutput/dwarf/tombstone-loc-addend
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
0x0000000000000000
_Z2f1v
/object/testfiles/dwarf/tombstone.cpp:3
0x0000000000000004
_Z2f1v
/object/testfiles/dwarf/tombstone.cpp:8
0x00000000000005a0
main
/object/testfiles/dwarf/tombstone.cpp:9
0x00000000000005a4
main
/object/testfiles/dwarf/tombstone.cpp:14
6 changes: 6 additions & 0 deletions testoutput/dwarf/tombstone-loc-max
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
0x0000000000001740
main
/object/testfiles/dwarf/tombstone.cpp:9
0x0000000000001744
main
/object/testfiles/dwarf/tombstone.cpp:14
12 changes: 12 additions & 0 deletions testoutput/dwarf/tombstone-loclists-0
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
0x0000000000000000
_Z2f1v
/object/testfiles/dwarf/tombstone.cpp:3
0x0000000000000004
_Z2f1v
/object/testfiles/dwarf/tombstone.cpp:8
0x0000000000001040
main
/object/testfiles/dwarf/tombstone.cpp:9
0x0000000000001044
main
/object/testfiles/dwarf/tombstone.cpp:14
12 changes: 12 additions & 0 deletions testoutput/dwarf/tombstone-loclists-addend
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
0x0000000000000000
_Z2f1v
/object/testfiles/dwarf/tombstone.cpp:3
0x0000000000000004
_Z2f1v
/object/testfiles/dwarf/tombstone.cpp:8
0x00000000000005a0
main
/object/testfiles/dwarf/tombstone.cpp:9
0x00000000000005a4
main
/object/testfiles/dwarf/tombstone.cpp:14
6 changes: 6 additions & 0 deletions testoutput/dwarf/tombstone-loclists-max
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
0x0000000000001740
main
/object/testfiles/dwarf/tombstone.cpp:9
0x0000000000001744
main
/object/testfiles/dwarf/tombstone.cpp:14
76 changes: 76 additions & 0 deletions tests/testinput.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use std::path::PathBuf;
use std::process::Command;
use std::{env, fs};

use libtest_mimic::{Arguments, Failed, Trial};

fn main() {
if cfg!(target_os = "windows") {
// Tests don't currently handle newline differences on Windows.
return;
}

let args = Arguments::from_args();
libtest_mimic::run(&args, make_tests()).exit();
}

fn make_tests() -> Vec<Trial> {
let testinput = PathBuf::from("testinput/dwarf");
let testoutput = PathBuf::from("testoutput/dwarf");

let mut tests = Vec::new();
let mut dirs = vec![(testinput, testoutput)];
while let Some((in_dir, out_dir)) = dirs.pop() {
for entry in out_dir.read_dir().unwrap() {
let entry = entry.unwrap();
let out_path = entry.path();
let mut in_path = in_dir.clone();
in_path.push(entry.file_name());

let file_type = entry.file_type().unwrap();
if file_type.is_dir() {
dirs.push((in_path, out_path));
} else if file_type.is_file() {
tests.push(Trial::test(
format!("addr2line -e {}", in_path.display()),
move || run_test(in_path, out_path),
));
}
}
}
tests
}

fn run_test(in_path: PathBuf, out_path: PathBuf) -> Result<(), Failed> {
let mut exe = env::current_exe().unwrap();
assert!(exe.pop());
if exe.file_name().unwrap().to_str().unwrap() == "deps" {
assert!(exe.pop());
}
exe.push("addr2line");
assert!(exe.is_file());

let mut cmd = Command::new(exe);
cmd.env("RUST_BACKTRACE", "1");
cmd.arg("--exe").arg(in_path).arg("--all").arg("-afi");

let output = cmd.output().unwrap();
assert!(output.status.success());
let out_data = output.stdout;

if env::var_os("ADDR2LINE_TESTOUTPUT_UPDATE").is_some() {
fs::write(out_path, &out_data).unwrap();
return Ok(());
}

let expect_out_data = fs::read(out_path).unwrap();
if out_data != expect_out_data {
let out_str = String::from_utf8_lossy(&out_data);
let expect_out_str = String::from_utf8_lossy(&expect_out_data);
return Err(
format!("output mismatch\nexpected:\n{expect_out_str}\nactual:\n{out_str}").into(),
);
}

Ok(())
}

0 comments on commit 3989031

Please sign in to comment.