Skip to content

Commit 3989031

Browse files
authored
Add tests for tombstones (#328)
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.
1 parent 5d10d81 commit 3989031

13 files changed

+151
-4
lines changed

.github/workflows/rust.yml

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ jobs:
2020
runs-on: ${{matrix.os}}
2121
steps:
2222
- uses: actions/checkout@v3
23+
with:
24+
submodules: true
2325
- name: Set env (macOS)
2426
if: matrix.os == 'macOS-latest'
2527
run: |

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "testinput"]
2+
path = testinput
3+
url = https://github.com/gimli-rs/object-testfiles

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ name = "output_equivalence"
7575
harness = false
7676
required-features = ["bin"]
7777

78+
[[test]]
79+
name = "testinput"
80+
harness = false
81+
required-features = ["bin"]
82+
7883
[[test]]
7984
name = "correctness"
8085
required-features = ["loader", "fallible-iterator"]

src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,10 @@ impl<R: gimli::Reader> RangeAttributes<R> {
395395
} else if let (Some(begin), Some(end)) = (self.low_pc, self.high_pc) {
396396
add_range(gimli::Range { begin, end });
397397
} else if let (Some(begin), Some(size)) = (self.low_pc, self.size) {
398-
add_range(gimli::Range {
399-
begin,
400-
end: begin + size,
401-
});
398+
// If `begin` is a -1 tombstone, this will overflow and the check in
399+
// `add_range` will ignore it.
400+
let end = begin.wrapping_add(size);
401+
add_range(gimli::Range { begin, end });
402402
}
403403
Ok(added_any)
404404
}

testinput

Submodule testinput added at 76d453e

testoutput/dwarf/tombstone-loc-0

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
0x0000000000001040
2+
main
3+
/object/testfiles/dwarf/tombstone.cpp:9
4+
0x0000000000001044
5+
main
6+
/object/testfiles/dwarf/tombstone.cpp:14

testoutput/dwarf/tombstone-loc-1

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
0x0000000000001740
2+
main
3+
/object/testfiles/dwarf/tombstone.cpp:9
4+
0x0000000000001744
5+
main
6+
/object/testfiles/dwarf/tombstone.cpp:14

testoutput/dwarf/tombstone-loc-addend

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
0x0000000000000000
2+
_Z2f1v
3+
/object/testfiles/dwarf/tombstone.cpp:3
4+
0x0000000000000004
5+
_Z2f1v
6+
/object/testfiles/dwarf/tombstone.cpp:8
7+
0x00000000000005a0
8+
main
9+
/object/testfiles/dwarf/tombstone.cpp:9
10+
0x00000000000005a4
11+
main
12+
/object/testfiles/dwarf/tombstone.cpp:14

testoutput/dwarf/tombstone-loc-max

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
0x0000000000001740
2+
main
3+
/object/testfiles/dwarf/tombstone.cpp:9
4+
0x0000000000001744
5+
main
6+
/object/testfiles/dwarf/tombstone.cpp:14

testoutput/dwarf/tombstone-loclists-0

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
0x0000000000000000
2+
_Z2f1v
3+
/object/testfiles/dwarf/tombstone.cpp:3
4+
0x0000000000000004
5+
_Z2f1v
6+
/object/testfiles/dwarf/tombstone.cpp:8
7+
0x0000000000001040
8+
main
9+
/object/testfiles/dwarf/tombstone.cpp:9
10+
0x0000000000001044
11+
main
12+
/object/testfiles/dwarf/tombstone.cpp:14
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
0x0000000000000000
2+
_Z2f1v
3+
/object/testfiles/dwarf/tombstone.cpp:3
4+
0x0000000000000004
5+
_Z2f1v
6+
/object/testfiles/dwarf/tombstone.cpp:8
7+
0x00000000000005a0
8+
main
9+
/object/testfiles/dwarf/tombstone.cpp:9
10+
0x00000000000005a4
11+
main
12+
/object/testfiles/dwarf/tombstone.cpp:14
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
0x0000000000001740
2+
main
3+
/object/testfiles/dwarf/tombstone.cpp:9
4+
0x0000000000001744
5+
main
6+
/object/testfiles/dwarf/tombstone.cpp:14

tests/testinput.rs

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use std::path::PathBuf;
2+
use std::process::Command;
3+
use std::{env, fs};
4+
5+
use libtest_mimic::{Arguments, Failed, Trial};
6+
7+
fn main() {
8+
if cfg!(target_os = "windows") {
9+
// Tests don't currently handle newline differences on Windows.
10+
return;
11+
}
12+
13+
let args = Arguments::from_args();
14+
libtest_mimic::run(&args, make_tests()).exit();
15+
}
16+
17+
fn make_tests() -> Vec<Trial> {
18+
let testinput = PathBuf::from("testinput/dwarf");
19+
let testoutput = PathBuf::from("testoutput/dwarf");
20+
21+
let mut tests = Vec::new();
22+
let mut dirs = vec![(testinput, testoutput)];
23+
while let Some((in_dir, out_dir)) = dirs.pop() {
24+
for entry in out_dir.read_dir().unwrap() {
25+
let entry = entry.unwrap();
26+
let out_path = entry.path();
27+
let mut in_path = in_dir.clone();
28+
in_path.push(entry.file_name());
29+
30+
let file_type = entry.file_type().unwrap();
31+
if file_type.is_dir() {
32+
dirs.push((in_path, out_path));
33+
} else if file_type.is_file() {
34+
tests.push(Trial::test(
35+
format!("addr2line -e {}", in_path.display()),
36+
move || run_test(in_path, out_path),
37+
));
38+
}
39+
}
40+
}
41+
tests
42+
}
43+
44+
fn run_test(in_path: PathBuf, out_path: PathBuf) -> Result<(), Failed> {
45+
let mut exe = env::current_exe().unwrap();
46+
assert!(exe.pop());
47+
if exe.file_name().unwrap().to_str().unwrap() == "deps" {
48+
assert!(exe.pop());
49+
}
50+
exe.push("addr2line");
51+
assert!(exe.is_file());
52+
53+
let mut cmd = Command::new(exe);
54+
cmd.env("RUST_BACKTRACE", "1");
55+
cmd.arg("--exe").arg(in_path).arg("--all").arg("-afi");
56+
57+
let output = cmd.output().unwrap();
58+
assert!(output.status.success());
59+
let out_data = output.stdout;
60+
61+
if env::var_os("ADDR2LINE_TESTOUTPUT_UPDATE").is_some() {
62+
fs::write(out_path, &out_data).unwrap();
63+
return Ok(());
64+
}
65+
66+
let expect_out_data = fs::read(out_path).unwrap();
67+
if out_data != expect_out_data {
68+
let out_str = String::from_utf8_lossy(&out_data);
69+
let expect_out_str = String::from_utf8_lossy(&expect_out_data);
70+
return Err(
71+
format!("output mismatch\nexpected:\n{expect_out_str}\nactual:\n{out_str}").into(),
72+
);
73+
}
74+
75+
Ok(())
76+
}

0 commit comments

Comments
 (0)