// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License..

//! A library for acquiring a backtrace at runtime
//!
//! This library is meant to supplement the `RUST_BACKTRACE=1` support of the
//! standard library by allowing an acquisition of a backtrace at runtime
//! programmatically. The backtraces generated by this library do not need to be
//! parsed, for example, and expose the functionality of multiple backend
//! implementations.
//!
//! # Usage
//!
//! First, add this to your Cargo.toml
//!
//! ```toml
//! [dependencies]
//! sgx_backtrace = "1.1.2"
//! ```
//!
//! Next:
//!
//! ```
//! extern crate sgx_backtrace;
//!
//! fn main() {
//! # // Unsafe here so test passes on no_std.
//! # #[cfg(feature = "std")] {
//!     sgx_backtrace::set_enclave_path("enclave.signed.so");
//!     sgx_backtrace::trace(|frame| {
//!         let ip = frame.ip();
//!         let symbol_address = frame.symbol_address();
//!
//!         // Resolve this instruction pointer to a symbol name
//!         sgx_backtrace::resolve_frame(frame, |symbol| {
//!             if let Some(name) = symbol.name() {
//!                 // ...
//!             }
//!             if let Some(filename) = symbol.filename() {
//!                 // ...
//!             }
//!         });
//!
//!         true // keep going to the next frame
//!     });
//! }
//! # }
//! ```
#![no_std]
#![cfg_attr(
    all(target_env = "sgx", target_vendor = "mesalock", feature = "std"),
    feature(rustc_private)
)]
#![cfg_attr(feature = "nostd", feature(panic_unwind))]
#![allow(clippy::missing_safety_doc)]

#[cfg(all(not(target_env = "sgx"), feature = "std"))]
#[macro_use]
extern crate sgx_tstd as std;
#[cfg(all(target_env = "sgx", feature = "std"))]
#[macro_use]
extern crate std;

extern crate alloc;
extern crate sgx_backtrace_sys as bt;

#[cfg(feature = "nostd")]
#[allow(unused_extern_crates)]
extern crate sgx_unwind;

#[macro_use]
extern crate sgx_types;
extern crate sgx_demangle;
extern crate sgx_libc as libc;
extern crate sgx_trts;

#[cfg(feature = "serialize")]
extern crate sgx_serialize;
#[cfg(feature = "serialize")]
#[macro_use]
extern crate sgx_serialize_derive;

pub use self::backtrace::{trace_unsynchronized, Frame};
mod backtrace;

pub use self::symbolize::resolve_frame_unsynchronized;
pub use self::symbolize::set_enclave_path;
pub use self::symbolize::{resolve_unsynchronized, Symbol, SymbolName};
mod symbolize;

pub use self::types::BytesOrWideString;
mod types;

#[cfg(feature = "std")]
pub use self::symbolize::clear_symbol_cache;

mod print;
pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt};
cfg_if! {
    if #[cfg(feature = "std")] {
        pub use self::backtrace::trace;
        pub use self::symbolize::{resolve, resolve_frame};
        pub use self::capture::{Backtrace, BacktraceFrame, BacktraceSymbol};
        mod capture;
    }
}

#[allow(dead_code)]
struct Bomb {
    enabled: bool,
}

#[allow(dead_code)]
impl Drop for Bomb {
    fn drop(&mut self) {
        if self.enabled {
            panic!("cannot panic during the backtrace function");
        }
    }
}

#[allow(dead_code)]
#[cfg(feature = "std")]
mod lock {
    use std::boxed::Box;
    use std::cell::Cell;
    use std::sync::{Once, SgxMutex, SgxMutexGuard};

    pub struct LockGuard(Option<SgxMutexGuard<'static, ()>>);

    static mut LOCK: *mut SgxMutex<()> = 0 as *mut _;
    static INIT: Once = Once::new();
    thread_local!(static LOCK_HELD: Cell<bool> = Cell::new(false));

    impl Drop for LockGuard {
        fn drop(&mut self) {
            if self.0.is_some() {
                LOCK_HELD.with(|slot| {
                    assert!(slot.get());
                    slot.set(false);
                });
            }
        }
    }

    pub fn lock() -> LockGuard {
        if LOCK_HELD.with(|l| l.get()) {
            return LockGuard(None);
        }
        LOCK_HELD.with(|s| s.set(true));
        unsafe {
            INIT.call_once(|| {
                LOCK = Box::into_raw(Box::new(SgxMutex::new(())));
            });
            LockGuard(Some((*LOCK).lock().unwrap()))
        }
    }
}
