Revert Break into the debugger on panic (129019)

This commit is contained in:
Chris Denton 2024-09-25 17:53:57 +00:00
parent b5117538e9
commit d3e59a502b
No known key found for this signature in database
GPG Key ID: 713472F2F45627DE
3 changed files with 1 additions and 170 deletions

View File

@ -23,8 +23,8 @@
use crate::panic::{BacktraceStyle, PanicHookInfo};
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{PoisonError, RwLock};
use crate::sys::backtrace;
use crate::sys::stdio::panic_output;
use crate::sys::{backtrace, dbg};
use crate::{fmt, intrinsics, process, thread};
// Binary interface to the panic runtime that the standard library depends on.
@ -859,14 +859,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg_attr(not(test), rustc_std_internal_symbol)]
#[cfg(not(feature = "panic_immediate_abort"))]
fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
// Break into the debugger if it is attached.
// The return value is not currently used.
//
// This function isn't used anywhere else, and
// using inside `#[panic_handler]` doesn't seem
// to count, so a warning is issued.
let _ = dbg::breakpoint_if_debugging();
let code = unsafe { __rust_start_panic(msg) };
rtabort!("failed to initiate panic, error {code}")
}
@ -874,14 +866,6 @@ fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
#[cfg_attr(not(test), rustc_std_internal_symbol)]
#[cfg(feature = "panic_immediate_abort")]
fn rust_panic(_: &mut dyn PanicPayload) -> ! {
// Break into the debugger if it is attached.
// The return value is not currently used.
//
// This function isn't used anywhere else, and
// using inside `#[panic_handler]` doesn't seem
// to count, so a warning is issued.
let _ = dbg::breakpoint_if_debugging();
unsafe {
crate::intrinsics::abort();
}

View File

@ -1,152 +0,0 @@
//! Debugging aids.
/// Presence of a debugger. The debugger being concerned
/// is expected to use the OS API to debug this process.
#[derive(Copy, Clone, Debug)]
#[allow(unused)]
pub(crate) enum DebuggerPresence {
/// The debugger is attached to this process.
Detected,
/// The debugger is not attached to this process.
NotDetected,
}
#[cfg(target_os = "windows")]
mod os {
use super::DebuggerPresence;
#[link(name = "kernel32")]
extern "system" {
fn IsDebuggerPresent() -> i32;
}
pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
// SAFETY: No state is shared between threads. The call reads
// a field from the Thread Environment Block using the OS API
// as required by the documentation.
if unsafe { IsDebuggerPresent() } != 0 {
Some(DebuggerPresence::Detected)
} else {
Some(DebuggerPresence::NotDetected)
}
}
}
#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
mod os {
use libc::{CTL_KERN, KERN_PROC, KERN_PROC_PID, c_int, sysctl};
use super::DebuggerPresence;
use crate::io::{Cursor, Read, Seek, SeekFrom};
use crate::process;
const P_TRACED: i32 = 0x00000800;
// The assumption is that the kernel structures available to the
// user space may not shrink or repurpose the existing fields over
// time. The kernels normally adhere to that for the backward
// compatibility of the user space.
// The macOS 14.5 SDK comes with a header `MacOSX14.5.sdk/usr/include/sys/sysctl.h`
// that defines `struct kinfo_proc` be of `648` bytes on the 64-bit system. That has
// not changed since macOS 10.13 (released in 2017) at least, validated by building
// a C program in XCode while changing the build target. Apple provides this example
// for reference: https://developer.apple.com/library/archive/qa/qa1361/_index.html.
#[cfg(target_vendor = "apple")]
const KINFO_PROC_SIZE: usize = if cfg!(target_pointer_width = "64") { 648 } else { 492 };
#[cfg(target_vendor = "apple")]
const KINFO_PROC_FLAGS_OFFSET: u64 = if cfg!(target_pointer_width = "64") { 32 } else { 16 };
// Works for FreeBSD stable (13.3, 13.4) and current (14.0, 14.1).
// The size of the structure has stayed the same for a long time,
// at least since 2005:
// https://lists.freebsd.org/pipermail/freebsd-stable/2005-November/019899.html
#[cfg(target_os = "freebsd")]
const KINFO_PROC_SIZE: usize = if cfg!(target_pointer_width = "64") { 1088 } else { 768 };
#[cfg(target_os = "freebsd")]
const KINFO_PROC_FLAGS_OFFSET: u64 = if cfg!(target_pointer_width = "64") { 368 } else { 296 };
pub(super) fn is_debugger_present() -> Option<DebuggerPresence> {
debug_assert_ne!(KINFO_PROC_SIZE, 0);
let mut flags = [0u8; 4]; // `ki_flag` under FreeBSD and `p_flag` under macOS.
let mut mib = [CTL_KERN, KERN_PROC, KERN_PROC_PID, process::id() as c_int];
let mut info_size = KINFO_PROC_SIZE;
let mut kinfo_proc = [0u8; KINFO_PROC_SIZE];
// SAFETY: No state is shared with other threads. The sysctl call
// is safe according to the documentation.
if unsafe {
sysctl(
mib.as_mut_ptr(),
mib.len() as u32,
kinfo_proc.as_mut_ptr().cast(),
&mut info_size,
core::ptr::null_mut(),
0,
)
} != 0
{
return None;
}
debug_assert_eq!(info_size, KINFO_PROC_SIZE);
let mut reader = Cursor::new(kinfo_proc);
reader.seek(SeekFrom::Start(KINFO_PROC_FLAGS_OFFSET)).ok()?;
reader.read_exact(&mut flags).ok()?;
// Just in case, not limiting this to the little-endian systems.
let flags = i32::from_ne_bytes(flags);
if flags & P_TRACED != 0 {
Some(DebuggerPresence::Detected)
} else {
Some(DebuggerPresence::NotDetected)
}
}
}
#[cfg(not(any(target_os = "windows", target_vendor = "apple", target_os = "freebsd")))]
mod os {
pub(super) fn is_debugger_present() -> Option<super::DebuggerPresence> {
None
}
}
/// Detect the debugger presence.
///
/// The code does not try to detect the debugger at all costs (e.g., when anti-debugger
/// tricks are at play), it relies on the interfaces provided by the OS.
///
/// Return value:
/// * `None`: it's not possible to conclude whether the debugger is attached to this
/// process or not. When checking for the presence of the debugger, the detection logic
/// encountered an issue, such as the OS API throwing an error or the feature not being
/// implemented.
/// * `Some(DebuggerPresence::Detected)`: yes, the debugger is attached
/// to this process.
/// * `Some(DebuggerPresence::NotDetected)`: no, the debugger is not
/// attached to this process.
pub(crate) fn is_debugger_present() -> Option<DebuggerPresence> {
if cfg!(miri) { None } else { os::is_debugger_present() }
}
/// Execute the breakpoint instruction if the debugger presence is detected.
/// Useful for breaking into the debugger without the need to set a breakpoint
/// in the debugger.
///
/// Note that there is a race between attaching or detaching the debugger, and running the
/// breakpoint instruction. This is nonetheless memory-safe, like [`crate::process::abort`]
/// is. In case the debugger is attached and the function is about
/// to run the breakpoint instruction yet right before that the debugger detaches, the
/// process will crash due to running the breakpoint instruction and the debugger not
/// handling the trap exception.
pub(crate) fn breakpoint_if_debugging() -> Option<DebuggerPresence> {
let debugger_present = is_debugger_present();
if let Some(DebuggerPresence::Detected) = debugger_present {
// SAFETY: Executing the breakpoint instruction. No state is shared
// or modified by this code.
unsafe { core::intrinsics::breakpoint() };
}
debugger_present
}

View File

@ -11,7 +11,6 @@
pub mod anonymous_pipe;
pub mod backtrace;
pub mod cmath;
pub mod dbg;
pub mod exit_guard;
pub mod os_str;
pub mod path;