Clean way to patch the std

This commit is contained in:
2026-03-18 19:58:23 +01:00
parent a087bdd523
commit 9b8afd2c5c
7 changed files with 258 additions and 277 deletions

View File

@@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
backtrace_rs = { package = "backtrace", version = "0.3", default-features = false }
hashbrown = "0.16" hashbrown = "0.16"
os-std-macros = { path = "../os-std-macros" } os-std-macros = { path = "../os-std-macros" }
shared = { path = "../shared", features = ["user"] } shared = { path = "../shared", features = ["user"] }

View File

@@ -6,25 +6,13 @@ patch-std:
@echo "Start patching the std..." @echo "Start patching the std..."
@find {{ PATCH_DIR }} -type f | while read -r patch_file; do \ @find {{ PATCH_DIR }} -type f | while read -r patch_file; do \
relative_path="${patch_file#{{ PATCH_DIR }}/}"; \ relative_path="${patch_file#{{ PATCH_DIR }}/}"; \
case "$patch_file" in \
*.rs) \
echo "📄 [COPY] $relative_path"; \
mkdir -p "{{ SRC_DIR }}/$(dirname "$relative_path")"; \
cp "$patch_file" "{{ SRC_DIR }}/$relative_path"; \
;; \
*.sed) \
target_file="${relative_path%.sed}.rs"; \ target_file="${relative_path%.sed}.rs"; \
if [ -f "{{ SRC_DIR }}/$target_file" ]; then \ if [ -f "{{ SRC_DIR }}/$target_file" ]; then \
echo " [SED] $target_file"; \ echo " [SED] $target_file"; \
sed -i -f "$patch_file" "{{ SRC_DIR }}/$target_file"; \ sed -i -f "$patch_file" "{{ SRC_DIR }}/$target_file"; \
else \ else \
echo "[WARN] target doesn't exist: $target_file"; \ echo " [WARN] target doesn't exist: $target_file"; \
fi \ fi; \
;; \
*) \
echo "❓ [SKIP] Unknown file : $relative_path"; \
;; \
esac; \
done done
@echo "✅ Patching done." @echo "✅ Patching done."
@@ -167,13 +155,14 @@ setup-std:
@just cp_std "sys/io/is_terminal/unsupported.rs" @just cp_std "sys/io/is_terminal/unsupported.rs"
@just cp_std "sys/io/kernel_copy/mod.rs" @just cp_std "sys/io/kernel_copy/mod.rs"
@just cp_std "sys/io/mod.rs" @just cp_std "sys/io/mod.rs"
@just cp_std "sys/io/error/mod.rs"
@just cp_std "sys/pipe/mod.rs" @just cp_std "sys/pipe/mod.rs"
@just cp_std "sys/pipe/unsupported.rs" @just cp_std "sys/pipe/unsupported.rs"
@just cp_std "sys/stdio/mod.rs" @just cp_std "sys/stdio/mod.rs"
@just cp_std "sys/stdio/unsupported.rs" @just cp_std "sys/stdio/unsupported.rs"
@just cp_std "sys/alloc/mod.rs" @just cp_std "sys/alloc/mod.rs"
@just cp_std "sys/backtrace.rs"
@just cp_std "alloc.rs"
@# Copied but edited for the moment @# Copied but edited for the moment
# @just cp_std "sys/process/unsupported.rs" # @just cp_std "sys/process/unsupported.rs"
@just cp_std "sys/io/error/mod.rs"
# @just cp_std "alloc.rs"
# @just cp_std "path.rs" # @just cp_std "path.rs"

View File

@@ -5,11 +5,5 @@ s|alloc::slice::Join|alloc_crate::slice::Join|g
s|alloc::bstr|alloc_crate::bstr|g s|alloc::bstr|alloc_crate::bstr|g
s|alloc::collections::TryReserveError|alloc_crate::collections::TryReserveError|g s|alloc::collections::TryReserveError|alloc_crate::collections::TryReserveError|g
s|crate::collections::VecDeque|alloc_crate::collections::VecDeque|g s|crate::collections::VecDeque|alloc_crate::collections::VecDeque|g
# s|collections::HashMap|hashbrown::HashMap|g
/crate::backtrace_rs/c \ todo!()
/crate::sys::os::getpid/c \ todo!() /crate::sys::os::getpid/c \ todo!()
/\[doc = include_str!/c \ // todo retreive docs /\[doc = include_str!/c \ // todo retreive docs
# /target_os = "xous",/a \ target_os = "survos",
# Ajouter d'autres modifications facilement ici :
# s|ancien_texte|nouveau_texte|g

View File

@@ -340,95 +340,95 @@ pub fn set_alloc_error_hook(hook: fn(Layout)) {
HOOK.store(hook as *mut (), Ordering::Release); HOOK.store(hook as *mut (), Ordering::Release);
} }
// /// Unregisters the current allocation error hook, returning it. /// Unregisters the current allocation error hook, returning it.
// /// ///
// /// *See also the function [`set_alloc_error_hook`].* /// *See also the function [`set_alloc_error_hook`].*
// /// ///
// /// If no custom hook is registered, the default hook will be returned. /// If no custom hook is registered, the default hook will be returned.
// #[unstable(feature = "alloc_error_hook", issue = "51245")] #[unstable(feature = "alloc_error_hook", issue = "51245")]
// pub fn take_alloc_error_hook() -> fn(Layout) { pub fn take_alloc_error_hook() -> fn(Layout) {
// let hook = HOOK.swap(ptr::null_mut(), Ordering::Acquire); let hook = HOOK.swap(ptr::null_mut(), Ordering::Acquire);
// if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } } if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } }
// } }
// #[optimize(size)] #[optimize(size)]
// fn default_alloc_error_hook(layout: Layout) { fn default_alloc_error_hook(layout: Layout) {
// if cfg!(panic = "immediate-abort") { if cfg!(panic = "immediate-abort") {
// return; return;
// } }
// // This is the default path taken on OOM, and the only path taken on stable with std. // This is the default path taken on OOM, and the only path taken on stable with std.
// // Crucially, it does *not* call any user-defined code, and therefore users do not have to // Crucially, it does *not* call any user-defined code, and therefore users do not have to
// // worry about allocation failure causing reentrancy issues. That makes it different from // worry about allocation failure causing reentrancy issues. That makes it different from
// // the default `__rdl_alloc_error_handler` defined in alloc (i.e., the default alloc error // the default `__rdl_alloc_error_handler` defined in alloc (i.e., the default alloc error
// // handler that is called when there is no `#[alloc_error_handler]`), which triggers a // handler that is called when there is no `#[alloc_error_handler]`), which triggers a
// // regular panic and thus can invoke a user-defined panic hook, executing arbitrary // regular panic and thus can invoke a user-defined panic hook, executing arbitrary
// // user-defined code. // user-defined code.
// static PREV_ALLOC_FAILURE: AtomicBool = AtomicBool::new(false); static PREV_ALLOC_FAILURE: AtomicBool = AtomicBool::new(false);
// if PREV_ALLOC_FAILURE.swap(true, Ordering::Relaxed) { if PREV_ALLOC_FAILURE.swap(true, Ordering::Relaxed) {
// // Don't try to print a backtrace if a previous alloc error happened. This likely means // Don't try to print a backtrace if a previous alloc error happened. This likely means
// // there is not enough memory to print a backtrace, although it could also mean that two // there is not enough memory to print a backtrace, although it could also mean that two
// // threads concurrently run out of memory. // threads concurrently run out of memory.
// rtprintpanic!( rtprintpanic!(
// "memory allocation of {} bytes failed\nskipping backtrace printing to avoid potential recursion\n", "memory allocation of {} bytes failed\nskipping backtrace printing to avoid potential recursion\n",
// layout.size() layout.size()
// ); );
// return; return;
// } else { } else {
// rtprintpanic!("memory allocation of {} bytes failed\n", layout.size()); rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
// } }
// let Some(mut out) = crate::sys::stdio::panic_output() else { let Some(mut out) = crate::sys::stdio::panic_output() else {
// return; return;
// }; };
// // Use a lock to prevent mixed output in multithreading context. // Use a lock to prevent mixed output in multithreading context.
// // Some platforms also require it when printing a backtrace, like `SymFromAddr` on Windows. // Some platforms also require it when printing a backtrace, like `SymFromAddr` on Windows.
// // Make sure to not take this lock until after checking PREV_ALLOC_FAILURE to avoid deadlocks // Make sure to not take this lock until after checking PREV_ALLOC_FAILURE to avoid deadlocks
// // when there is too little memory to print a backtrace. // when there is too little memory to print a backtrace.
// let mut lock = crate::sys::backtrace::lock(); let mut lock = crate::sys::backtrace::lock();
// match crate::panic::get_backtrace_style() { match crate::panic::get_backtrace_style() {
// Some(crate::panic::BacktraceStyle::Short) => { Some(crate::panic::BacktraceStyle::Short) => {
// drop(lock.print(&mut out, crate::backtrace_rs::PrintFmt::Short)) drop(lock.print(&mut out, crate::backtrace_rs::PrintFmt::Short))
// } }
// Some(crate::panic::BacktraceStyle::Full) => { Some(crate::panic::BacktraceStyle::Full) => {
// drop(lock.print(&mut out, crate::backtrace_rs::PrintFmt::Full)) drop(lock.print(&mut out, crate::backtrace_rs::PrintFmt::Full))
// } }
// Some(crate::panic::BacktraceStyle::Off) => { Some(crate::panic::BacktraceStyle::Off) => {
// use crate::io::Write; use crate::io::Write;
// let _ = writeln!( let _ = writeln!(
// out, out,
// "note: run with `RUST_BACKTRACE=1` environment variable to display a \ "note: run with `RUST_BACKTRACE=1` environment variable to display a \
// backtrace" backtrace"
// ); );
// if cfg!(miri) { if cfg!(miri) {
// let _ = writeln!( let _ = writeln!(
// out, out,
// "note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` \ "note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` \
// for the environment variable to have an effect" for the environment variable to have an effect"
// ); );
// } }
// } }
// // If backtraces aren't supported or are forced-off, do nothing. // If backtraces aren't supported or are forced-off, do nothing.
// None => {} None => {}
// } }
// } }
// #[cfg(not(test))] #[cfg(not(test))]
// #[doc(hidden)] #[doc(hidden)]
// #[alloc_error_handler] #[alloc_error_handler]
// #[unstable(feature = "alloc_internals", issue = "none")] #[unstable(feature = "alloc_internals", issue = "none")]
// pub fn rust_oom(layout: Layout) -> ! { pub fn rust_oom(layout: Layout) -> ! {
// crate::sys::backtrace::__rust_end_short_backtrace(|| { crate::sys::backtrace::__rust_end_short_backtrace(|| {
// let hook = HOOK.load(Ordering::Acquire); let hook = HOOK.load(Ordering::Acquire);
// let hook: fn(Layout) = let hook: fn(Layout) =
// if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } }; if hook.is_null() { default_alloc_error_hook } else { unsafe { mem::transmute(hook) } };
// hook(layout); hook(layout);
// crate::process::abort() crate::process::abort()
// }) })
// } }
#[cfg(not(test))] #[cfg(not(test))]
#[doc(hidden)] #[doc(hidden)]

View File

@@ -295,6 +295,7 @@ pub mod sync;
pub mod sys; pub mod sys;
pub mod thread; pub mod thread;
pub mod time; pub mod time;
pub use backtrace_rs;
#[prelude_import] #[prelude_import]
#[allow(unused_imports)] #[allow(unused_imports)]

View File

@@ -286,10 +286,10 @@ fn default_hook(info: &PanicHookInfo<'_>) {
match backtrace { match backtrace {
Some(BacktraceStyle::Short) => { Some(BacktraceStyle::Short) => {
todo!() drop(lock.print(err, crate::backtrace_rs::PrintFmt::Short))
} }
Some(BacktraceStyle::Full) => { Some(BacktraceStyle::Full) => {
todo!() drop(lock.print(err, crate::backtrace_rs::PrintFmt::Full))
} }
Some(BacktraceStyle::Off) => { Some(BacktraceStyle::Off) => {
if FIRST_PANIC.swap(false, Ordering::Relaxed) { if FIRST_PANIC.swap(false, Ordering::Relaxed) {

View File

@@ -1,7 +1,7 @@
//! Common code for printing backtraces. //! Common code for printing backtraces.
#![forbid(unsafe_op_in_unsafe_fn)] #![forbid(unsafe_op_in_unsafe_fn)]
// use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt}; use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt};
use crate::borrow::Cow; use crate::borrow::Cow;
use crate::io::prelude::*; use crate::io::prelude::*;
use crate::path::{self, Path, PathBuf}; use crate::path::{self, Path, PathBuf};
@@ -24,140 +24,136 @@ pub(crate) fn lock<'a>() -> BacktraceLock<'a> {
BacktraceLock(LOCK.lock().unwrap_or_else(PoisonError::into_inner)) BacktraceLock(LOCK.lock().unwrap_or_else(PoisonError::into_inner))
} }
// impl BacktraceLock<'_> { impl BacktraceLock<'_> {
// /// Prints the current backtrace. /// Prints the current backtrace.
// pub(crate) fn print(&mut self, w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { pub(crate) fn print(&mut self, w: &mut dyn Write, format: PrintFmt) -> io::Result<()> {
// // There are issues currently linking libbacktrace into tests, and in // There are issues currently linking libbacktrace into tests, and in
// // general during std's own unit tests we're not testing this path. In // general during std's own unit tests we're not testing this path. In
// // test mode immediately return here to optimize away any references to the // test mode immediately return here to optimize away any references to the
// // libbacktrace symbols // libbacktrace symbols
// if cfg!(test) { if cfg!(test) {
// return Ok(()); return Ok(());
// } }
// struct DisplayBacktrace { struct DisplayBacktrace {
// format: PrintFmt, format: PrintFmt,
// } }
// impl fmt::Display for DisplayBacktrace { impl fmt::Display for DisplayBacktrace {
// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
// // SAFETY: the backtrace lock is held // SAFETY: the backtrace lock is held
// unsafe { _print_fmt(fmt, self.format) } unsafe { _print_fmt(fmt, self.format) }
// } }
// } }
// write!(w, "{}", DisplayBacktrace { format }) write!(w, "{}", DisplayBacktrace { format })
// } }
// } }
// /// # Safety /// # Safety
// /// ///
// /// This function is not Sync. The caller must hold a mutex lock, or there must be only one thread in the program. /// This function is not Sync. The caller must hold a mutex lock, or there must be only one thread in the program.
// unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::Result { unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::Result {
// // Always 'fail' to get the cwd when running under Miri - // Always 'fail' to get the cwd when running under Miri -
// // this allows Miri to display backtraces in isolation mode // this allows Miri to display backtraces in isolation mode
// let cwd = if !cfg!(miri) { let cwd = if !cfg!(miri) { env::current_dir().ok() } else { None };
// env::current_dir().ok()
// } else {
// None
// };
// let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| { let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| {
// output_filename(fmt, bows, print_fmt, cwd.as_ref()) output_filename(fmt, bows, print_fmt, cwd.as_ref())
// }; };
// writeln!(fmt, "stack backtrace:")?; writeln!(fmt, "stack backtrace:")?;
// let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path); let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path);
// bt_fmt.add_context()?; bt_fmt.add_context()?;
// let mut idx = 0; let mut idx = 0;
// let mut res = Ok(()); let mut res = Ok(());
// let mut omitted_count: usize = 0; let mut omitted_count: usize = 0;
// let mut first_omit = true; let mut first_omit = true;
// // If we're using a short backtrace, ignore all frames until we're told to start printing. // If we're using a short backtrace, ignore all frames until we're told to start printing.
// let mut print = print_fmt != PrintFmt::Short; let mut print = print_fmt != PrintFmt::Short;
// set_image_base(); set_image_base();
// // SAFETY: we roll our own locking in this town // SAFETY: we roll our own locking in this town
// unsafe { unsafe {
// backtrace_rs::trace_unsynchronized(|frame| { backtrace_rs::trace_unsynchronized(|frame| {
// if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
// return false; return false;
// } }
// if cfg!(feature = "backtrace-trace-only") { if cfg!(feature = "backtrace-trace-only") {
// const HEX_WIDTH: usize = 2 + 2 * size_of::<usize>(); const HEX_WIDTH: usize = 2 + 2 * size_of::<usize>();
// let frame_ip = frame.ip(); let frame_ip = frame.ip();
// res = writeln!(bt_fmt.formatter(), "{idx:4}: {frame_ip:HEX_WIDTH$?}"); res = writeln!(bt_fmt.formatter(), "{idx:4}: {frame_ip:HEX_WIDTH$?}");
// } else { } else {
// let mut hit = false; let mut hit = false;
// backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| { backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
// hit = true; hit = true;
// // `__rust_end_short_backtrace` means we are done hiding symbols // `__rust_end_short_backtrace` means we are done hiding symbols
// // for now. Print until we see `__rust_begin_short_backtrace`. // for now. Print until we see `__rust_begin_short_backtrace`.
// if print_fmt == PrintFmt::Short { if print_fmt == PrintFmt::Short {
// if let Some(sym) = symbol.name().and_then(|s| s.as_str()) { if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
// if sym.contains("__rust_end_short_backtrace") { if sym.contains("__rust_end_short_backtrace") {
// print = true; print = true;
// return; return;
// } }
// if print && sym.contains("__rust_begin_short_backtrace") { if print && sym.contains("__rust_begin_short_backtrace") {
// print = false; print = false;
// return; return;
// } }
// if !print { if !print {
// omitted_count += 1; omitted_count += 1;
// } }
// } }
// } }
// if print { if print {
// if omitted_count > 0 { if omitted_count > 0 {
// debug_assert!(print_fmt == PrintFmt::Short); debug_assert!(print_fmt == PrintFmt::Short);
// // only print the message between the middle of frames // only print the message between the middle of frames
// if !first_omit { if !first_omit {
// let _ = writeln!( let _ = writeln!(
// bt_fmt.formatter(), bt_fmt.formatter(),
// " [... omitted {} frame{} ...]", " [... omitted {} frame{} ...]",
// omitted_count, omitted_count,
// if omitted_count > 1 { "s" } else { "" } if omitted_count > 1 { "s" } else { "" }
// ); );
// } }
// first_omit = false; first_omit = false;
// omitted_count = 0; omitted_count = 0;
// } }
// res = bt_fmt.frame().symbol(frame, symbol); res = bt_fmt.frame().symbol(frame, symbol);
// } }
// }); });
// #[cfg(all(target_os = "nto", any(target_env = "nto70", target_env = "nto71")))] #[cfg(all(target_os = "nto", any(target_env = "nto70", target_env = "nto71")))]
// if libc::__my_thread_exit as *mut libc::c_void == frame.ip() { if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
// if !hit && print { if !hit && print {
// use crate::backtrace_rs::SymbolName; use crate::backtrace_rs::SymbolName;
// res = bt_fmt.frame().print_raw( res = bt_fmt.frame().print_raw(
// frame.ip(), frame.ip(),
// Some(SymbolName::new("__my_thread_exit".as_bytes())), Some(SymbolName::new("__my_thread_exit".as_bytes())),
// None, None,
// None, None,
// ); );
// } }
// return false; return false;
// } }
// if !hit && print { if !hit && print {
// res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
// } }
// } }
// idx += 1; idx += 1;
// res.is_ok() res.is_ok()
// }) })
// }; };
// res?; res?;
// bt_fmt.finish()?; bt_fmt.finish()?;
// if print_fmt == PrintFmt::Short { if print_fmt == PrintFmt::Short {
// writeln!( writeln!(
// fmt, fmt,
// "note: Some details are omitted, \ "note: Some details are omitted, \
// run with `RUST_BACKTRACE=full` for a verbose backtrace." run with `RUST_BACKTRACE=full` for a verbose backtrace."
// )?; )?;
// } }
// Ok(()) Ok(())
// } }
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
/// this is only inline(never) when backtraces in std are enabled, otherwise /// this is only inline(never) when backtraces in std are enabled, otherwise
@@ -191,44 +187,44 @@ where
result result
} }
// /// Prints the filename of the backtrace frame. /// Prints the filename of the backtrace frame.
// /// ///
// /// See also `output`. /// See also `output`.
// pub fn output_filename( pub fn output_filename(
// fmt: &mut fmt::Formatter<'_>, fmt: &mut fmt::Formatter<'_>,
// bows: BytesOrWideString<'_>, bows: BytesOrWideString<'_>,
// print_fmt: PrintFmt, print_fmt: PrintFmt,
// cwd: Option<&PathBuf>, cwd: Option<&PathBuf>,
// ) -> fmt::Result { ) -> fmt::Result {
// let file: Cow<'_, Path> = match bows { let file: Cow<'_, Path> = match bows {
// #[cfg(unix)] #[cfg(unix)]
// BytesOrWideString::Bytes(bytes) => { BytesOrWideString::Bytes(bytes) => {
// use crate::os::unix::prelude::*; use crate::os::unix::prelude::*;
// Path::new(crate::ffi::OsStr::from_bytes(bytes)).into() Path::new(crate::ffi::OsStr::from_bytes(bytes)).into()
// } }
// #[cfg(not(unix))] #[cfg(not(unix))]
// BytesOrWideString::Bytes(bytes) => { BytesOrWideString::Bytes(bytes) => {
// Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>")).into() Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>")).into()
// } }
// #[cfg(windows)] #[cfg(windows)]
// BytesOrWideString::Wide(wide) => { BytesOrWideString::Wide(wide) => {
// use crate::os::windows::prelude::*; use crate::os::windows::prelude::*;
// Cow::Owned(crate::ffi::OsString::from_wide(wide).into()) Cow::Owned(crate::ffi::OsString::from_wide(wide).into())
// } }
// #[cfg(not(windows))] #[cfg(not(windows))]
// BytesOrWideString::Wide(_wide) => Path::new("<unknown>").into(), BytesOrWideString::Wide(_wide) => Path::new("<unknown>").into(),
// }; };
// if print_fmt == PrintFmt::Short && file.is_absolute() { if print_fmt == PrintFmt::Short && file.is_absolute() {
// if let Some(cwd) = cwd { if let Some(cwd) = cwd {
// if let Ok(stripped) = file.strip_prefix(&cwd) { if let Ok(stripped) = file.strip_prefix(&cwd) {
// if let Some(s) = stripped.to_str() { if let Some(s) = stripped.to_str() {
// return write!(fmt, ".{}{s}", path::MAIN_SEPARATOR); return write!(fmt, ".{}{s}", path::MAIN_SEPARATOR);
// } }
// } }
// } }
// } }
// fmt::Display::fmt(&file.display(), fmt) fmt::Display::fmt(&file.display(), fmt)
// } }
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
pub fn set_image_base() { pub fn set_image_base() {