diff options
| author | Vardhan Thigle <vardhan.thigle@fortanix.com> | 2019-01-03 10:46:22 +0530 |
|---|---|---|
| committer | Vardhan Thigle <vardhan.thigle@fortanix.com> | 2019-01-08 22:10:55 +0530 |
| commit | 4166a4e5d0ef32ceb0d67d1f5dba334caf439a0d (patch) | |
| tree | 525660bdcae9fa71d55ac3874a07cff0374526f1 | |
| parent | 7ad470c0a64ed0801708cee6657e82be097a29ac (diff) | |
| download | rust-4166a4e5d0ef32ceb0d67d1f5dba334caf439a0d.tar.gz rust-4166a4e5d0ef32ceb0d67d1f5dba334caf439a0d.zip | |
Supporting backtrace for x86_64-fortanix-unknown-sgx.
| -rw-r--r-- | src/libstd/lib.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/sgx/backtrace.rs | 91 |
2 files changed, 83 insertions, 10 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ccfce672e5f..2f35b58106e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -305,7 +305,7 @@ #![feature(maybe_uninit)] #![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"), feature(global_asm, range_contains, slice_index_methods, - decl_macro, coerce_unsized, sgx_platform))] + decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))] #![default_lib_allocator] diff --git a/src/libstd/sys/sgx/backtrace.rs b/src/libstd/sys/sgx/backtrace.rs index 52d4a63bb63..7e792300f43 100644 --- a/src/libstd/sys/sgx/backtrace.rs +++ b/src/libstd/sys/sgx/backtrace.rs @@ -1,21 +1,94 @@ use io; -use sys::unsupported; +use error::Error; +use libc; use sys_common::backtrace::Frame; +use unwind as uw; pub struct BacktraceContext; -pub fn unwind_backtrace(_frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - unsupported() +struct Context<'a> { + idx: usize, + frames: &'a mut [Frame], +} + +#[derive(Debug)] +struct UnwindError(uw::_Unwind_Reason_Code); + +impl Error for UnwindError { + fn description(&self) -> &'static str { + "unexpected return value while unwinding" + } +} + +impl ::fmt::Display for UnwindError { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + write!(f, "{}: {:?}", self.description(), self.0) + } +} + +#[inline(never)] // this function call can be skipped it when tracing. +pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> { + let mut cx = Context { idx: 0, frames }; + let result_unwind = + unsafe { uw::_Unwind_Backtrace(trace_fn, &mut cx as *mut Context as *mut libc::c_void) }; + // See libunwind:src/unwind/Backtrace.c for the return values. + // No, there is no doc. + let res = match result_unwind { + // These return codes seem to be benign and need to be ignored for backtraces + // to show up properly on all tested platforms. + uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => { + Ok((cx.idx, BacktraceContext)) + } + _ => Err(io::Error::new( + io::ErrorKind::Other, + UnwindError(result_unwind), + )), + }; + res } -pub fn resolve_symname<F>(_frame: Frame, - _callback: F, +extern "C" fn trace_fn( + ctx: *mut uw::_Unwind_Context, + arg: *mut libc::c_void, +) -> uw::_Unwind_Reason_Code { + let cx = unsafe { &mut *(arg as *mut Context) }; + if cx.idx >= cx.frames.len() { + return uw::_URC_NORMAL_STOP; + } + + let mut ip_before_insn = 0; + let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void }; + if !ip.is_null() && ip_before_insn == 0 { + // this is a non-signaling frame, so `ip` refers to the address + // after the calling instruction. account for that. + ip = (ip as usize - 1) as *mut _; + } + + let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) }; + cx.frames[cx.idx] = Frame { + symbol_addr: symaddr as *mut u8, + exact_position: ip as *mut u8, + inline_context: 0, + }; + cx.idx += 1; + + uw::_URC_NO_REASON +} + +extern { + static IMAGE_BASE: u8; +} + + +// To reduce TCB size in Sgx enclave, we do not want to implement resolve_symname functionality. +// Rather, we print the offset of the address here, which could be later mapped to correct function. +pub fn resolve_symname<F>(frame: Frame, + callback: F, _: &BacktraceContext) -> io::Result<()> where F: FnOnce(Option<&str>) -> io::Result<()> { - unsupported() + callback(Some(&format!("0x{:x}", + (unsafe {frame.symbol_addr.wrapping_offset_from(&IMAGE_BASE)})))) } pub fn foreach_symbol_fileline<F>(_: Frame, @@ -23,5 +96,5 @@ pub fn foreach_symbol_fileline<F>(_: Frame, _: &BacktraceContext) -> io::Result<bool> where F: FnMut(&[u8], u32) -> io::Result<()> { - unsupported() + Ok(false) } |
