Skip to content

Commit a898aae

Browse files
committed
Test gimli without debuginfo
Ensure that it's using the dladdr fallback like other unix platforms.
1 parent 6f25d6f commit a898aae

File tree

3 files changed

+76
-16
lines changed

3 files changed

+76
-16
lines changed

ci/azure-test-all.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,7 @@ steps:
5353
displayName: "Test without debuginfo (libbacktrace)"
5454
- bash: cd ./crates/without_debuginfo && cargo test --features 'libbacktrace coresymbolication'
5555
displayName: "Test without debuginfo (coresymbolication)"
56+
# TODO: there's a bug on stable Rust right now (1.35.0) which prevents testing
57+
# gimli here, so disable this temporarily until 1.36.0 is released.
58+
# - bash: cd ./crates/without_debuginfo && cargo test --features 'libbacktrace gimli-symbolize'
59+
# displayName: "Test without debuginfo (gimli-symbolize)"

crates/without_debuginfo/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ debug = false
2828
[features]
2929
libbacktrace = ['backtrace/libbacktrace']
3030
coresymbolication = ['backtrace/coresymbolication']
31+
gimli-symbolize = ['backtrace/gimli-symbolize']

src/symbolize/gimli.rs

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! all platforms, but it's hoped to be developed over time! Long-term this is
55
//! intended to wholesale replace the `libbacktrace.rs` implementation.
66
7+
use crate::symbolize::dladdr;
78
use crate::symbolize::ResolveWhat;
89
use crate::types::BytesOrWideString;
910
use crate::SymbolName;
@@ -49,7 +50,6 @@ fn mmap(path: &Path) -> Option<Mmap> {
4950
let file = File::open(path).ok()?;
5051
// TODO: not completely safe, see https://github.com/danburkert/memmap-rs/issues/25
5152
unsafe { Mmap::map(&file).ok() }
52-
5353
}
5454

5555
impl Mapping {
@@ -189,8 +189,13 @@ where
189189
});
190190
}
191191

192-
pub fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
192+
pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
193193
let addr = what.address_or_ip();
194+
let mut cb = DladdrFallback {
195+
cb,
196+
addr,
197+
called: false,
198+
};
194199

195200
// First, find the file containing the segment that the given AVMA (after
196201
// relocation) address falls within. Use the containing segment to compute
@@ -248,7 +253,7 @@ pub fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
248253
let sym = super::Symbol {
249254
inner: Symbol::new(addr.0 as usize, file, line, name),
250255
};
251-
cb(&sym);
256+
cb.call(&sym);
252257
found_sym = true;
253258
}
254259
}
@@ -259,22 +264,55 @@ pub fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
259264
let sym = super::Symbol {
260265
inner: Symbol::new(addr.0 as usize, None, None, Some(name.to_string())),
261266
};
262-
cb(&sym);
267+
cb.call(&sym);
263268
}
264269
}
265270
});
271+
272+
drop(cb);
273+
}
274+
275+
struct DladdrFallback<'a, 'b> {
276+
addr: *mut c_void,
277+
called: bool,
278+
cb: &'a mut (FnMut(&super::Symbol) + 'b),
279+
}
280+
281+
impl DladdrFallback<'_, '_> {
282+
fn call(&mut self, sym: &super::Symbol) {
283+
self.called = true;
284+
(self.cb)(sym);
285+
}
266286
}
267287

268-
pub struct Symbol {
269-
addr: usize,
270-
file: Option<String>,
271-
line: Option<u64>,
272-
name: Option<String>,
288+
impl Drop for DladdrFallback<'_, '_> {
289+
fn drop(&mut self) {
290+
if self.called {
291+
return;
292+
}
293+
unsafe {
294+
dladdr::resolve(self.addr, &mut |sym| {
295+
(self.cb)(&super::Symbol {
296+
inner: Symbol::Dladdr(sym),
297+
})
298+
});
299+
}
300+
}
301+
}
302+
303+
pub enum Symbol {
304+
Dladdr(dladdr::Symbol),
305+
Gimli {
306+
addr: usize,
307+
file: Option<String>,
308+
line: Option<u64>,
309+
name: Option<String>,
310+
},
273311
}
274312

275313
impl Symbol {
276314
fn new(addr: usize, file: Option<String>, line: Option<u64>, name: Option<String>) -> Symbol {
277-
Symbol {
315+
Symbol::Gimli {
278316
addr,
279317
file,
280318
line,
@@ -283,25 +321,42 @@ impl Symbol {
283321
}
284322

285323
pub fn name(&self) -> Option<SymbolName> {
286-
self.name.as_ref().map(|s| SymbolName::new(s.as_bytes()))
324+
match self {
325+
Symbol::Dladdr(s) => s.name(),
326+
Symbol::Gimli { name, .. } => name.as_ref().map(|s| SymbolName::new(s.as_bytes())),
327+
}
287328
}
288329

289330
pub fn addr(&self) -> Option<*mut c_void> {
290-
Some(self.addr as *mut c_void)
331+
match self {
332+
Symbol::Dladdr(s) => s.addr(),
333+
Symbol::Gimli { addr, .. } => Some(*addr as *mut c_void),
334+
}
291335
}
292336

293337
pub fn filename_raw(&self) -> Option<BytesOrWideString> {
294-
self.file
295-
.as_ref()
338+
let file = match self {
339+
Symbol::Dladdr(s) => return s.filename_raw(),
340+
Symbol::Gimli { file, .. } => file,
341+
};
342+
file.as_ref()
296343
.map(|f| BytesOrWideString::Bytes(f.as_bytes()))
297344
}
298345

299346
pub fn filename(&self) -> Option<&Path> {
300-
self.file.as_ref().map(Path::new)
347+
let file = match self {
348+
Symbol::Dladdr(s) => return s.filename(),
349+
Symbol::Gimli { file, .. } => file,
350+
};
351+
file.as_ref().map(Path::new)
301352
}
302353

303354
pub fn lineno(&self) -> Option<u32> {
304-
self.line.and_then(|l| {
355+
let line = match self {
356+
Symbol::Dladdr(s) => return s.lineno(),
357+
Symbol::Gimli { line, .. } => line,
358+
};
359+
line.and_then(|l| {
305360
if l > (u32::MAX as u64) {
306361
None
307362
} else {

0 commit comments

Comments
 (0)