Skip to content

Commit

Permalink
Add tests for tombstones
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 committed Sep 11, 2024
1 parent 48f4734 commit 66519e6
Show file tree
Hide file tree
Showing 13 changed files with 150 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 @@ -390,10 +390,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
75 changes: 75 additions & 0 deletions tests/testinput.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::path::PathBuf;
use std::process::Command;
use std::{env, fs};

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

fn main() {
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());
}
if cfg!(target_os = "windows") {
exe.push("addr2line.exe");
} else {
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 66519e6

Please sign in to comment.