Skip to content

Commit

Permalink
dbgutil: automatically switch to the kernel if booting from preboot
Browse files Browse the repository at this point in the history
  • Loading branch information
Qix- committed Jul 30, 2024
1 parent 5a24686 commit 06835ec
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 4 deletions.
31 changes: 29 additions & 2 deletions dbgutil/oro_debug_suite/cmd/boot.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import gdb # type: ignore
import os
from os import path
from ..log import log, error
from ..log import log, error, warn, debug
from .. import gdb_util
import subprocess
from ..service import QEMU
from ..service import QEMU, SYMBOLS


class BootCmd(gdb.Command):
Expand Down Expand Up @@ -283,6 +283,16 @@ def copyfile(src, dst):
with gdb_util.parameter("confirm", False):
gdb.execute(f"file {limine_path}", to_string=False, from_tty=True)

# Set an auto-switch breakpoint if we found one
kernel_will_switch_sym = SYMBOLS.get_kernel_will_transfer()
if kernel_will_switch_sym:
log("setting kernel switch breakpoint")
SwitchKernelBreakpoint(kernel_will_switch_sym, kernel_path)
else:
warn(
"no kernel switch symbol found; will not automatically switch to kernel image"
)

if auto_continue:
log("setting _start breakpoint")
gdb.Breakpoint("_start", internal=True, temporary=True, qualified=True)
Expand All @@ -294,5 +304,22 @@ def copyfile(src, dst):
log("(note: _start breakpoint was NOT set)")


class SwitchKernelBreakpoint(gdb.Breakpoint):
def __init__(self, at, switch_to_file):
super(SwitchKernelBreakpoint, self).__init__(
at, internal=True, temporary=True, qualified=True
)
self.silent = True
self._switch_to_file = switch_to_file

def stop(self):
debug(
"preboot environment is about to jump to kernel; switching to kernel image file"
)
with gdb_util.parameter("confirm", False):
gdb.execute(f"file {self._switch_to_file}", to_string=False, from_tty=True)
return False # don't stop


BootCmd()
BootCmdLimine()
26 changes: 25 additions & 1 deletion dbgutil/oro_debug_suite/service/autosym.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,24 @@

## AArch64: AT S1E1R instruction stub
SYM_AARCH64_ATS1E1R = "oro_arch_aarch64::dbgutil::__oro_dbgutil_ATS1E1R"
## AArch64: Transfer to kernel function hook
SYM_AARCH64_KERNEL_TRANSFER = (
"oro_arch_aarch64::dbgutil::__oro_dbgutil_kernel_will_transfer"
)
## x86_64: Transfer to kernel function hook
SYM_X86_64_KERNEL_TRANSFER = (
"oro_arch_x86_64::dbgutil::__oro_dbgutil_kernel_will_transfer"
)

TRACKED_SYMBOLS = frozenset(set([("f", SYM_AARCH64_ATS1E1R)]))
TRACKED_SYMBOLS = frozenset(
set(
[
("f", SYM_AARCH64_ATS1E1R),
("f", SYM_AARCH64_KERNEL_TRANSFER),
("f", SYM_X86_64_KERNEL_TRANSFER),
]
)
)

SYMBOL_FUNCTION_DOMAIN = (
gdb.SYMBOL_FUNCTION_DOMAIN
Expand All @@ -23,6 +39,14 @@ def __init__(self):
def get(self, sym):
return self.__symbols.get(sym)

def get_kernel_will_transfer(self):
if self.get(SYM_AARCH64_KERNEL_TRANSFER):
return SYM_AARCH64_KERNEL_TRANSFER
elif self.get(SYM_X86_64_KERNEL_TRANSFER):
return SYM_X86_64_KERNEL_TRANSFER
else:
return None

def _on_objfile_freed(self, objfile):
for _, sym in TRACKED_SYMBOLS:
if sym in self.__symbols and self.__symbols[sym][1] == objfile:
Expand Down
11 changes: 11 additions & 0 deletions oro-arch-aarch64/src/dbgutil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,14 @@ pub extern "C" fn __oro_dbgutil_ATS1E1R() -> ! {
asm!("AT S1E1R, x0", "nop", options(noreturn));
}
}

/// Transfer marker stub for `gdbutil` that allows the debugger to switch
/// to the kernel image at an opportune time.
#[no_mangle]
#[link_section = ".text.force_keep"]
pub extern "C" fn __oro_dbgutil_kernel_will_transfer() {
// SAFETY(qix-): This is a marker function for GDB to switch to the kernel image.
unsafe {
asm!("nop", options(nostack, nomem, preserves_flags));
}
}
2 changes: 1 addition & 1 deletion oro-arch-aarch64/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#![cfg(not(all(doc, not(target_arch = "aarch64"))))]

#[cfg(debug_assertions)]
mod dbgutil;
pub(crate) mod dbgutil;

pub(crate) mod arch;
pub(crate) mod asm;
Expand Down
4 changes: 4 additions & 0 deletions oro-arch-aarch64/src/xfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ pub unsafe fn transfer(
in("x0") stubs_page_table_phys,
);

// Tell dbgutil we're about to switch
#[cfg(debug_assertions)]
crate::dbgutil::__oro_dbgutil_kernel_will_transfer();

// Populate registers and jump to stubs
asm!(
"isb",
Expand Down
18 changes: 18 additions & 0 deletions oro-arch-x86_64/src/dbgutil.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! Stubs and other internal functionality for the `dbgutil` suite
//! of Oro-specific GDB debugging utilities.
#[cfg(not(debug_assertions))]
compile_error!("The `dbgutil` module should only be used in debug builds.");

use core::arch::asm;

/// Transfer marker stub for `gdbutil` that allows the debugger to switch
/// to the kernel image at an opportune time.
#[no_mangle]
#[link_section = ".text.force_keep"]
pub extern "C" fn __oro_dbgutil_kernel_will_transfer() {
// SAFETY(qix-): This is a marker function for GDB to switch to the kernel image.
unsafe {
asm!("nop", options(nostack, nomem, preserves_flags));
}
}
3 changes: 3 additions & 0 deletions oro-arch-x86_64/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
)]
#![cfg(not(all(doc, not(target_arch = "x86_64"))))]

#[cfg(debug_assertions)]
pub(crate) mod dbgutil;

pub(crate) mod arch;
pub(crate) mod asm;
pub(crate) mod mem;
Expand Down
4 changes: 4 additions & 0 deletions oro-arch-x86_64/src/xfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ pub unsafe fn transfer(
let core_id: u64 = transfer_token.core_id;
let core_is_primary: u64 = u64::from(transfer_token.core_is_primary);

// Tell dbgutil we're about to switch
#[cfg(debug_assertions)]
crate::dbgutil::__oro_dbgutil_kernel_will_transfer();

// Jump to stubs.
// SAFETY(qix-): Do NOT use `ax`, `dx`, `cx` for transfer registers.
asm!(
Expand Down

0 comments on commit 06835ec

Please sign in to comment.