* Changed arch_debug_save_registers() to take an arch-specific structure
arch_debug_registers instead.
* Call arch_debug_save_registers() on all CPUs when entering the kernel
debugger.
* Added debug_get_debug_registers() to return a specified CPU's saved
registers.
* x86:
- Replaced the previous arch_debug_save_registers() implementation. Disabled
getting the registers via the gdb interface for the time being.
- Fixed the "sc", "call", and "calling" commands to also work for threads
running on another CPU.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35907 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_ARCH_ARM_DEBUG_H
|
||||||
|
#define _KERNEL_ARCH_ARM_DEBUG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct arch_debug_registers {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _KERNEL_ARCH_ARM_DEBUG_H
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include <arch_debug.h>
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ int32 arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
|
|||||||
void* arch_debug_get_interrupt_pc(bool* _isSyscall);
|
void* arch_debug_get_interrupt_pc(bool* _isSyscall);
|
||||||
bool arch_debug_contains_call(struct thread *thread, const char *symbol,
|
bool arch_debug_contains_call(struct thread *thread, const char *symbol,
|
||||||
addr_t start, addr_t end);
|
addr_t start, addr_t end);
|
||||||
void arch_debug_save_registers(int *);
|
void arch_debug_save_registers(struct arch_debug_registers* registers);
|
||||||
void arch_debug_unset_current_thread(void);
|
void arch_debug_unset_current_thread(void);
|
||||||
void arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer,
|
void arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer,
|
||||||
void (*function)(void*), void* parameter);
|
void (*function)(void*), void* parameter);
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_ARCH_M68K_DEBUG_H
|
||||||
|
#define _KERNEL_ARCH_M68K_DEBUG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct arch_debug_registers {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _KERNEL_ARCH_M68K_DEBUG_H
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_ARCH_MIPSEL_DEBUG_H
|
||||||
|
#define _KERNEL_ARCH_MIPSEL_DEBUG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct arch_debug_registers {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _KERNEL_ARCH_MIPSEL_DEBUG_H
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_ARCH_PPC_DEBUG_H
|
||||||
|
#define _KERNEL_ARCH_PPC_DEBUG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct arch_debug_registers {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _KERNEL_ARCH_PPC_DEBUG_H
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_ARCH_X86_DEBUG_H
|
||||||
|
#define _KERNEL_ARCH_X86_DEBUG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct arch_debug_registers {
|
||||||
|
uint32 ebp;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _KERNEL_ARCH_X86_DEBUG_H
|
||||||
@@ -67,6 +67,10 @@
|
|||||||
#define B_KDEBUG_DONT_PARSE_ARGUMENTS (0x01)
|
#define B_KDEBUG_DONT_PARSE_ARGUMENTS (0x01)
|
||||||
#define B_KDEBUG_PIPE_FINAL_RERUN (0x02)
|
#define B_KDEBUG_PIPE_FINAL_RERUN (0x02)
|
||||||
|
|
||||||
|
|
||||||
|
struct arch_debug_registers;
|
||||||
|
|
||||||
|
|
||||||
struct debugger_module_info {
|
struct debugger_module_info {
|
||||||
module_info info;
|
module_info info;
|
||||||
|
|
||||||
@@ -92,8 +96,6 @@ struct debugger_demangle_module_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern int dbg_register_file[B_MAX_CPU_COUNT][14];
|
|
||||||
|
|
||||||
typedef struct debug_page_fault_info {
|
typedef struct debug_page_fault_info {
|
||||||
addr_t fault_address;
|
addr_t fault_address;
|
||||||
addr_t pc;
|
addr_t pc;
|
||||||
@@ -170,6 +172,8 @@ extern status_t debug_get_next_demangled_argument(uint32* _cookie,
|
|||||||
|
|
||||||
extern struct thread* debug_set_debugged_thread(struct thread* thread);
|
extern struct thread* debug_set_debugged_thread(struct thread* thread);
|
||||||
extern struct thread* debug_get_debugged_thread();
|
extern struct thread* debug_get_debugged_thread();
|
||||||
|
extern struct arch_debug_registers* debug_get_debug_registers(int32 cpu);
|
||||||
|
|
||||||
|
|
||||||
extern status_t _user_kernel_debugger(const char *message);
|
extern status_t _user_kernel_debugger(const char *message);
|
||||||
extern void _user_debug_output(const char *userString);
|
extern void _user_debug_output(const char *userString);
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ return 0;
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_debug_save_registers(int *regs)
|
arch_debug_save_registers(struct arch_debug_registers* registers)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ return 0;
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_debug_save_registers(int *regs)
|
arch_debug_save_registers(struct arch_debug_registers* registers)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ extern struct iframe_stack gBootFrameStack;
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_debug_save_registers(int* regs)
|
arch_debug_save_registers(struct arch_debug_registers* registers)
|
||||||
{
|
{
|
||||||
#warning IMPLEMENT arch_debug_save_registers
|
#warning IMPLEMENT arch_debug_save_registers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ return 0;
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_debug_save_registers(int *regs)
|
arch_debug_save_registers(struct arch_debug_registers* registers)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -357,8 +357,19 @@ setup_for_thread(char *arg, struct thread **_thread, uint32 *_ebp,
|
|||||||
write_cr3(newPageDirectory);
|
write_cr3(newPageDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thread->state == B_THREAD_RUNNING) {
|
||||||
|
// The thread is currently running on another CPU.
|
||||||
|
if (thread->cpu == NULL)
|
||||||
|
return false;
|
||||||
|
arch_debug_registers* registers = debug_get_debug_registers(
|
||||||
|
thread->cpu->cpu_num);
|
||||||
|
if (registers == NULL)
|
||||||
|
return false;
|
||||||
|
*_ebp = registers->ebp;
|
||||||
|
} else {
|
||||||
// read %ebp from the thread's stack stored by a pushad
|
// read %ebp from the thread's stack stored by a pushad
|
||||||
*_ebp = thread->arch_info.current_stack.esp[2];
|
*_ebp = thread->arch_info.current_stack.esp[2];
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
thread = NULL;
|
thread = NULL;
|
||||||
}
|
}
|
||||||
@@ -896,6 +907,15 @@ cmd_in_context(int argc, char** argv)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
arch_debug_save_registers(struct arch_debug_registers* registers)
|
||||||
|
{
|
||||||
|
// get the caller's frame pointer
|
||||||
|
stack_frame* frame = (stack_frame*)x86_read_ebp();
|
||||||
|
registers->ebp = (addr_t)frame->previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_debug_stack_trace(void)
|
arch_debug_stack_trace(void)
|
||||||
{
|
{
|
||||||
@@ -910,8 +930,21 @@ arch_debug_contains_call(struct thread *thread, const char *symbol,
|
|||||||
addr_t ebp;
|
addr_t ebp;
|
||||||
if (thread == thread_get_current_thread())
|
if (thread == thread_get_current_thread())
|
||||||
ebp = x86_read_ebp();
|
ebp = x86_read_ebp();
|
||||||
else
|
else {
|
||||||
|
if (thread->state == B_THREAD_RUNNING) {
|
||||||
|
// The thread is currently running on another CPU.
|
||||||
|
if (thread->cpu == NULL)
|
||||||
|
return false;
|
||||||
|
arch_debug_registers* registers = debug_get_debug_registers(
|
||||||
|
thread->cpu->cpu_num);
|
||||||
|
if (registers == NULL)
|
||||||
|
return false;
|
||||||
|
ebp = registers->ebp;
|
||||||
|
} else {
|
||||||
|
// thread not running
|
||||||
ebp = thread->arch_info.current_stack.esp[2];
|
ebp = thread->arch_info.current_stack.esp[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!is_kernel_stack_address(thread, ebp))
|
if (!is_kernel_stack_address(thread, ebp))
|
||||||
|
|||||||
@@ -194,46 +194,6 @@ done:
|
|||||||
FUNCTION_END(reboot)
|
FUNCTION_END(reboot)
|
||||||
|
|
||||||
|
|
||||||
FUNCTION(arch_debug_save_registers):
|
|
||||||
pushl %esi
|
|
||||||
pushl %eax
|
|
||||||
movl 12(%esp), %esi
|
|
||||||
|
|
||||||
movl %eax, 0(%esi)
|
|
||||||
movl %ebx, 4(%esi)
|
|
||||||
movl %ecx, 8(%esi)
|
|
||||||
movl %edx, 12(%esi)
|
|
||||||
|
|
||||||
lea 16(%esp), %eax
|
|
||||||
movl %eax, 16(%esi) // caller's %esp
|
|
||||||
movl %ebp, 20(%esi)
|
|
||||||
|
|
||||||
movl 4(%esp), %eax
|
|
||||||
movl %eax, 24(%esi) // caller's %esi
|
|
||||||
movl %edi, 28(%esi)
|
|
||||||
|
|
||||||
movl 8(%esp), %eax
|
|
||||||
movl %eax, 32(%esi) // caller's %ebp
|
|
||||||
|
|
||||||
pushfl
|
|
||||||
popl %eax
|
|
||||||
movl %eax, 36(%esi)
|
|
||||||
|
|
||||||
xor %eax, %eax
|
|
||||||
movw %cs, %ax
|
|
||||||
movl %eax, 40(%esi)
|
|
||||||
movw %ss, %ax
|
|
||||||
movl %eax, 44(%esi)
|
|
||||||
movw %ds, %ax
|
|
||||||
movl %eax, 48(%esi)
|
|
||||||
movw %es, %ax
|
|
||||||
movl %eax, 52(%esi)
|
|
||||||
|
|
||||||
popl %eax
|
|
||||||
popl %esi
|
|
||||||
ret
|
|
||||||
FUNCTION_END(arch_debug_save_registers)
|
|
||||||
|
|
||||||
/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
|
/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
|
||||||
FUNCTION(arch_cpu_user_memcpy):
|
FUNCTION(arch_cpu_user_memcpy):
|
||||||
pushl %esi
|
pushl %esi
|
||||||
|
|||||||
@@ -80,9 +80,7 @@ void call_modules_hook(bool enter);
|
|||||||
|
|
||||||
static void syslog_write(const char* text, int32 length, bool notify);
|
static void syslog_write(const char* text, int32 length, bool notify);
|
||||||
|
|
||||||
|
static arch_debug_registers sDebugRegisters[B_MAX_CPU_COUNT];
|
||||||
int dbg_register_file[B_MAX_CPU_COUNT][14];
|
|
||||||
/* XXXmpetit -- must be made generic */
|
|
||||||
|
|
||||||
static debug_page_fault_info sPageFaultInfo;
|
static debug_page_fault_info sPageFaultInfo;
|
||||||
|
|
||||||
@@ -939,7 +937,7 @@ enter_kernel_debugger(int32 cpu)
|
|||||||
smp_intercpu_int_handler(cpu);
|
smp_intercpu_int_handler(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
arch_debug_save_registers(&dbg_register_file[cpu][0]);
|
arch_debug_save_registers(&sDebugRegisters[cpu]);
|
||||||
sPreviousDprintfState = set_dprintf_enabled(true);
|
sPreviousDprintfState = set_dprintf_enabled(true);
|
||||||
|
|
||||||
if (!gKernelStartup && sDebuggerOnCPU != cpu && smp_get_num_cpus() > 1) {
|
if (!gKernelStartup && sDebuggerOnCPU != cpu && smp_get_num_cpus() > 1) {
|
||||||
@@ -1692,6 +1690,8 @@ debug_trap_cpu_in_kdl(int32 cpu, bool returnIfHandedOver)
|
|||||||
if (sCPUTrapped[cpu])
|
if (sCPUTrapped[cpu])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
arch_debug_save_registers(&sDebugRegisters[cpu]);
|
||||||
|
|
||||||
sCPUTrapped[cpu] = true;
|
sCPUTrapped[cpu] = true;
|
||||||
|
|
||||||
while (sInDebugger != 0) {
|
while (sInDebugger != 0) {
|
||||||
@@ -1992,6 +1992,16 @@ debug_get_next_demangled_argument(uint32* _cookie, const char* symbol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct arch_debug_registers*
|
||||||
|
debug_get_debug_registers(int32 cpu)
|
||||||
|
{
|
||||||
|
if (cpu < 0 || cpu > smp_get_num_cpus())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &sDebugRegisters[cpu];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct thread*
|
struct thread*
|
||||||
debug_set_debugged_thread(struct thread* thread)
|
debug_set_debugged_thread(struct thread* thread)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ gdb_parse_command(void)
|
|||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
// command 'g' is used for reading the register
|
// command 'g' is used for reading the register
|
||||||
@@ -247,6 +248,10 @@ gdb_parse_command(void)
|
|||||||
// dump in *big endian* format.
|
// dump in *big endian* format.
|
||||||
cpu = smp_get_current_cpu();
|
cpu = smp_get_current_cpu();
|
||||||
gdb_regreply(dbg_register_file[cpu], 14);
|
gdb_regreply(dbg_register_file[cpu], 14);
|
||||||
|
#else
|
||||||
|
(void)gdb_regreply;
|
||||||
|
gdb_reply("E01");
|
||||||
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user