diff --git a/headers/os/arch/m68k/arch_debugger.h b/headers/os/arch/m68k/arch_debugger.h index 8843571eb8..cc2ad42952 100644 --- a/headers/os/arch/m68k/arch_debugger.h +++ b/headers/os/arch/m68k/arch_debugger.h @@ -1,11 +1,11 @@ /* - * Copyright 2005, Haiku Inc. + * Copyright 2005-2009, Haiku Inc. * Distributed under the terms of the MIT License. */ #ifndef _ARCH_M68K_DEBUGGER_H #define _ARCH_M68K_DEBUGGER_H -struct debug_cpu_state { +struct m68k_debug_cpu_state { uint32 d0; uint32 d1; uint32 d2; @@ -24,7 +24,7 @@ struct debug_cpu_state { uint32 a7; uint32 pc; uint16 sr; -#warning M68K: missing members! +//#warning M68K: missing members! uint32 dummy; } __attribute__((aligned(8))); diff --git a/headers/os/arch/mipsel/arch_debugger.h b/headers/os/arch/mipsel/arch_debugger.h index 17a8210873..29f87d71e4 100644 --- a/headers/os/arch/mipsel/arch_debugger.h +++ b/headers/os/arch/mipsel/arch_debugger.h @@ -5,9 +5,11 @@ #ifndef _ARCH_MIPSEL_DEBUGGER_H #define _ARCH_MIPSEL_DEBUGGER_H -#warning MIPSEL: fixme -struct debug_cpu_state { + +//#warning MIPSEL: fixme +struct mipsel_debug_cpu_state { uint32 dummy; } __attribute__((aligned(8))); + #endif // _ARCH_MIPSEL_DEBUGGER_H diff --git a/headers/os/arch/ppc/arch_debugger.h b/headers/os/arch/ppc/arch_debugger.h index 0f82da4911..be5f704566 100644 --- a/headers/os/arch/ppc/arch_debugger.h +++ b/headers/os/arch/ppc/arch_debugger.h @@ -1,12 +1,14 @@ /* - * Copyright 2005, Haiku Inc. + * Copyright 2005-2009, Haiku Inc. * Distributed under the terms of the MIT License. */ #ifndef _ARCH_PPC_DEBUGGER_H #define _ARCH_PPC_DEBUGGER_H -struct debug_cpu_state { + +struct ppc_debug_cpu_state { uint32 dummy; } __attribute__((aligned(8))); + #endif // _ARCH_PPC_DEBUGGER_H diff --git a/headers/os/arch/x86/arch_debugger.h b/headers/os/arch/x86/arch_debugger.h index 13e4415176..dbe686e3b6 100644 --- a/headers/os/arch/x86/arch_debugger.h +++ b/headers/os/arch/x86/arch_debugger.h @@ -1,12 +1,47 @@ /* - * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. + * Copyright 2005-2009, Haiku Inc. * Distributed under the terms of the MIT License. */ #ifndef _ARCH_X86_DEBUGGER_H #define _ARCH_X86_DEBUGGER_H -struct debug_cpu_state { - uint8 extended_regs[512]; + +typedef struct x86_fp_register { + uint8 value[10]; + uint8 reserved[6]; +} x86_fp_register; + + +typedef struct x86_xmm_register { + uint8 value[16]; +} x86_xmm_register; + + +typedef struct x86_extended_registers { + uint16 control; + uint16 status; + uint8 tag; + uint8 reserved1; + uint16 opcode; + uint32 instruction_pointer; + uint16 cs; + uint16 reserved2; + uint32 data_pointer; + uint16 ds; + uint16 reserved3; + uint32 mxcsr; + uint32 mxcsr_mask; + union { + x86_fp_register fp_registers[8]; // st0-st7 + x86_fp_register mmx_registers[8]; // mm0-mm7 + }; + x86_xmm_register xmm_registers[8]; // xmm0-xmm7 + uint8 reserved4[224]; // 288 - 512 +} x86_extended_registers; + + +struct x86_debug_cpu_state { + x86_extended_registers extended_registers; uint32 gs; uint32 fs; @@ -27,6 +62,7 @@ struct debug_cpu_state { uint32 eflags; uint32 user_esp; uint32 user_ss; -} __attribute__((aligned(8))); +} __attribute__((aligned(16))); + #endif // _ARCH_X86_DEBUGGER_H diff --git a/headers/os/kernel/debugger.h b/headers/os/kernel/debugger.h index 65b9e0801a..ce903b3a92 100644 --- a/headers/os/kernel/debugger.h +++ b/headers/os/kernel/debugger.h @@ -11,19 +11,23 @@ #include // include architecture specific definitions +#include +#include +#include +#include + #ifdef __INTEL__ - #include + typedef struct x86_debug_cpu_state debug_cpu_state; #elif __POWERPC__ - #include + typedef struct ppc_debug_cpu_state debug_cpu_state; #elif __M68K__ - #include + typedef struct m68k_debug_cpu_state debug_cpu_state; #elif __MIPSEL__ - #include + typedef struct mipsel_debug_cpu_state debug_cpu_state; #else - #error you need to write a /arch_debugger.h> + #error unsupported architecture #endif -typedef struct debug_cpu_state debug_cpu_state; #ifdef __cplusplus extern "C" { diff --git a/headers/private/kernel/arch/user_debugger.h b/headers/private/kernel/arch/user_debugger.h index 93b1e87e50..7ab43e1f8a 100644 --- a/headers/private/kernel/arch/user_debugger.h +++ b/headers/private/kernel/arch/user_debugger.h @@ -26,10 +26,8 @@ void arch_destroy_thread_debug_info(struct arch_thread_debug_info *info); void arch_update_thread_single_step(); -void arch_set_debug_cpu_state(const struct debug_cpu_state *cpuState); -void arch_get_debug_cpu_state(struct debug_cpu_state *cpuState); -status_t arch_get_thread_debug_cpu_state(struct thread *thread, - struct debug_cpu_state *cpuState); +void arch_set_debug_cpu_state(const debug_cpu_state *cpuState); +void arch_get_debug_cpu_state(debug_cpu_state *cpuState); status_t arch_set_breakpoint(void *address); status_t arch_clear_breakpoint(void *address); diff --git a/headers/private/kernel/user_debugger.h b/headers/private/kernel/user_debugger.h index 3de07f2a3b..5597fa5dea 100644 --- a/headers/private/kernel/user_debugger.h +++ b/headers/private/kernel/user_debugger.h @@ -252,8 +252,6 @@ status_t _user_install_default_debugger(port_id debuggerPort); port_id _user_install_team_debugger(team_id team, port_id debuggerPort); status_t _user_remove_team_debugger(team_id team); status_t _user_debug_thread(thread_id thread); -status_t _user_get_thread_cpu_state(thread_id thread, - struct debug_cpu_state *cpuState); void _user_wait_for_debugger(void); status_t _user_set_debugger_breakpoint(void *address, uint32 type, diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index 558df6970e..97f1f79af7 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -7,9 +7,9 @@ #include +#include #include #include -#include #include #include @@ -19,7 +19,6 @@ extern "C" { #endif -struct debug_cpu_state; struct dirent; struct Elf32_Sym; struct fd_info; @@ -422,8 +421,6 @@ extern port_id _kern_install_team_debugger(team_id team, port_id debuggerPort); extern status_t _kern_remove_team_debugger(team_id team); extern status_t _kern_debug_thread(thread_id thread); -extern status_t _kern_get_thread_cpu_state(thread_id threadID, - struct debug_cpu_state *userCPUState); extern void _kern_wait_for_debugger(void); extern status_t _kern_set_debugger_breakpoint(void *address, uint32 type, diff --git a/src/bin/gdb/gdb/i386-haiku-nat.c b/src/bin/gdb/gdb/i386-haiku-nat.c index af72bd4b27..87ef19e6b4 100644 --- a/src/bin/gdb/gdb/i386-haiku-nat.c +++ b/src/bin/gdb/gdb/i386-haiku-nat.c @@ -28,7 +28,7 @@ #include "target.h" /* Offset in `struct debug_cpu_state' where MEMBER is stored. */ -#define REG_OFFSET(member) offsetof (struct debug_cpu_state, member) +#define REG_OFFSET(member) offsetof (struct x86_debug_cpu_state, member) /* At kHaikuI386RegOffset[REGNUM] you'll find the offset in `struct debug_cpu_state' where the GDB register REGNUM is stored. */ @@ -63,7 +63,8 @@ haiku_supply_registers(int reg, const debug_cpu_state *cpuState) int offset = kHaikuI386RegOffset[reg]; regcache_raw_supply (current_regcache, reg, (char*)cpuState + offset); } else { - i387_supply_fxsave (current_regcache, -1, cpuState->extended_regs); + i387_supply_fxsave (current_regcache, -1, + &cpuState->extended_registers); } } @@ -79,7 +80,8 @@ haiku_collect_registers(int reg, debug_cpu_state *cpuState) int offset = kHaikuI386RegOffset[reg]; regcache_raw_collect (current_regcache, reg, (char*)cpuState + offset); } else { - i387_collect_fsave (current_regcache, -1, cpuState->extended_regs); + i387_collect_fxsave (current_regcache, -1, + &cpuState->extended_registers); } } diff --git a/src/system/kernel/arch/m68k/arch_user_debugger.cpp b/src/system/kernel/arch/m68k/arch_user_debugger.cpp index e1909e4a3f..028c63c012 100644 --- a/src/system/kernel/arch/m68k/arch_user_debugger.cpp +++ b/src/system/kernel/arch/m68k/arch_user_debugger.cpp @@ -65,25 +65,17 @@ arch_update_thread_single_step() void -arch_set_debug_cpu_state(const struct debug_cpu_state *cpuState) +arch_set_debug_cpu_state(const debug_cpu_state *cpuState) { } void -arch_get_debug_cpu_state(struct debug_cpu_state *cpuState) +arch_get_debug_cpu_state(debug_cpu_state *cpuState) { } -status_t -arch_get_thread_debug_cpu_state(struct thread *thread, - struct debug_cpu_state *cpuState) -{ - return B_UNSUPPORTED; -} - - status_t arch_set_breakpoint(void *address) { diff --git a/src/system/kernel/arch/ppc/arch_user_debugger.cpp b/src/system/kernel/arch/ppc/arch_user_debugger.cpp index b4710494a3..99ae27b605 100644 --- a/src/system/kernel/arch/ppc/arch_user_debugger.cpp +++ b/src/system/kernel/arch/ppc/arch_user_debugger.cpp @@ -43,25 +43,17 @@ arch_update_thread_single_step() void -arch_set_debug_cpu_state(const struct debug_cpu_state *cpuState) +arch_set_debug_cpu_state(const debug_cpu_state *cpuState) { } void -arch_get_debug_cpu_state(struct debug_cpu_state *cpuState) +arch_get_debug_cpu_state(debug_cpu_state *cpuState) { } -status_t -arch_get_thread_debug_cpu_state(struct thread *thread, - struct debug_cpu_state *cpuState) -{ - return B_UNSUPPORTED; -} - - status_t arch_set_breakpoint(void *address) { diff --git a/src/system/kernel/arch/x86/arch_user_debugger.cpp b/src/system/kernel/arch/x86/arch_user_debugger.cpp index 7a707bd64f..92298f158d 100644 --- a/src/system/kernel/arch/x86/arch_user_debugger.cpp +++ b/src/system/kernel/arch/x86/arch_user_debugger.cpp @@ -3,6 +3,7 @@ * Distributed under the terms of the MIT License. */ + #include #include @@ -12,6 +13,7 @@ #include #include #include +#include //#define TRACE_ARCH_USER_DEBUGGER @@ -28,7 +30,10 @@ #define B_WATCHPOINT_LENGTH_NOT_SUPPORTED B_NOT_SUPPORTED #define B_BREAKPOINT_NOT_FOUND B_NAME_NOT_FOUND #define B_WATCHPOINT_NOT_FOUND B_NAME_NOT_FOUND - // ToDo: Make those real error codes. + // TODO: Make those real error codes. + + +extern bool gHasSSE; // The software breakpoint instruction (int3). const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; @@ -64,7 +69,7 @@ static bool sQEmuSingleStepHack = false; static void -get_iframe_registers(struct iframe *frame, struct debug_cpu_state *cpuState) +get_iframe_registers(struct iframe *frame, debug_cpu_state *cpuState) { cpuState->gs = frame->gs; cpuState->fs = frame->fs; @@ -576,12 +581,25 @@ arch_update_thread_single_step() void -arch_set_debug_cpu_state(const struct debug_cpu_state *cpuState) +arch_set_debug_cpu_state(const debug_cpu_state *cpuState) { if (struct iframe *frame = i386_get_user_iframe()) { - i386_frstor(cpuState->extended_regs); - // For this to be correct the calling function must not use these - // registers (not even indirectly). + // For the floating point state to be correct the calling function must + // not use these registers (not even indirectly). + if (gHasSSE) { + // Since fxrstor requires 16-byte alignment and this isn't + // guaranteed passed buffer, we use our thread's fpu_state field as + // temporary buffer. We need to disable interrupts to make use of + // it. + struct thread* thread = thread_get_current_thread(); + InterruptsLocker locker; + memcpy(thread->arch_info.fpu_state, &cpuState->extended_registers, + sizeof(&cpuState->extended_registers)); + i386_fxrstor(thread->arch_info.fpu_state); + } else { + // TODO: Implement! We need to convert the format first. +// i386_frstor(&cpuState->extended_registers); + } // frame->gs = cpuState->gs; // frame->fs = cpuState->fs; @@ -608,36 +626,33 @@ arch_set_debug_cpu_state(const struct debug_cpu_state *cpuState) void -arch_get_debug_cpu_state(struct debug_cpu_state *cpuState) +arch_get_debug_cpu_state(debug_cpu_state *cpuState) { if (struct iframe *frame = i386_get_user_iframe()) { - i386_fnsave(cpuState->extended_regs); - // For this to be correct the calling function must not use these - // registers (not even indirectly). + // For the floating point state to be correct the calling function must + // not use these registers (not even indirectly). + if (gHasSSE) { + // Since fxsave requires 16-byte alignment and this isn't guaranteed + // passed buffer, we use our thread's fpu_state field as temporary + // buffer. We need to disable interrupts to make use of it. + struct thread* thread = thread_get_current_thread(); + InterruptsLocker locker; + i386_fxsave(thread->arch_info.fpu_state); + // unlike fnsave, fxsave doesn't reinit the FPU state + memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state, + sizeof(&cpuState->extended_registers)); + } else { + i386_fnsave(&cpuState->extended_registers); + i386_frstor(&cpuState->extended_registers); + // fnsave reinits the FPU state after saving, so we need to + // load it again + // TODO: Convert to fxsave format! + } get_iframe_registers(frame, cpuState); } } -/*! \brief Returns the CPU state for the given thread. - The thread must not be running and the threads spinlock must be held. -*/ -status_t -arch_get_thread_debug_cpu_state(struct thread *thread, - struct debug_cpu_state *cpuState) -{ - struct iframe *frame = i386_get_thread_user_iframe(thread); - if (frame == NULL) - return B_BAD_VALUE; - - get_iframe_registers(frame, cpuState); - memcpy(cpuState->extended_regs, thread->arch_info.fpu_state, - sizeof(cpuState->extended_regs)); - - return B_OK; -} - - status_t arch_set_breakpoint(void *address) { diff --git a/src/system/kernel/debug/user_debugger.cpp b/src/system/kernel/debug/user_debugger.cpp index d6214afb70..2de1c3221e 100644 --- a/src/system/kernel/debug/user_debugger.cpp +++ b/src/system/kernel/debug/user_debugger.cpp @@ -3,6 +3,7 @@ * Distributed under the terms of the MIT License. */ + #include #include #include @@ -2903,49 +2904,6 @@ _user_debug_thread(thread_id threadID) } -status_t -_user_get_thread_cpu_state(thread_id threadID, - struct debug_cpu_state *userCPUState) -{ - TRACE(("[%ld] _user_get_thread_cpu_state(%ld, %p)\n", find_thread(NULL), - threadID, userCPUState)); - - if (userCPUState == NULL || !IS_USER_ADDRESS(userCPUState)) - return B_BAD_ADDRESS; - - InterruptsSpinLocker locker(gThreadSpinlock); - - // get and check the thread - struct thread *thread = thread_get_thread_struct_locked(threadID); - if (thread == NULL) { - // thread doesn't exist any longer - return B_BAD_THREAD_ID; - } else if (thread->team == team_get_kernel_team()) { - // we can't debug the kernel team - return B_NOT_ALLOWED; - } else if (thread->debug_info.flags & B_THREAD_DEBUG_DYING) { - // the thread is already dying - return B_BAD_THREAD_ID; - } else if (thread->debug_info.flags & B_THREAD_DEBUG_NUB_THREAD) { - // don't play with the nub thread - return B_NOT_ALLOWED; - } else if (thread->state == B_THREAD_RUNNING) { - // thread is running -- no way to get its CPU state - return B_BAD_THREAD_STATE; - } - - // get the CPU state - debug_cpu_state cpuState; - status_t error = arch_get_thread_debug_cpu_state(thread, &cpuState); - if (error != B_OK) - return error; - - locker.Unlock(); - - return user_memcpy(userCPUState, &cpuState, sizeof(cpuState)); -} - - void _user_wait_for_debugger(void) {