mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-14 20:03:29 +00:00
Kernel: Add ptrace commands for reading/writing the debug registers
This adds PT_PEEKDEBUG and PT_POKEDEBUG to allow for reading/writing the debug registers, and updates the Kernel's debug handler to read the new information from the debug status register.
This commit is contained in:
parent
97a4c627cb
commit
3123ffb19d
|
@ -363,14 +363,15 @@ void debug_handler(TrapFrame* trap)
|
|||
PANIC("Debug exception in ring 0");
|
||||
}
|
||||
constexpr u8 REASON_SINGLESTEP = 14;
|
||||
bool is_reason_singlestep = (read_dr6() & (1 << REASON_SINGLESTEP));
|
||||
if (!is_reason_singlestep)
|
||||
auto debug_status = read_dr6();
|
||||
auto should_trap_mask = (1 << REASON_SINGLESTEP) | 0b1111;
|
||||
if ((debug_status & should_trap_mask) == 0)
|
||||
return;
|
||||
|
||||
if (auto tracer = process.tracer()) {
|
||||
tracer->set_regs(regs);
|
||||
}
|
||||
current_thread->send_urgent_signal_to_self(SIGTRAP);
|
||||
write_dr6(debug_status & ~(should_trap_mask));
|
||||
}
|
||||
|
||||
EH_ENTRY_NO_CODE(3, breakpoint);
|
||||
|
|
|
@ -153,6 +153,19 @@ static KResultOr<u32> handle_ptrace(const Kernel::Syscall::SC_ptrace_params& par
|
|||
return EFAULT;
|
||||
return peer->process().poke_user_data(Userspace<u32*> { (FlatPtr)params.addr }, params.data);
|
||||
|
||||
case PT_PEEKDEBUG: {
|
||||
Kernel::Syscall::SC_ptrace_peek_params peek_params {};
|
||||
if (!copy_from_user(&peek_params, reinterpret_cast<Kernel::Syscall::SC_ptrace_peek_params*>(params.addr)))
|
||||
return EFAULT;
|
||||
auto result = peer->peek_debug_register(reinterpret_cast<uintptr_t>(peek_params.address));
|
||||
if (result.is_error())
|
||||
return result.error();
|
||||
if (!copy_to_user(peek_params.out_data, &result.value()))
|
||||
return EFAULT;
|
||||
break;
|
||||
}
|
||||
case PT_POKEDEBUG:
|
||||
return peer->poke_debug_register(reinterpret_cast<uintptr_t>(params.addr), params.data);
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
@ -229,4 +242,56 @@ KResult Process::poke_user_data(Userspace<u32*> address, u32 data)
|
|||
return KSuccess;
|
||||
}
|
||||
|
||||
KResultOr<u32> Thread::peek_debug_register(u32 register_index)
|
||||
{
|
||||
u32 data;
|
||||
switch (register_index) {
|
||||
case 0:
|
||||
data = m_debug_register_state.dr0;
|
||||
break;
|
||||
case 1:
|
||||
data = m_debug_register_state.dr1;
|
||||
break;
|
||||
case 2:
|
||||
data = m_debug_register_state.dr2;
|
||||
break;
|
||||
case 3:
|
||||
data = m_debug_register_state.dr3;
|
||||
break;
|
||||
case 6:
|
||||
data = m_debug_register_state.dr6;
|
||||
break;
|
||||
case 7:
|
||||
data = m_debug_register_state.dr7;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
KResult Thread::poke_debug_register(u32 register_index, u32 data)
|
||||
{
|
||||
switch (register_index) {
|
||||
case 0:
|
||||
m_debug_register_state.dr0 = data;
|
||||
break;
|
||||
case 1:
|
||||
m_debug_register_state.dr1 = data;
|
||||
break;
|
||||
case 2:
|
||||
m_debug_register_state.dr2 = data;
|
||||
break;
|
||||
case 3:
|
||||
m_debug_register_state.dr3 = data;
|
||||
break;
|
||||
case 7:
|
||||
m_debug_register_state.dr7 = data;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -972,6 +972,9 @@ public:
|
|||
u32 signal_mask() const;
|
||||
void clear_signals();
|
||||
|
||||
KResultOr<u32> peek_debug_register(u32 register_index);
|
||||
KResult poke_debug_register(u32 register_index, u32 data);
|
||||
|
||||
void set_dump_backtrace_on_finalization() { m_dump_backtrace_on_finalization = true; }
|
||||
|
||||
DispatchSignalResult dispatch_one_pending_signal();
|
||||
|
|
|
@ -690,6 +690,8 @@ struct rtentry {
|
|||
#define PT_PEEK 7
|
||||
#define PT_POKE 8
|
||||
#define PT_SETREGS 9
|
||||
#define PT_POKEDEBUG 10
|
||||
#define PT_PEEKDEBUG 11
|
||||
|
||||
// Used in struct dirent
|
||||
enum {
|
||||
|
|
|
@ -40,7 +40,8 @@ int ptrace(int request, pid_t tid, void* addr, int data)
|
|||
|
||||
u32 out_data;
|
||||
Syscall::SC_ptrace_peek_params peek_params;
|
||||
if (request == PT_PEEK) {
|
||||
auto is_peek_type = request == PT_PEEK || request == PT_PEEKDEBUG;
|
||||
if (is_peek_type) {
|
||||
peek_params.address = reinterpret_cast<u32*>(addr);
|
||||
peek_params.out_data = &out_data;
|
||||
addr = &peek_params;
|
||||
|
@ -54,7 +55,7 @@ int ptrace(int request, pid_t tid, void* addr, int data)
|
|||
};
|
||||
int rc = syscall(SC_ptrace, ¶ms);
|
||||
|
||||
if (request == PT_PEEK) {
|
||||
if (is_peek_type) {
|
||||
if (rc < 0) {
|
||||
errno = -rc;
|
||||
return -1;
|
||||
|
|
|
@ -39,6 +39,8 @@ __BEGIN_DECLS
|
|||
#define PT_PEEK 7
|
||||
#define PT_POKE 8
|
||||
#define PT_SETREGS 9
|
||||
#define PT_POKEDEBUG 10
|
||||
#define PT_PEEKDEBUG 11
|
||||
|
||||
// FIXME: PID/TID ISSUE
|
||||
// Affects the entirety of LibDebug and Userland/strace.cpp.
|
||||
|
|
Loading…
Reference in a new issue