forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#57441 - VardhanThigle:Vardhan/x86_64-fortan…
…ix-unknown-sgx-backtrace-support, r=alexcrichton Supporting backtrace for x86_64-fortanix-unknown-sgx. # Overview Implementing following functions required by `libstd/sys_common` to support `backtrace`: ``` 1. unwind_backtrace 2. trace_fn 3. resolve_symname ``` # Description: The changes here are quite similar to the Cloudabi target `src/libstd/sys/cloudabi/backtrace.rs` The first 2 functions are implemented via calls to libunwind.a that is linked to the `x86_64-fortanix-unknown-sgx` (rust-lang#56979), we have not implemented functionality needed by `resolve_symname` (or `dladdr`) to reduce SGX TCB. Rather, we print the function address (relative to enclave image base) in `resolve_symname` which can be later translated to correct symbol name (say, via `addr2line`). # Note: For `x86_64-fortanix-unknown-sgx`, the `RUST_BACKTRACE` environment has to be set from within the program running in an enclave. cc: @jethrogb r? @alexcrichton
- Loading branch information
Showing
3 changed files
with
82 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,96 @@ | ||
use io; | ||
use sys::unsupported; | ||
use error::Error; | ||
use libc; | ||
use sys_common::backtrace::Frame; | ||
use unwind as uw; | ||
use sys::sgx::abi::mem::image_base; | ||
|
||
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 | ||
} | ||
|
||
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 | ||
} | ||
|
||
pub fn resolve_symname<F>(_frame: Frame, | ||
_callback: F, | ||
// 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}", | ||
(frame.symbol_addr.wrapping_offset_from(image_base() as _))))) | ||
} | ||
|
||
pub fn foreach_symbol_fileline<F>(_: Frame, | ||
_: F, | ||
_: &BacktraceContext) -> io::Result<bool> | ||
where F: FnMut(&[u8], u32) -> io::Result<()> | ||
{ | ||
unsupported() | ||
Ok(false) | ||
} |