Skip to content
This repository was archived by the owner on Mar 24, 2022. It is now read-only.

Commit ed2f7c2

Browse files
committed
add rudimentary backtrace support, still needs to be cleaned up
1 parent 5c8bb55 commit ed2f7c2

11 files changed

Lines changed: 90 additions & 8 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lucet-runtime/lucet-runtime-internals/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ edition = "2018"
1212
[dependencies]
1313
lucet-module = { path = "../../lucet-module", version = "0.1.1" }
1414

15+
backtrace = "0.3"
1516
bitflags = "1.0"
1617
bincode = "1.1.4"
1718
byteorder = "1.3"

lucet-runtime/lucet-runtime-internals/src/instance.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::module::{self, FunctionHandle, FunctionPointer, Global, GlobalValue,
1313
use crate::region::RegionInternal;
1414
use crate::val::{UntypedRetVal, Val};
1515
use crate::WASM_PAGE_SIZE;
16+
use backtrace::Backtrace;
1617
use libc::{c_void, siginfo_t, uintptr_t};
1718
use lucet_module::InstanceRuntimeData;
1819
use memoffset::offset_of;
@@ -914,6 +915,7 @@ impl Instance {
914915
mut details,
915916
siginfo,
916917
context,
918+
full_backtrace,
917919
} => {
918920
// Sandbox is no longer runnable. It's unsafe to determine all error details in the signal
919921
// handler, so we fill in extra details here.
@@ -924,11 +926,15 @@ impl Instance {
924926
.module
925927
.addr_details(details.rip_addr as *const c_void)?;
926928

929+
details.backtrace = Some(self.module.resolve_and_trim(&full_backtrace));
930+
// dbg!(&details.backtrace);
931+
927932
// fill the state back in with the updated details in case fatal handlers need it
928933
self.state = State::Faulted {
929934
details: details.clone(),
930935
siginfo,
931936
context,
937+
full_backtrace,
932938
};
933939

934940
if details.fatal {
@@ -1109,6 +1115,8 @@ pub struct FaultDetails {
11091115
pub rip_addr: uintptr_t,
11101116
/// Extra information about the instruction pointer's location, if available.
11111117
pub rip_addr_details: Option<module::AddrDetails>,
1118+
/// Backtrace of the frames from the guest stack, if available.
1119+
pub backtrace: Option<Backtrace>,
11121120
}
11131121

11141122
impl std::fmt::Display for FaultDetails {

lucet-runtime/lucet-runtime-internals/src/instance/signals.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::instance::{
55
HOST_CTX,
66
};
77
use crate::sysdeps::UContextPtr;
8+
use backtrace::Backtrace;
89
use lazy_static::lazy_static;
910
use libc::{c_int, c_void, siginfo_t, SIGBUS, SIGSEGV};
1011
use lucet_module::TrapCode;
@@ -214,9 +215,11 @@ extern "C" fn handle_signal(signum: c_int, siginfo_ptr: *mut siginfo_t, ucontext
214215
// Details set to `None` here: have to wait until `verify_trap_safety` to
215216
// fill in these details, because access may not be signal safe.
216217
rip_addr_details: None,
218+
backtrace: None,
217219
},
218220
siginfo,
219221
context: ctx.into(),
222+
full_backtrace: Backtrace::new_unresolved(),
220223
};
221224
true
222225
}

lucet-runtime/lucet-runtime-internals/src/instance/state.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::instance::siginfo_ext::SiginfoExt;
22
use crate::instance::{FaultDetails, TerminationDetails, YieldedVal};
33
use crate::sysdeps::UContext;
4+
use backtrace::Backtrace;
45
use libc::{SIGBUS, SIGSEGV};
56
use std::any::Any;
67
use std::ffi::{CStr, CString};
@@ -26,6 +27,7 @@ pub enum State {
2627
details: FaultDetails,
2728
siginfo: libc::siginfo_t,
2829
context: UContext,
30+
full_backtrace: Backtrace,
2931
},
3032

3133
/// The instance is in the process of terminating.

lucet-runtime/lucet-runtime-internals/src/module.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub use lucet_module::{
1111

1212
use crate::alloc::Limits;
1313
use crate::error::Error;
14+
use backtrace::Backtrace;
1415
use libc::c_void;
1516

1617
/// Details about a program address.
@@ -64,6 +65,8 @@ pub trait ModuleInternal: Send + Sync {
6465

6566
fn addr_details(&self, addr: *const c_void) -> Result<Option<AddrDetails>, Error>;
6667

68+
fn resolve_and_trim(&self, full_bt: &Backtrace) -> Backtrace;
69+
6770
fn get_signature(&self, fn_id: FunctionIndex) -> &Signature;
6871

6972
fn function_handle_from_ptr(&self, ptr: FunctionPointer) -> FunctionHandle {

lucet-runtime/lucet-runtime-internals/src/module/dl.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::error::Error;
22
use crate::module::{AddrDetails, GlobalSpec, HeapSpec, Module, ModuleInternal, TableElement};
3+
use backtrace::{Backtrace, BacktraceFrame};
34
use libc::c_void;
45
use libloading::Library;
56
use lucet_module::{
@@ -242,6 +243,50 @@ impl ModuleInternal for DlModule {
242243
fn get_signature(&self, fn_id: FunctionIndex) -> &Signature {
243244
self.module.module_data.get_signature(fn_id)
244245
}
246+
247+
fn resolve_and_trim(&self, full_bt: &Backtrace) -> Backtrace {
248+
let mut bt = full_bt.clone();
249+
bt.resolve();
250+
let trimmed_frames = bt
251+
.frames()
252+
.iter()
253+
.filter(|fr| match self.addr_details(fr.ip()) {
254+
// if we can look up addr details, and it's in module code, keep the frame
255+
Ok(Some(details)) => details.in_module_code,
256+
_ => false,
257+
})
258+
// // skip everything until the entry to the signal handler
259+
// .skip_while(|fr| {
260+
// fr.symbols()
261+
// .iter()
262+
// .find(|sym| {
263+
// sym.name().map_or(false, |sn| {
264+
// let name = format!("{}", sn);
265+
// name.starts_with(
266+
// "lucet_runtime_internals::instance::signals::handle_signal",
267+
// ) && !name.contains("closure")
268+
// })
269+
// })
270+
// .is_none()
271+
// })
272+
// // drop the handle_signal frame
273+
// .skip(1)
274+
// // take all frames between handle_signal and Context::swap
275+
// .take_while(|fr| {
276+
// fr.symbols()
277+
// .iter()
278+
// .find(|sym| {
279+
// sym.name().map_or(false, |sn| {
280+
// format!("{}", sn)
281+
// .starts_with("lucet_runtime_internals::context::Context::swap")
282+
// })
283+
// })
284+
// .is_none()
285+
// })
286+
.cloned()
287+
.collect::<Vec<BacktraceFrame>>();
288+
trimmed_frames.into()
289+
}
245290
}
246291

247292
// TODO: PR to nix or libloading?

lucet-runtime/lucet-runtime-internals/src/module/mock.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::error::Error;
22
use crate::module::{AddrDetails, GlobalSpec, HeapSpec, Module, ModuleInternal, TableElement};
3+
use backtrace::Backtrace;
34
use libc::c_void;
45
use lucet_module::owned::{
56
OwnedExportFunction, OwnedFunctionMetadata, OwnedGlobalSpec, OwnedImportFunction,
@@ -318,6 +319,14 @@ impl ModuleInternal for MockModule {
318319
Ok(None)
319320
}
320321

322+
fn resolve_and_trim(&self, full_bt: &Backtrace) -> Backtrace {
323+
// for a mock module, just resolve since we can't differentiate between hostcall code and
324+
// mock module functions
325+
let mut bt = full_bt.clone();
326+
bt.resolve();
327+
bt
328+
}
329+
321330
fn get_signature(&self, fn_id: FunctionIndex) -> &Signature {
322331
self.module_data.get_signature(fn_id)
323332
}

lucet-runtime/src/c_api.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use lucet_runtime_internals::c_api::*;
55
use lucet_runtime_internals::instance::{
66
instance_handle_from_raw, instance_handle_to_raw, InstanceInternal,
77
};
8-
use lucet_runtime_internals::vmctx::VmctxInternal;
98
use lucet_runtime_internals::WASM_PAGE_SIZE;
109
use lucet_runtime_internals::{
1110
assert_nonnull, lucet_hostcall_terminate, lucet_hostcalls, with_ffi_arcs,

lucetc/src/decls.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,12 @@ impl<'a> ModuleDecls<'a> {
174174
(None, None) => {
175175
// No import or export for this function. It's local, and we have to make up a
176176
// name.
177-
decls.declare_function(
178-
clif_module,
179-
format!("guest_func_{}", ix),
180-
Linkage::Local,
181-
func_index,
182-
)?;
177+
let name = if let Some(Some(name)) = decls.info.function_names.get(func_index) {
178+
format!("guest_func_{}", name)
179+
} else {
180+
format!("guest_func_{}", ix)
181+
};
182+
decls.declare_function(clif_module, name, Linkage::Local, func_index)?;
183183
}
184184
}
185185
}

0 commit comments

Comments
 (0)