blob: d1a7008590b8d9d21d415bbf147a01a190e16ed1 [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::task::CurrentTask;
use starnix_uapi::errors::Errno;
use starnix_uapi::from_status_like_fdio;
unsafe extern "C" {
/// breakpoint_for_module_changes is a single breakpoint instruction that is used to notify
/// the debugger about the module changes.
fn breakpoint_for_module_changes();
}
/// Notifies the debugger, if one is attached, that the module list might have been changed.
///
/// For more information about the debugger protocol, see:
/// https://cs.opensource.google/fuchsia/fuchsia/+/master:src/developer/debug/debug_agent/process_handle.h;l=31
///
/// # Parameters:
/// - `current_task`: The task to set the property for. The register's of this task, the instruction
/// pointer specifically, needs to be set to the value with which the task is
/// expected to resume.
pub fn notify_debugger_of_module_list(current_task: &mut CurrentTask) -> Result<(), Errno> {
let break_on_load = current_task
.thread_group()
.process
.get_break_on_load()
.map_err(|err| from_status_like_fdio!(err))?;
// If break on load is 0, there is no debugger attached, so return before issuing the software
// breakpoint.
if break_on_load == 0 {
return Ok(());
}
// For restricted executor, we only need to trigger the debug break on the current thread.
let breakpoint_addr = breakpoint_for_module_changes as *const () as usize as u64;
if breakpoint_addr != break_on_load {
current_task
.thread_group()
.process
.set_break_on_load(&breakpoint_addr)
.map_err(|err| from_status_like_fdio!(err))?;
}
#[allow(
clippy::undocumented_unsafe_blocks,
reason = "Force documented unsafe blocks in Starnix"
)]
unsafe {
breakpoint_for_module_changes();
}
Ok(())
}