1 extern crate addr2line;
2 extern crate memmap;
3 extern crate object;
4 
5 use std::borrow::Cow;
6 use std::env;
7 use std::fs::File;
8 use std::path::{self, PathBuf};
9 
10 use object::Object;
11 
release_fixture_path() -> PathBuf12 fn release_fixture_path() -> PathBuf {
13     if let Ok(p) = env::var("ADDR2LINE_FIXTURE_PATH") {
14         return p.into();
15     }
16 
17     let mut path = PathBuf::new();
18     if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") {
19         path.push(dir);
20     }
21     path.push("fixtures");
22     path.push("addr2line-release");
23     path
24 }
25 
with_file<F: FnOnce(&object::File)>(target: &path::Path, f: F)26 fn with_file<F: FnOnce(&object::File)>(target: &path::Path, f: F) {
27     let file = File::open(target).unwrap();
28     let map = unsafe { memmap::Mmap::map(&file).unwrap() };
29     let file = object::File::parse(&*map).unwrap();
30     f(&file)
31 }
32 
dwarf_load<'a>(object: &object::File<'a>) -> gimli::Dwarf<Cow<'a, [u8]>>33 fn dwarf_load<'a>(object: &object::File<'a>) -> gimli::Dwarf<Cow<'a, [u8]>> {
34     let load_section = |id: gimli::SectionId| -> Result<Cow<'a, [u8]>, gimli::Error> {
35         use object::ObjectSection;
36 
37         let data = object
38             .section_by_name(id.name())
39             .and_then(|section| section.data().ok())
40             .unwrap_or(&[][..]);
41         Ok(Cow::Borrowed(data))
42     };
43     gimli::Dwarf::load(&load_section).unwrap()
44 }
45 
dwarf_borrow<'a>( dwarf: &'a gimli::Dwarf<Cow<[u8]>>, ) -> gimli::Dwarf<gimli::EndianSlice<'a, gimli::LittleEndian>>46 fn dwarf_borrow<'a>(
47     dwarf: &'a gimli::Dwarf<Cow<[u8]>>,
48 ) -> gimli::Dwarf<gimli::EndianSlice<'a, gimli::LittleEndian>> {
49     let borrow_section: &dyn for<'b> Fn(
50         &'b Cow<[u8]>,
51     ) -> gimli::EndianSlice<'b, gimli::LittleEndian> =
52         &|section| gimli::EndianSlice::new(&*section, gimli::LittleEndian);
53     dwarf.borrow(&borrow_section)
54 }
55 
56 #[test]
parse_base_rc()57 fn parse_base_rc() {
58     let target = release_fixture_path();
59 
60     with_file(&target, |file| {
61         addr2line::ObjectContext::new(file).unwrap();
62     });
63 }
64 
65 #[test]
parse_base_slice()66 fn parse_base_slice() {
67     let target = release_fixture_path();
68 
69     with_file(&target, |file| {
70         let dwarf = dwarf_load(file);
71         let dwarf = dwarf_borrow(&dwarf);
72         addr2line::Context::from_dwarf(dwarf).unwrap();
73     });
74 }
75 
76 #[test]
parse_lines_rc()77 fn parse_lines_rc() {
78     let target = release_fixture_path();
79 
80     with_file(&target, |file| {
81         let context = addr2line::ObjectContext::new(file).unwrap();
82         context.parse_lines().unwrap();
83     });
84 }
85 
86 #[test]
parse_lines_slice()87 fn parse_lines_slice() {
88     let target = release_fixture_path();
89 
90     with_file(&target, |file| {
91         let dwarf = dwarf_load(file);
92         let dwarf = dwarf_borrow(&dwarf);
93         let context = addr2line::Context::from_dwarf(dwarf).unwrap();
94         context.parse_lines().unwrap();
95     });
96 }
97 
98 #[test]
parse_functions_rc()99 fn parse_functions_rc() {
100     let target = release_fixture_path();
101 
102     with_file(&target, |file| {
103         let context = addr2line::ObjectContext::new(file).unwrap();
104         context.parse_functions().unwrap();
105     });
106 }
107 
108 #[test]
parse_functions_slice()109 fn parse_functions_slice() {
110     let target = release_fixture_path();
111 
112     with_file(&target, |file| {
113         let dwarf = dwarf_load(file);
114         let dwarf = dwarf_borrow(&dwarf);
115         let context = addr2line::Context::from_dwarf(dwarf).unwrap();
116         context.parse_functions().unwrap();
117     });
118 }
119