Skip to content

Commit 036d490

Browse files
Merge #566 from mzohreva/mz/sgx-image-base
Adjust frame IP in SGX relative to image base
2 parents 11e0a4b + 43d7859 commit 036d490

File tree

5 files changed

+108
-11
lines changed

5 files changed

+108
-11
lines changed

src/backtrace/libunwind.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,18 @@ impl Frame {
4040
Frame::Raw(ctx) => ctx,
4141
Frame::Cloned { ip, .. } => return ip,
4242
};
43-
unsafe { uw::_Unwind_GetIP(ctx) as *mut c_void }
43+
#[allow(unused_mut)]
44+
let mut ip = unsafe { uw::_Unwind_GetIP(ctx) as *mut c_void };
45+
46+
// To reduce TCB size in SGX enclaves, we do not want to implement
47+
// symbol resolution functionality. Rather, we can print the offset of
48+
// the address here, which could be later mapped to correct function.
49+
#[cfg(all(target_env = "sgx", target_vendor = "fortanix"))]
50+
{
51+
let image_base = super::get_image_base();
52+
ip = usize::wrapping_sub(ip as usize, image_base as _) as _;
53+
}
54+
ip
4455
}
4556

4657
pub fn sp(&self) -> *mut c_void {

src/backtrace/mod.rs

+33
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,39 @@ impl fmt::Debug for Frame {
125125
}
126126
}
127127

128+
#[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))]
129+
mod sgx_no_std_image_base {
130+
use core::ffi::c_void;
131+
use core::sync::atomic::{AtomicUsize, Ordering::SeqCst};
132+
133+
static IMAGE_BASE: AtomicUsize = AtomicUsize::new(0);
134+
135+
/// Set the image base address. This is only available for Fortanix SGX
136+
/// target when the `std` feature is not enabled. This can be used in the
137+
/// standard library to set the correct base address.
138+
#[doc(hidden)]
139+
pub fn set_image_base(base_addr: *mut c_void) {
140+
IMAGE_BASE.store(base_addr as _, SeqCst);
141+
}
142+
143+
pub(crate) fn get_image_base() -> *mut c_void {
144+
IMAGE_BASE.load(SeqCst) as _
145+
}
146+
}
147+
148+
#[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))]
149+
pub use self::sgx_no_std_image_base::set_image_base;
150+
151+
#[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))]
152+
#[deny(unused)]
153+
pub(crate) use self::sgx_no_std_image_base::get_image_base;
154+
155+
#[cfg(all(target_env = "sgx", target_vendor = "fortanix", feature = "std"))]
156+
#[deny(unused)]
157+
pub(crate) fn get_image_base() -> *mut c_void {
158+
std::os::fortanix_sgx::mem::image_base() as _
159+
}
160+
128161
cfg_if::cfg_if! {
129162
// This needs to come first, to ensure that
130163
// Miri takes priority over the host platform

src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ cfg_if::cfg_if! {
134134
}
135135
}
136136

137+
cfg_if::cfg_if! {
138+
if #[cfg(all(target_env = "sgx", target_vendor = "fortanix", not(feature = "std")))] {
139+
pub use self::backtrace::set_image_base;
140+
}
141+
}
142+
137143
#[allow(dead_code)]
138144
struct Bomb {
139145
enabled: bool,

src/print.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ impl BacktraceFrameFmt<'_, '_, '_> {
219219
#[allow(unused_mut)]
220220
fn print_raw_generic(
221221
&mut self,
222-
mut frame_ip: *mut c_void,
222+
frame_ip: *mut c_void,
223223
symbol_name: Option<SymbolName<'_>>,
224224
filename: Option<BytesOrWideString<'_>>,
225225
lineno: Option<u32>,
@@ -233,15 +233,6 @@ impl BacktraceFrameFmt<'_, '_, '_> {
233233
}
234234
}
235235

236-
// To reduce TCB size in Sgx enclave, we do not want to implement symbol
237-
// resolution functionality. Rather, we can print the offset of the
238-
// address here, which could be later mapped to correct function.
239-
#[cfg(all(feature = "std", target_env = "sgx", target_vendor = "fortanix"))]
240-
{
241-
let image_base = std::os::fortanix_sgx::mem::image_base();
242-
frame_ip = usize::wrapping_sub(frame_ip as usize, image_base as _) as _;
243-
}
244-
245236
// Print the index of the frame as well as the optional instruction
246237
// pointer of the frame. If we're beyond the first symbol of this frame
247238
// though we just print appropriate whitespace.

tests/sgx-image-base.rs

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#![cfg(all(target_env = "sgx", target_vendor = "fortanix"))]
2+
#![feature(sgx_platform)]
3+
4+
#[cfg(feature = "std")]
5+
#[test]
6+
fn sgx_image_base_with_std() {
7+
use backtrace::trace;
8+
9+
let image_base = std::os::fortanix_sgx::mem::image_base();
10+
11+
let mut frame_ips = Vec::new();
12+
trace(|frame| {
13+
frame_ips.push(frame.ip());
14+
true
15+
});
16+
17+
assert!(frame_ips.len() > 0);
18+
for ip in frame_ips {
19+
let ip: u64 = ip as _;
20+
assert!(ip < image_base);
21+
}
22+
}
23+
24+
#[cfg(not(feature = "std"))]
25+
#[test]
26+
fn sgx_image_base_no_std() {
27+
use backtrace::trace_unsynchronized;
28+
29+
fn guess_image_base() -> u64 {
30+
let mut top_frame_ip = None;
31+
unsafe {
32+
trace_unsynchronized(|frame| {
33+
top_frame_ip = Some(frame.ip());
34+
false
35+
});
36+
}
37+
top_frame_ip.unwrap() as u64 & 0xFFFFFF000000
38+
}
39+
40+
let image_base = guess_image_base();
41+
backtrace::set_image_base(image_base as _);
42+
43+
let mut frame_ips = Vec::new();
44+
unsafe {
45+
trace_unsynchronized(|frame| {
46+
frame_ips.push(frame.ip());
47+
true
48+
});
49+
}
50+
51+
assert!(frame_ips.len() > 0);
52+
for ip in frame_ips {
53+
let ip: u64 = ip as _;
54+
assert!(ip < image_base);
55+
}
56+
}

0 commit comments

Comments
 (0)