aboutsummaryrefslogtreecommitdiff
path: root/vendor/addr2line/tests/correctness.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/addr2line/tests/correctness.rs')
-rw-r--r--vendor/addr2line/tests/correctness.rs126
1 files changed, 126 insertions, 0 deletions
diff --git a/vendor/addr2line/tests/correctness.rs b/vendor/addr2line/tests/correctness.rs
new file mode 100644
index 0000000..73ee462
--- /dev/null
+++ b/vendor/addr2line/tests/correctness.rs
@@ -0,0 +1,126 @@
+use addr2line::Context;
+use fallible_iterator::FallibleIterator;
+use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
+use object::Object;
+use std::borrow::Cow;
+use std::fs::File;
+use std::sync::Arc;
+
+fn find_debuginfo() -> memmap2::Mmap {
+ let path = std::env::current_exe().unwrap();
+ let file = File::open(&path).unwrap();
+ let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
+ let file = &object::File::parse(&*map).unwrap();
+ if let Ok(uuid) = file.mach_uuid() {
+ for candidate in path.parent().unwrap().read_dir().unwrap() {
+ let path = candidate.unwrap().path();
+ if !path.to_str().unwrap().ends_with(".dSYM") {
+ continue;
+ }
+ for candidate in path.join("Contents/Resources/DWARF").read_dir().unwrap() {
+ let path = candidate.unwrap().path();
+ let file = File::open(&path).unwrap();
+ let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
+ let file = &object::File::parse(&*map).unwrap();
+ if file.mach_uuid().unwrap() == uuid {
+ return map;
+ }
+ }
+ }
+ }
+
+ return map;
+}
+
+#[test]
+fn correctness() {
+ let map = find_debuginfo();
+ let file = &object::File::parse(&*map).unwrap();
+ let module_base = file.relative_address_base();
+
+ let endian = if file.is_little_endian() {
+ gimli::RunTimeEndian::Little
+ } else {
+ gimli::RunTimeEndian::Big
+ };
+
+ fn load_section<'data: 'file, 'file, O, Endian>(
+ id: gimli::SectionId,
+ file: &'file O,
+ endian: Endian,
+ ) -> Result<gimli::EndianArcSlice<Endian>, gimli::Error>
+ where
+ O: object::Object<'data, 'file>,
+ Endian: gimli::Endianity,
+ {
+ use object::ObjectSection;
+
+ let data = file
+ .section_by_name(id.name())
+ .and_then(|section| section.uncompressed_data().ok())
+ .unwrap_or(Cow::Borrowed(&[]));
+ Ok(gimli::EndianArcSlice::new(Arc::from(&*data), endian))
+ }
+
+ let dwarf = gimli::Dwarf::load(|id| load_section(id, file, endian)).unwrap();
+ let ctx = Context::from_dwarf(dwarf).unwrap();
+ let mut split_dwarf_loader = addr2line::builtin_split_dwarf_loader::SplitDwarfLoader::new(
+ |data, endian| gimli::EndianArcSlice::new(Arc::from(&*data), endian),
+ None,
+ );
+
+ let mut bias = None;
+ TargetSharedLibrary::each(|lib| {
+ bias = Some((lib.virtual_memory_bias().0 as u64).wrapping_sub(module_base));
+ IterationControl::Break
+ });
+
+ #[allow(unused_mut)]
+ let mut test = |sym: u64, expected_prefix: &str| {
+ let ip = sym.wrapping_sub(bias.unwrap());
+
+ let frames = ctx.find_frames(ip);
+ let frames = split_dwarf_loader.run(frames).unwrap();
+ let frame = frames.last().unwrap().unwrap();
+ let name = frame.function.as_ref().unwrap().demangle().unwrap();
+ // Old rust versions generate DWARF with wrong linkage name,
+ // so only check the start.
+ if !name.starts_with(expected_prefix) {
+ panic!("incorrect name '{}', expected {:?}", name, expected_prefix);
+ }
+ };
+
+ test(test_function as u64, "correctness::test_function");
+ test(
+ small::test_function as u64,
+ "correctness::small::test_function",
+ );
+ test(auxiliary::foo as u64, "auxiliary::foo");
+}
+
+mod small {
+ pub fn test_function() {
+ println!("y");
+ }
+}
+
+fn test_function() {
+ println!("x");
+}
+
+#[test]
+fn zero_function() {
+ let map = find_debuginfo();
+ let file = &object::File::parse(&*map).unwrap();
+ let ctx = Context::new(file).unwrap();
+ for probe in 0..10 {
+ assert!(
+ ctx.find_frames(probe)
+ .skip_all_loads()
+ .unwrap()
+ .count()
+ .unwrap()
+ < 10
+ );
+ }
+}