Skip to content

Commit

Permalink
Merge pull request #196 from rust-lang/work-without-debuginfo
Browse files Browse the repository at this point in the history
Fall back to `dladdr` on Unix in more places
  • Loading branch information
alexcrichton authored Jun 3, 2019
2 parents 577e602 + 861faf1 commit 21f4d73
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 78 deletions.
6 changes: 4 additions & 2 deletions ci/azure-test-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,7 @@ steps:
displayName: "Test backtrace (-default + dbghelp + std + verify-winapi)"
- bash: cd ./crates/cpp_smoke_test && cargo test
displayName: "Test cpp_smoke_test"
- bash: cd ./crates/without_debuginfo && cargo test
displayName: "Test without debuginfo"
- bash: cd ./crates/without_debuginfo && cargo test --features libbacktrace
displayName: "Test without debuginfo (libbacktrace)"
- bash: cd ./crates/without_debuginfo && cargo test --features 'libbacktrace coresymbolication'
displayName: "Test without debuginfo (coresymbolication)"
20 changes: 18 additions & 2 deletions crates/without_debuginfo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@ version = "0.1.0"
authors = ["Alex Crichton <[email protected]>"]
edition = "2018"

[dependencies]
backtrace = { path = "../.." }
[dependencies.backtrace]
path = "../.."
default-features = false
features = [
# make sure a trace can be acquired
'libunwind',
'dbghelp',

# Allow fallback to dladdr
'dladdr',

# Yes, we have `std`
'std',
]

[profile.dev]
debug = false

[profile.test]
debug = false

[features]
libbacktrace = ['backtrace/libbacktrace']
coresymbolication = ['backtrace/coresymbolication']
18 changes: 9 additions & 9 deletions src/symbolize/coresymbolication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ use core::mem;
use core::ptr;
use core::slice;

use libc::{self, c_char, c_int, Dl_info};
use libc::{self, c_char, c_int};

use symbolize::ResolveWhat;
use symbolize::dladdr;
use types::{c_void, BytesOrWideString};
use SymbolName;

Expand All @@ -55,14 +56,14 @@ pub enum Symbol {
name: *const c_char,
addr: *mut c_void,
},
Dladdr(Dl_info),
Dladdr(dladdr::Symbol),
}

impl Symbol {
pub fn name(&self) -> Option<SymbolName> {
let name = match *self {
Symbol::Core { name, .. } => name,
Symbol::Dladdr(ref info) => info.dli_sname,
Symbol::Dladdr(ref info) => return info.name(),
};
if name.is_null() {
None
Expand All @@ -77,7 +78,7 @@ impl Symbol {
pub fn addr(&self) -> Option<*mut c_void> {
match *self {
Symbol::Core { addr, .. } => Some(addr),
Symbol::Dladdr(ref info) => Some(info.dli_saddr as *mut _),
Symbol::Dladdr(ref info) => info.addr(),
}
}

Expand Down Expand Up @@ -269,10 +270,9 @@ pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
if try_resolve(addr, cb) {
return;
}
let mut info: Dl_info = mem::zeroed();
if libc::dladdr(addr as *mut _, &mut info) != 0 {
dladdr::resolve(addr, &mut |sym| {
cb(&super::Symbol {
inner: Symbol::Dladdr(info),
});
}
inner: Symbol::Dladdr(sym),
})
})
}
123 changes: 77 additions & 46 deletions src/symbolize/dladdr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,63 +8,94 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Symbolication strategy using `dladdr`
//!
//! The `dladdr` API is available on most Unix implementations but it's quite
//! basic, not handling inline frame information at all. Since it's so prevalent
//! though we have an option to use it!
//! Common support for resolving with `dladdr`, often used as a fallback if
//! other strategies don't work.

use core::{mem, slice};
#![allow(dead_code)]

use types::{BytesOrWideString, c_void};
use libc::{self, Dl_info};
use symbolize::ResolveWhat;
cfg_if! {
if #[cfg(all(unix, not(target_os = "emscripten"), feature = "dladdr"))] {
use core::{mem, slice};

use SymbolName;
use types::{BytesOrWideString, c_void};
use libc::{self, Dl_info};

pub struct Symbol {
inner: Dl_info,
}
use SymbolName;

pub struct Symbol {
inner: Dl_info,
}

impl Symbol {
pub fn name(&self) -> Option<SymbolName> {
if self.inner.dli_sname.is_null() {
None
} else {
let ptr = self.inner.dli_sname as *const u8;
unsafe {
let len = libc::strlen(self.inner.dli_sname);
Some(SymbolName::new(slice::from_raw_parts(ptr, len)))
}
}
}

pub fn addr(&self) -> Option<*mut c_void> {
Some(self.inner.dli_saddr as *mut _)
}

impl Symbol {
pub fn name(&self) -> Option<SymbolName> {
if self.inner.dli_sname.is_null() {
None
} else {
let ptr = self.inner.dli_sname as *const u8;
unsafe {
let len = libc::strlen(self.inner.dli_sname);
Some(SymbolName::new(slice::from_raw_parts(ptr, len)))
pub fn filename_raw(&self) -> Option<BytesOrWideString> {
None
}

#[cfg(feature = "std")]
pub fn filename(&self) -> Option<&::std::path::Path> {
None
}

pub fn lineno(&self) -> Option<u32> {
None
}
}
}

pub fn addr(&self) -> Option<*mut c_void> {
Some(self.inner.dli_saddr as *mut _)
}
pub unsafe fn resolve(addr: *mut c_void, cb: &mut FnMut(Symbol)) {
let mut info = Symbol {
inner: mem::zeroed(),
};
if libc::dladdr(addr as *mut _, &mut info.inner) != 0 {
cb(info)
}
}
} else {
use types::{BytesOrWideString, c_void};
use symbolize::SymbolName;

pub fn filename_raw(&self) -> Option<BytesOrWideString> {
None
}
pub enum Symbol {}

#[cfg(feature = "std")]
pub fn filename(&self) -> Option<&::std::path::Path> {
None
}
impl Symbol {
pub fn name(&self) -> Option<SymbolName> {
match *self {}
}

pub fn lineno(&self) -> Option<u32> {
None
}
}
pub fn addr(&self) -> Option<*mut c_void> {
match *self {}
}

pub fn filename_raw(&self) -> Option<BytesOrWideString> {
match *self {}
}

#[cfg(feature = "std")]
pub fn filename(&self) -> Option<&::std::path::Path> {
match *self {}
}

pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
let addr = what.address_or_ip();
let mut info: super::Symbol = super::Symbol {
inner: Symbol {
inner: mem::zeroed(),
},
};
if libc::dladdr(addr as *mut _, &mut info.inner.inner) != 0 {
cb(&info)
pub fn lineno(&self) -> Option<u32> {
match *self {}
}
}

pub unsafe fn resolve(addr: *mut c_void, cb: &mut FnMut(Symbol)) {
drop((addr, cb));
}
}
}
51 changes: 51 additions & 0 deletions src/symbolize/dladdr_resolve.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Symbolication strategy using `dladdr`
//!
//! The `dladdr` API is available on most Unix implementations but it's quite
//! basic, not handling inline frame information at all. Since it's so prevalent
//! though we have an option to use it!

use types::{BytesOrWideString, c_void};
use symbolize::{dladdr, SymbolName, ResolveWhat};

pub struct Symbol(dladdr::Symbol);

impl Symbol {
pub fn name(&self) -> Option<SymbolName> {
self.0.name()
}

pub fn addr(&self) -> Option<*mut c_void> {
self.0.addr()
}

pub fn filename_raw(&self) -> Option<BytesOrWideString> {
self.0.filename_raw()
}

#[cfg(feature = "std")]
pub fn filename(&self) -> Option<&::std::path::Path> {
self.0.filename()
}

pub fn lineno(&self) -> Option<u32> {
self.0.lineno()
}
}

pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
dladdr::resolve(what.address_or_ip(), &mut |sym| {
cb(&super::Symbol {
inner: Symbol(sym),
})
});
}
53 changes: 37 additions & 16 deletions src/symbolize/libbacktrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,10 @@
extern crate backtrace_sys as bt;

use core::{ptr, slice};

use libc::{self, c_char, c_int, c_void, uintptr_t};

use SymbolName;

use symbolize::ResolveWhat;
use symbolize::{ResolveWhat, SymbolName};
use symbolize::dladdr;
use types::BytesOrWideString;

pub enum Symbol {
Expand All @@ -56,6 +54,7 @@ pub enum Symbol {
function: *const c_char,
symname: *const c_char,
},
Dladdr(dladdr::Symbol),
}

impl Symbol {
Expand Down Expand Up @@ -90,13 +89,15 @@ impl Symbol {
}
symbol(symname)
}
Symbol::Dladdr(ref s) => s.name(),
}
}

pub fn addr(&self) -> Option<*mut c_void> {
let pc = match *self {
Symbol::Syminfo { pc, .. } => pc,
Symbol::Pcinfo { pc, .. } => pc,
Symbol::Dladdr(ref s) => return s.addr(),
};
if pc == 0 {
None
Expand All @@ -115,6 +116,7 @@ impl Symbol {
Some(slice::from_raw_parts(ptr, len))
}
}
Symbol::Dladdr(_) => None,
}
}

Expand Down Expand Up @@ -146,6 +148,7 @@ impl Symbol {
match *self {
Symbol::Syminfo { .. } => None,
Symbol::Pcinfo { lineno, .. } => Some(lineno as u32),
Symbol::Dladdr(ref s) => s.lineno(),
}
}
}
Expand Down Expand Up @@ -425,7 +428,7 @@ pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
// backtrace errors are currently swept under the rug
let state = init_state();
if state.is_null() {
return;
return dladdr_fallback(what.address_or_ip(), cb);
}

// Call the `backtrace_syminfo` API first. This is (from reading the code)
Expand All @@ -434,15 +437,33 @@ pub unsafe fn resolve(what: ResolveWhat, cb: &mut FnMut(&super::Symbol)) {
//
// Note that we do this since `syminfo` will consult the symbol table,
// finding symbol names even if there's no debug information in the binary.
let mut syminfo_state = SyminfoState {
pc: symaddr,
cb: cb,
};
bt::backtrace_syminfo(
state,
symaddr as uintptr_t,
syminfo_cb,
error_cb,
&mut syminfo_state as *mut _ as *mut _,
);
let mut called = false;
{
let mut syminfo_state = SyminfoState {
pc: symaddr,
cb: &mut |sym| {
called = true;
cb(sym);
},
};
bt::backtrace_syminfo(
state,
symaddr as uintptr_t,
syminfo_cb,
error_cb,
&mut syminfo_state as *mut _ as *mut _,
);
}

if !called {
dladdr_fallback(what.address_or_ip(), cb);
}
}

unsafe fn dladdr_fallback(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
dladdr::resolve(addr, &mut |sym| {
cb(&super::Symbol {
inner: Symbol::Dladdr(sym),
})
});
}
Loading

0 comments on commit 21f4d73

Please sign in to comment.