Implemented user debugging support for x86_64.
Reused x86 arch_user_debugger.cpp, with a few minor changes to make the code work for both 32 and 64 bit. Something isn't quite working right, if a breakpoint is hit the kernel will hang. Other than that everything appears to work correctly.
This commit is contained in:
@@ -32,7 +32,7 @@ typedef struct x86_64_extended_registers {
|
|||||||
x86_64_fp_register mmx_registers[8]; // mm0-mm7
|
x86_64_fp_register mmx_registers[8]; // mm0-mm7
|
||||||
};
|
};
|
||||||
x86_64_xmm_register xmm_registers[16]; // xmm0-xmm15
|
x86_64_xmm_register xmm_registers[16]; // xmm0-xmm15
|
||||||
uint8 reserved4[96]; // 416 - 512
|
uint8 reserved2[96]; // 416 - 512
|
||||||
} x86_64_extended_registers;
|
} x86_64_extended_registers;
|
||||||
|
|
||||||
|
|
||||||
@@ -58,8 +58,6 @@ struct x86_64_debug_cpu_state {
|
|||||||
uint64 rcx;
|
uint64 rcx;
|
||||||
uint64 rbx;
|
uint64 rbx;
|
||||||
uint64 rax;
|
uint64 rax;
|
||||||
uint64 vector;
|
|
||||||
uint64 error_code;
|
|
||||||
uint64 rip;
|
uint64 rip;
|
||||||
uint64 cs;
|
uint64 cs;
|
||||||
uint64 rflags;
|
uint64 rflags;
|
||||||
|
|||||||
@@ -263,8 +263,8 @@ typedef struct arch_cpu_info {
|
|||||||
|
|
||||||
struct X86PagingStructures* active_paging_structures;
|
struct X86PagingStructures* active_paging_structures;
|
||||||
|
|
||||||
uint32 dr6; // temporary storage for debug registers (cf.
|
size_t dr6; // temporary storage for debug registers (cf.
|
||||||
uint32 dr7; // x86_exit_user_debug_at_kernel_entry())
|
size_t dr7; // x86_exit_user_debug_at_kernel_entry())
|
||||||
|
|
||||||
// local TSS for this cpu
|
// local TSS for this cpu
|
||||||
struct tss tss;
|
struct tss tss;
|
||||||
|
|||||||
@@ -9,8 +9,12 @@
|
|||||||
#define ARCH_INIT_USER_DEBUG x86_init_user_debug
|
#define ARCH_INIT_USER_DEBUG x86_init_user_debug
|
||||||
|
|
||||||
// number of breakpoints the CPU supports
|
// number of breakpoints the CPU supports
|
||||||
// Actually it supports 4, but DR3 is used to hold the Thread*.
|
// On 32-bit, DR3 is used to hold the Thread*.
|
||||||
#define X86_BREAKPOINT_COUNT 3
|
#ifdef __x86_64__
|
||||||
|
# define X86_BREAKPOINT_COUNT 4
|
||||||
|
#else
|
||||||
|
# define X86_BREAKPOINT_COUNT 3
|
||||||
|
#endif
|
||||||
|
|
||||||
// debug status register DR6
|
// debug status register DR6
|
||||||
enum {
|
enum {
|
||||||
@@ -95,14 +99,14 @@ enum {
|
|||||||
|
|
||||||
struct arch_breakpoint {
|
struct arch_breakpoint {
|
||||||
void *address; // NULL, if deactivated
|
void *address; // NULL, if deactivated
|
||||||
uint32 type; // one of the architecture types above
|
size_t type; // one of the architecture types above
|
||||||
uint32 length; // one of the length values above
|
size_t length; // one of the length values above
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arch_team_debug_info {
|
struct arch_team_debug_info {
|
||||||
struct arch_breakpoint breakpoints[X86_BREAKPOINT_COUNT];
|
struct arch_breakpoint breakpoints[X86_BREAKPOINT_COUNT];
|
||||||
|
|
||||||
uint32 dr7; // debug control register DR7
|
size_t dr7; // debug control register DR7
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arch_thread_debug_info {
|
struct arch_thread_debug_info {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#define _KERNEL_ELF_H
|
#define _KERNEL_ELF_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <elf_common.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <image.h>
|
#include <image.h>
|
||||||
|
|
||||||
@@ -49,9 +50,9 @@ status_t elf_add_memory_image_symbol(image_id id, const char* name,
|
|||||||
addr_t address, size_t size, int32 type);
|
addr_t address, size_t size, int32 type);
|
||||||
status_t elf_init(struct kernel_args *args);
|
status_t elf_init(struct kernel_args *args);
|
||||||
|
|
||||||
status_t _user_read_kernel_image_symbols(image_id id,
|
status_t _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
|
||||||
struct Elf32_Sym* symbolTable, int32* _symbolCount,
|
int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
|
||||||
char* stringTable, size_t* _stringTableSize, addr_t* _imageDelta);
|
addr_t* _imageDelta);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <arch_config.h>
|
#include <arch_config.h>
|
||||||
#include <DiskDeviceDefs.h>
|
#include <DiskDeviceDefs.h>
|
||||||
|
#include <elf_common.h>
|
||||||
#include <image.h>
|
#include <image.h>
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
@@ -21,7 +22,6 @@ extern "C" {
|
|||||||
|
|
||||||
struct attr_info;
|
struct attr_info;
|
||||||
struct dirent;
|
struct dirent;
|
||||||
struct Elf32_Sym;
|
|
||||||
struct fd_info;
|
struct fd_info;
|
||||||
struct fd_set;
|
struct fd_set;
|
||||||
struct fs_info;
|
struct fs_info;
|
||||||
@@ -226,7 +226,7 @@ extern status_t _kern_get_image_info(image_id id, image_info *info,
|
|||||||
extern status_t _kern_get_next_image_info(team_id team, int32 *cookie,
|
extern status_t _kern_get_next_image_info(team_id team, int32 *cookie,
|
||||||
image_info *info, size_t size);
|
image_info *info, size_t size);
|
||||||
extern status_t _kern_read_kernel_image_symbols(image_id id,
|
extern status_t _kern_read_kernel_image_symbols(image_id id,
|
||||||
struct Elf32_Sym* symbolTable, int32* _symbolCount,
|
elf_sym* symbolTable, int32* _symbolCount,
|
||||||
char* stringTable, size_t* _stringTableSize,
|
char* stringTable, size_t* _stringTableSize,
|
||||||
addr_t* _imageDelta);
|
addr_t* _imageDelta);
|
||||||
|
|
||||||
|
|||||||
@@ -72,11 +72,9 @@ arch_int_init(kernel_args* args)
|
|||||||
table[i] = x86_hardware_interrupt;
|
table[i] = x86_hardware_interrupt;
|
||||||
|
|
||||||
table[0] = x86_unexpected_exception; // Divide Error Exception (#DE)
|
table[0] = x86_unexpected_exception; // Divide Error Exception (#DE)
|
||||||
//table[1] = x86_handle_debug_exception; // Debug Exception (#DB)
|
table[1] = x86_handle_debug_exception; // Debug Exception (#DB)
|
||||||
table[1] = x86_unexpected_exception;
|
|
||||||
table[2] = x86_fatal_exception; // NMI Interrupt
|
table[2] = x86_fatal_exception; // NMI Interrupt
|
||||||
//table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
|
table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP)
|
||||||
table[3] = x86_unexpected_exception;
|
|
||||||
table[4] = x86_unexpected_exception; // Overflow Exception (#OF)
|
table[4] = x86_unexpected_exception; // Overflow Exception (#OF)
|
||||||
table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR)
|
table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR)
|
||||||
table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD)
|
table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD)
|
||||||
|
|||||||
@@ -109,17 +109,12 @@
|
|||||||
\
|
\
|
||||||
UNLOCK_THREAD_TIME()
|
UNLOCK_THREAD_TIME()
|
||||||
|
|
||||||
// TODO
|
|
||||||
#if 0
|
|
||||||
#define STOP_USER_DEBUGGING() \
|
#define STOP_USER_DEBUGGING() \
|
||||||
testl $(THREAD_FLAGS_BREAKPOINTS_INSTALLED \
|
testl $(THREAD_FLAGS_BREAKPOINTS_INSTALLED \
|
||||||
| THREAD_FLAGS_SINGLE_STEP), THREAD_flags(%r12); \
|
| THREAD_FLAGS_SINGLE_STEP), THREAD_flags(%r12); \
|
||||||
jz 1f; \
|
jz 1f; \
|
||||||
call x86_exit_user_debug_at_kernel_entry; \
|
call x86_exit_user_debug_at_kernel_entry; \
|
||||||
1:
|
1:
|
||||||
#else
|
|
||||||
#define STOP_USER_DEBUGGING()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// The following code defines the interrupt service routines for all 256
|
// The following code defines the interrupt service routines for all 256
|
||||||
@@ -273,12 +268,12 @@ STATIC_FUNCTION(int_bottom_user):
|
|||||||
call thread_at_kernel_exit_no_signals
|
call thread_at_kernel_exit_no_signals
|
||||||
|
|
||||||
.Lkernel_exit_work_done:
|
.Lkernel_exit_work_done:
|
||||||
// Install breakpoints, if defined. TODO
|
// Install breakpoints, if defined.
|
||||||
//testl $THREAD_FLAGS_BREAKPOINTS_DEFINED, THREAD_flags(%r12)
|
testl $THREAD_FLAGS_BREAKPOINTS_DEFINED, THREAD_flags(%r12)
|
||||||
//jz 1f
|
jz 1f
|
||||||
//movq %rbp, %rdi
|
movq %rbp, %rdi
|
||||||
//call x86_init_user_debug_at_kernel_exit
|
call x86_init_user_debug_at_kernel_exit
|
||||||
//1:
|
1:
|
||||||
// Restore the saved registers.
|
// Restore the saved registers.
|
||||||
RESTORE_IFRAME()
|
RESTORE_IFRAME()
|
||||||
|
|
||||||
@@ -333,7 +328,7 @@ FUNCTION(x86_64_syscall_entry):
|
|||||||
|
|
||||||
// Check whether the syscall number is valid.
|
// Check whether the syscall number is valid.
|
||||||
cmpq $SYSCALL_COUNT, %r14
|
cmpq $SYSCALL_COUNT, %r14
|
||||||
jae .Lbad_syscall_number
|
jae .Lsyscall_return
|
||||||
|
|
||||||
// Get the system call table entry. Note I'm hardcoding the shift because
|
// Get the system call table entry. Note I'm hardcoding the shift because
|
||||||
// sizeof(syscall_info) is 16 and scale factors of 16 aren't supported,
|
// sizeof(syscall_info) is 16 and scale factors of 16 aren't supported,
|
||||||
@@ -348,6 +343,11 @@ FUNCTION(x86_64_syscall_entry):
|
|||||||
cmpq $48, %rcx
|
cmpq $48, %rcx
|
||||||
ja .Lsyscall_stack_args
|
ja .Lsyscall_stack_args
|
||||||
|
|
||||||
|
.Lperform_syscall:
|
||||||
|
testl $THREAD_FLAGS_DEBUGGER_INSTALLED, THREAD_flags(%r12)
|
||||||
|
jnz .Lpre_syscall_debug
|
||||||
|
|
||||||
|
.Lpre_syscall_debug_done:
|
||||||
// Restore the arguments from the iframe. UPDATE_THREAD_USER_TIME() makes
|
// Restore the arguments from the iframe. UPDATE_THREAD_USER_TIME() makes
|
||||||
// 2 function calls which means they may have been overwritten. Note that
|
// 2 function calls which means they may have been overwritten. Note that
|
||||||
// argument 4 is in R10 on the frame rather than RCX as RCX is used by
|
// argument 4 is in R10 on the frame rather than RCX as RCX is used by
|
||||||
@@ -359,7 +359,7 @@ FUNCTION(x86_64_syscall_entry):
|
|||||||
movq IFRAME_r8(%rbp), %r8
|
movq IFRAME_r8(%rbp), %r8
|
||||||
movq IFRAME_r9(%rbp), %r9
|
movq IFRAME_r9(%rbp), %r9
|
||||||
|
|
||||||
// TODO: pre-syscall tracing/debug
|
// TODO: pre-syscall tracing
|
||||||
|
|
||||||
// Call the function and save its return value.
|
// Call the function and save its return value.
|
||||||
call *SYSCALL_INFO_function(%rax)
|
call *SYSCALL_INFO_function(%rax)
|
||||||
@@ -367,7 +367,9 @@ FUNCTION(x86_64_syscall_entry):
|
|||||||
|
|
||||||
// TODO: post-syscall tracing
|
// TODO: post-syscall tracing
|
||||||
|
|
||||||
.Lbad_syscall_number:
|
// Restore the original stack pointer and return.
|
||||||
|
movq %rbp, %rsp
|
||||||
|
|
||||||
.Lsyscall_return:
|
.Lsyscall_return:
|
||||||
// Clear the restarted flag.
|
// Clear the restarted flag.
|
||||||
testl $THREAD_FLAGS_SYSCALL_RESTARTED, THREAD_flags(%r12)
|
testl $THREAD_FLAGS_SYSCALL_RESTARTED, THREAD_flags(%r12)
|
||||||
@@ -405,9 +407,41 @@ FUNCTION(x86_64_syscall_entry):
|
|||||||
swapgs
|
swapgs
|
||||||
sysretq
|
sysretq
|
||||||
|
|
||||||
.Lpost_syscall_work:
|
.Lpre_syscall_debug:
|
||||||
// TODO: post-syscall debugging
|
// user_debug_pre_syscall expects a pointer to a block of arguments, need
|
||||||
|
// to push the register arguments onto the stack.
|
||||||
|
push IFRAME_r9(%rbp)
|
||||||
|
push IFRAME_r8(%rbp)
|
||||||
|
push IFRAME_r10(%rbp)
|
||||||
|
push IFRAME_dx(%rbp)
|
||||||
|
push IFRAME_si(%rbp)
|
||||||
|
push IFRAME_di(%rbp)
|
||||||
|
movq %r14, %rdi // syscall number
|
||||||
|
movq %rsp, %rsi
|
||||||
|
push %rax
|
||||||
|
call user_debug_pre_syscall
|
||||||
|
pop %rax
|
||||||
|
addq $48, %rsp
|
||||||
|
jmp .Lpre_syscall_debug_done
|
||||||
|
|
||||||
|
.Lpost_syscall_work:
|
||||||
|
testl $THREAD_FLAGS_DEBUGGER_INSTALLED, THREAD_flags(%r12)
|
||||||
|
jz 1f
|
||||||
|
|
||||||
|
// Post-syscall debugging. Same as above, need a block of arguments.
|
||||||
|
push IFRAME_r9(%rbp)
|
||||||
|
push IFRAME_r8(%rbp)
|
||||||
|
push IFRAME_r10(%rbp)
|
||||||
|
push IFRAME_dx(%rbp)
|
||||||
|
push IFRAME_si(%rbp)
|
||||||
|
push IFRAME_di(%rbp)
|
||||||
|
movq %r14, %rdi // syscall number
|
||||||
|
movq %rsp, %rsi
|
||||||
|
movq IFRAME_ax(%rbp), %rdx // return value
|
||||||
|
movq %r13, %rcx // start time, preserved earlier
|
||||||
|
call user_debug_post_syscall
|
||||||
|
addq $48, %rsp
|
||||||
|
1:
|
||||||
// Do we need to handle signals?
|
// Do we need to handle signals?
|
||||||
testl $(THREAD_FLAGS_SIGNALS_PENDING | THREAD_FLAGS_DEBUG_THREAD) \
|
testl $(THREAD_FLAGS_SIGNALS_PENDING | THREAD_FLAGS_DEBUG_THREAD) \
|
||||||
, THREAD_flags(%r12)
|
, THREAD_flags(%r12)
|
||||||
@@ -422,11 +456,11 @@ FUNCTION(x86_64_syscall_entry):
|
|||||||
movq %rsp, %rdi
|
movq %rsp, %rdi
|
||||||
call x86_restart_syscall
|
call x86_restart_syscall
|
||||||
1:
|
1:
|
||||||
// Install breakpoints, if defined. TODO
|
// Install breakpoints, if defined.
|
||||||
//testl $THREAD_FLAGS_BREAKPOINTS_DEFINED, THREAD_flags(%r12)
|
testl $THREAD_FLAGS_BREAKPOINTS_DEFINED, THREAD_flags(%r12)
|
||||||
//jz .Liret
|
jz .Liret
|
||||||
//movq %rbp, %rdi
|
movq %rbp, %rdi
|
||||||
//call x86_init_user_debug_at_kernel_exit
|
call x86_init_user_debug_at_kernel_exit
|
||||||
|
|
||||||
// On this return path it is possible that the frame has been modified,
|
// On this return path it is possible that the frame has been modified,
|
||||||
// for example to execute a signal handler. In this case it is safer to
|
// for example to execute a signal handler. In this case it is safer to
|
||||||
@@ -470,25 +504,8 @@ FUNCTION(x86_64_syscall_entry):
|
|||||||
movsq
|
movsq
|
||||||
movq $0, THREAD_fault_handler(%r12)
|
movq $0, THREAD_fault_handler(%r12)
|
||||||
|
|
||||||
// Restore the register arguments from the iframe.
|
// Perform the call.
|
||||||
movq IFRAME_di(%rbp), %rdi
|
jmp .Lperform_syscall
|
||||||
movq IFRAME_si(%rbp), %rsi
|
|
||||||
movq IFRAME_dx(%rbp), %rdx
|
|
||||||
movq IFRAME_r10(%rbp), %rcx
|
|
||||||
movq IFRAME_r8(%rbp), %r8
|
|
||||||
movq IFRAME_r9(%rbp), %r9
|
|
||||||
|
|
||||||
// TODO: pre-syscall tracing/debug
|
|
||||||
|
|
||||||
// Call the function and save its return value.
|
|
||||||
call *SYSCALL_INFO_function(%rax)
|
|
||||||
movq %rax, IFRAME_ax(%rbp)
|
|
||||||
|
|
||||||
// TODO: post-syscall tracing
|
|
||||||
|
|
||||||
// Restore the original stack pointer and return.
|
|
||||||
movq %rbp, %rsp
|
|
||||||
jmp .Lsyscall_return
|
|
||||||
|
|
||||||
.Lbad_syscall_args:
|
.Lbad_syscall_args:
|
||||||
movq $0, THREAD_fault_handler(%r12)
|
movq $0, THREAD_fault_handler(%r12)
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// This file contains stubs for everything that's not been implemented yet on
|
|
||||||
// x86_64.
|
|
||||||
|
|
||||||
|
|
||||||
#include <cpu.h>
|
|
||||||
#include <commpage.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <debugger.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <elf_priv.h>
|
|
||||||
#include <real_time_clock.h>
|
|
||||||
#include <real_time_data.h>
|
|
||||||
#include <smp.h>
|
|
||||||
#include <timer.h>
|
|
||||||
#include <team.h>
|
|
||||||
#include <thread.h>
|
|
||||||
#include <vm/vm.h>
|
|
||||||
#include <vm/VMAddressSpace.h>
|
|
||||||
|
|
||||||
#include <boot/kernel_args.h>
|
|
||||||
|
|
||||||
#include <arch/debug.h>
|
|
||||||
#include <arch/vm_translation_map.h>
|
|
||||||
#include <arch/vm.h>
|
|
||||||
#include <arch/user_debugger.h>
|
|
||||||
#include <arch/timer.h>
|
|
||||||
#include <arch/thread.h>
|
|
||||||
#include <arch/system_info.h>
|
|
||||||
#include <arch/smp.h>
|
|
||||||
#include <arch/real_time_clock.h>
|
|
||||||
#include <arch/elf.h>
|
|
||||||
|
|
||||||
|
|
||||||
// The software breakpoint instruction (int3).
|
|
||||||
const uint8 kX86SoftwareBreakpoint[1] = { 0xcc };
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
arch_clear_team_debug_info(struct arch_team_debug_info *info)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
arch_destroy_team_debug_info(struct arch_team_debug_info *info)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
arch_clear_thread_debug_info(struct arch_thread_debug_info *info)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 debug_cpu_state *cpuState)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
arch_get_debug_cpu_state(debug_cpu_state *cpuState)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
arch_set_breakpoint(void *address)
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
arch_clear_breakpoint(void *address)
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
arch_set_watchpoint(void *address, uint32 type, int32 length)
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
arch_clear_watchpoint(void *address)
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
arch_has_breakpoints(struct arch_team_debug_info *info)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
x86_init_user_debug()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
_user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable,
|
|
||||||
int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
|
|
||||||
addr_t* _imageDelta)
|
|
||||||
{
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,6 @@ if $(TARGET_ARCH) = x86_64 {
|
|||||||
cpuid.S
|
cpuid.S
|
||||||
int.cpp
|
int.cpp
|
||||||
interrupts.S
|
interrupts.S
|
||||||
stubs.cpp
|
|
||||||
signals.cpp
|
signals.cpp
|
||||||
signals_asm.S
|
signals_asm.S
|
||||||
syscalls.cpp
|
syscalls.cpp
|
||||||
@@ -56,7 +55,6 @@ if $(TARGET_ARCH) = x86_64 {
|
|||||||
syscalls_asm.S
|
syscalls_asm.S
|
||||||
thread.cpp
|
thread.cpp
|
||||||
|
|
||||||
arch_user_debugger.cpp
|
|
||||||
ioapic.cpp
|
ioapic.cpp
|
||||||
irq_routing_table.cpp
|
irq_routing_table.cpp
|
||||||
|
|
||||||
@@ -88,6 +86,7 @@ local archGenericSources =
|
|||||||
arch_system_info.cpp
|
arch_system_info.cpp
|
||||||
arch_thread.cpp
|
arch_thread.cpp
|
||||||
arch_timer.cpp
|
arch_timer.cpp
|
||||||
|
arch_user_debugger.cpp
|
||||||
arch_vm.cpp
|
arch_vm.cpp
|
||||||
arch_vm_translation_map.cpp
|
arch_vm_translation_map.cpp
|
||||||
apic.cpp
|
apic.cpp
|
||||||
|
|||||||
@@ -39,27 +39,27 @@ extern bool gHasSSE;
|
|||||||
const uint8 kX86SoftwareBreakpoint[1] = { 0xcc };
|
const uint8 kX86SoftwareBreakpoint[1] = { 0xcc };
|
||||||
|
|
||||||
// maps breakpoint slot index to LEN_i LSB number
|
// maps breakpoint slot index to LEN_i LSB number
|
||||||
static const uint32 sDR7Len[4] = {
|
static const size_t sDR7Len[4] = {
|
||||||
X86_DR7_LEN0_LSB, X86_DR7_LEN1_LSB, X86_DR7_LEN2_LSB, X86_DR7_LEN3_LSB
|
X86_DR7_LEN0_LSB, X86_DR7_LEN1_LSB, X86_DR7_LEN2_LSB, X86_DR7_LEN3_LSB
|
||||||
};
|
};
|
||||||
|
|
||||||
// maps breakpoint slot index to R/W_i LSB number
|
// maps breakpoint slot index to R/W_i LSB number
|
||||||
static const uint32 sDR7RW[4] = {
|
static const size_t sDR7RW[4] = {
|
||||||
X86_DR7_RW0_LSB, X86_DR7_RW1_LSB, X86_DR7_RW2_LSB, X86_DR7_RW3_LSB
|
X86_DR7_RW0_LSB, X86_DR7_RW1_LSB, X86_DR7_RW2_LSB, X86_DR7_RW3_LSB
|
||||||
};
|
};
|
||||||
|
|
||||||
// maps breakpoint slot index to L_i bit number
|
// maps breakpoint slot index to L_i bit number
|
||||||
static const uint32 sDR7L[4] = {
|
static const size_t sDR7L[4] = {
|
||||||
X86_DR7_L0, X86_DR7_L1, X86_DR7_L2, X86_DR7_L3
|
X86_DR7_L0, X86_DR7_L1, X86_DR7_L2, X86_DR7_L3
|
||||||
};
|
};
|
||||||
|
|
||||||
// maps breakpoint slot index to G_i bit number
|
// maps breakpoint slot index to G_i bit number
|
||||||
static const uint32 sDR7G[4] = {
|
static const size_t sDR7G[4] = {
|
||||||
X86_DR7_G0, X86_DR7_G1, X86_DR7_G2, X86_DR7_G3
|
X86_DR7_G0, X86_DR7_G1, X86_DR7_G2, X86_DR7_G3
|
||||||
};
|
};
|
||||||
|
|
||||||
// maps breakpoint slot index to B_i bit number
|
// maps breakpoint slot index to B_i bit number
|
||||||
static const uint32 sDR6B[4] = {
|
static const size_t sDR6B[4] = {
|
||||||
X86_DR6_B0, X86_DR6_B1, X86_DR6_B2, X86_DR6_B3
|
X86_DR6_B0, X86_DR6_B1, X86_DR6_B2, X86_DR6_B3
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,8 +68,78 @@ static const uint32 sDR6B[4] = {
|
|||||||
static bool sQEmuSingleStepHack = false;
|
static bool sQEmuSingleStepHack = false;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
get_iframe_registers(struct iframe *frame, debug_cpu_state *cpuState)
|
get_iframe_registers(const iframe* frame, debug_cpu_state* cpuState)
|
||||||
|
{
|
||||||
|
// Get general purpose registers.
|
||||||
|
cpuState->r15 = frame->r15;
|
||||||
|
cpuState->r14 = frame->r14;
|
||||||
|
cpuState->r13 = frame->r13;
|
||||||
|
cpuState->r12 = frame->r12;
|
||||||
|
cpuState->r11 = frame->r11;
|
||||||
|
cpuState->r10 = frame->r10;
|
||||||
|
cpuState->r9 = frame->r9;
|
||||||
|
cpuState->r8 = frame->r8;
|
||||||
|
cpuState->rbp = frame->bp;
|
||||||
|
cpuState->rsi = frame->si;
|
||||||
|
cpuState->rdi = frame->di;
|
||||||
|
cpuState->rdx = frame->dx;
|
||||||
|
cpuState->rcx = frame->cx;
|
||||||
|
cpuState->rbx = frame->bx;
|
||||||
|
cpuState->rax = frame->ax;
|
||||||
|
cpuState->rip = frame->ip;
|
||||||
|
cpuState->cs = frame->cs;
|
||||||
|
cpuState->rflags = frame->flags;
|
||||||
|
cpuState->rsp = frame->sp;
|
||||||
|
cpuState->ss = frame->ss;
|
||||||
|
|
||||||
|
// Other segment registers are not saved or changed on interrupts, so
|
||||||
|
// get their value here.
|
||||||
|
uint16 seg;
|
||||||
|
__asm__ volatile ("movw %%ds, %0" : "=r" (seg));
|
||||||
|
cpuState->ds = seg;
|
||||||
|
__asm__ volatile ("movw %%es, %0" : "=r" (seg));
|
||||||
|
cpuState->es = seg;
|
||||||
|
__asm__ volatile ("movw %%fs, %0" : "=r" (seg));
|
||||||
|
cpuState->fs = seg;
|
||||||
|
__asm__ volatile ("movw %%gs, %0" : "=r" (seg));
|
||||||
|
cpuState->gs = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_iframe_registers(iframe* frame, const debug_cpu_state* cpuState)
|
||||||
|
{
|
||||||
|
frame->r15 = cpuState->r15;
|
||||||
|
frame->r14 = cpuState->r14;
|
||||||
|
frame->r13 = cpuState->r13;
|
||||||
|
frame->r12 = cpuState->r12;
|
||||||
|
frame->r11 = cpuState->r11;
|
||||||
|
frame->r10 = cpuState->r10;
|
||||||
|
frame->r9 = cpuState->r9;
|
||||||
|
frame->r8 = cpuState->r8;
|
||||||
|
frame->bp = cpuState->rbp;
|
||||||
|
frame->si = cpuState->rsi;
|
||||||
|
frame->di = cpuState->rdi;
|
||||||
|
frame->dx = cpuState->rdx;
|
||||||
|
frame->cx = cpuState->rcx;
|
||||||
|
frame->bx = cpuState->rbx;
|
||||||
|
frame->ax = cpuState->rax;
|
||||||
|
frame->ip = cpuState->rip;
|
||||||
|
frame->flags = (frame->flags & ~X86_EFLAGS_USER_SETTABLE_FLAGS)
|
||||||
|
| (cpuState->rflags & X86_EFLAGS_USER_SETTABLE_FLAGS);
|
||||||
|
frame->sp = cpuState->rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else // __x86_64__
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_iframe_registers(const iframe* frame, debug_cpu_state* cpuState)
|
||||||
{
|
{
|
||||||
cpuState->gs = frame->gs;
|
cpuState->gs = frame->gs;
|
||||||
cpuState->fs = frame->fs;
|
cpuState->fs = frame->fs;
|
||||||
@@ -93,25 +163,56 @@ get_iframe_registers(struct iframe *frame, debug_cpu_state *cpuState)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_iframe_registers(iframe* frame, const debug_cpu_state* cpuState)
|
||||||
|
{
|
||||||
|
// frame->gs = cpuState->gs;
|
||||||
|
// frame->fs = cpuState->fs;
|
||||||
|
// frame->es = cpuState->es;
|
||||||
|
// frame->ds = cpuState->ds;
|
||||||
|
frame->di = cpuState->edi;
|
||||||
|
frame->si = cpuState->esi;
|
||||||
|
frame->bp = cpuState->ebp;
|
||||||
|
// frame->esp = cpuState->esp;
|
||||||
|
frame->bx = cpuState->ebx;
|
||||||
|
frame->dx = cpuState->edx;
|
||||||
|
frame->cx = cpuState->ecx;
|
||||||
|
frame->ax = cpuState->eax;
|
||||||
|
// frame->vector = cpuState->vector;
|
||||||
|
// frame->error_code = cpuState->error_code;
|
||||||
|
frame->ip = cpuState->eip;
|
||||||
|
// frame->cs = cpuState->cs;
|
||||||
|
frame->flags = (frame->flags & ~X86_EFLAGS_USER_SETTABLE_FLAGS)
|
||||||
|
| (cpuState->eflags & X86_EFLAGS_USER_SETTABLE_FLAGS);
|
||||||
|
frame->user_sp = cpuState->user_esp;
|
||||||
|
// frame->user_ss = cpuState->user_ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __x86_64__
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
install_breakpoints(const arch_team_debug_info &teamInfo)
|
install_breakpoints(const arch_team_debug_info& teamInfo)
|
||||||
{
|
{
|
||||||
// set breakpoints
|
// set breakpoints
|
||||||
asm("movl %0, %%dr0" : : "r"(teamInfo.breakpoints[0].address));
|
asm("mov %0, %%dr0" : : "r"(teamInfo.breakpoints[0].address));
|
||||||
asm("movl %0, %%dr1" : : "r"(teamInfo.breakpoints[1].address));
|
asm("mov %0, %%dr1" : : "r"(teamInfo.breakpoints[1].address));
|
||||||
asm("movl %0, %%dr2" : : "r"(teamInfo.breakpoints[2].address));
|
asm("mov %0, %%dr2" : : "r"(teamInfo.breakpoints[2].address));
|
||||||
// asm("movl %0, %%dr3" : : "r"(teamInfo.breakpoints[3].address));
|
#ifdef __x86_64__
|
||||||
// DR3 is used to hold the current Thread*.
|
asm("mov %0, %%dr3" : : "r"(teamInfo.breakpoints[3].address));
|
||||||
|
// DR3 is used to hold the current Thread* on 32.
|
||||||
|
#endif
|
||||||
|
|
||||||
// enable breakpoints
|
// enable breakpoints
|
||||||
asm("movl %0, %%dr7" : : "r"(teamInfo.dr7));
|
asm("mov %0, %%dr7" : : "r"(teamInfo.dr7));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
disable_breakpoints()
|
disable_breakpoints()
|
||||||
{
|
{
|
||||||
asm("movl %0, %%dr7" : : "r"(X86_BREAKPOINTS_DISABLED_DR7));
|
asm("mov %0, %%dr7" : : "r"((size_t)X86_BREAKPOINTS_DISABLED_DR7));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -119,8 +220,8 @@ disable_breakpoints()
|
|||||||
Interrupts must be disabled and the team debug info lock be held.
|
Interrupts must be disabled and the team debug info lock be held.
|
||||||
*/
|
*/
|
||||||
static inline status_t
|
static inline status_t
|
||||||
set_breakpoint(arch_team_debug_info &info, void *address, uint32 type,
|
set_breakpoint(arch_team_debug_info& info, void* address, size_t type,
|
||||||
uint32 length, bool setGlobalFlag)
|
size_t length, bool setGlobalFlag)
|
||||||
{
|
{
|
||||||
// check, if there is already a breakpoint at that address
|
// check, if there is already a breakpoint at that address
|
||||||
bool alreadySet = false;
|
bool alreadySet = false;
|
||||||
@@ -169,7 +270,7 @@ set_breakpoint(arch_team_debug_info &info, void *address, uint32 type,
|
|||||||
Interrupts must be disabled and the team debug info lock be held.
|
Interrupts must be disabled and the team debug info lock be held.
|
||||||
*/
|
*/
|
||||||
static inline status_t
|
static inline status_t
|
||||||
clear_breakpoint(arch_team_debug_info &info, void *address, bool watchpoint)
|
clear_breakpoint(arch_team_debug_info& info, void* address, bool watchpoint)
|
||||||
{
|
{
|
||||||
// find the breakpoint
|
// find the breakpoint
|
||||||
int32 slot = -1;
|
int32 slot = -1;
|
||||||
@@ -202,12 +303,12 @@ clear_breakpoint(arch_team_debug_info &info, void *address, bool watchpoint)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
set_breakpoint(void *address, uint32 type, uint32 length)
|
set_breakpoint(void* address, size_t type, size_t length)
|
||||||
{
|
{
|
||||||
if (!address)
|
if (!address)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
Thread *thread = thread_get_current_thread();
|
Thread* thread = thread_get_current_thread();
|
||||||
|
|
||||||
cpu_status state = disable_interrupts();
|
cpu_status state = disable_interrupts();
|
||||||
GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
|
GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
|
||||||
@@ -223,12 +324,12 @@ set_breakpoint(void *address, uint32 type, uint32 length)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
clear_breakpoint(void *address, bool watchpoint)
|
clear_breakpoint(void* address, bool watchpoint)
|
||||||
{
|
{
|
||||||
if (!address)
|
if (!address)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
Thread *thread = thread_get_current_thread();
|
Thread* thread = thread_get_current_thread();
|
||||||
|
|
||||||
cpu_status state = disable_interrupts();
|
cpu_status state = disable_interrupts();
|
||||||
GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
|
GRAB_TEAM_DEBUG_INFO_LOCK(thread->team->debug_info);
|
||||||
@@ -260,7 +361,7 @@ install_breakpoints_per_cpu(void* /*cookie*/, int cpu)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
set_kernel_breakpoint(void *address, uint32 type, uint32 length)
|
set_kernel_breakpoint(void* address, size_t type, size_t length)
|
||||||
{
|
{
|
||||||
if (!address)
|
if (!address)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -284,7 +385,7 @@ set_kernel_breakpoint(void *address, uint32 type, uint32 length)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
clear_kernel_breakpoint(void *address, bool watchpoint)
|
clear_kernel_breakpoint(void* address, bool watchpoint)
|
||||||
{
|
{
|
||||||
if (!address)
|
if (!address)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -311,7 +412,7 @@ clear_kernel_breakpoint(void *address, bool watchpoint)
|
|||||||
|
|
||||||
static inline status_t
|
static inline status_t
|
||||||
check_watch_point_parameters(void* address, uint32 type, int32 length,
|
check_watch_point_parameters(void* address, uint32 type, int32 length,
|
||||||
uint32& archType, uint32& archLength)
|
size_t& archType, size_t& archLength)
|
||||||
{
|
{
|
||||||
// check type
|
// check type
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -333,12 +434,12 @@ check_watch_point_parameters(void* address, uint32 type, int32 length,
|
|||||||
archLength = X86_BREAKPOINT_LENGTH_1;
|
archLength = X86_BREAKPOINT_LENGTH_1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if ((uint32)address & 0x1)
|
if ((addr_t)address & 0x1)
|
||||||
return B_BAD_WATCHPOINT_ALIGNMENT;
|
return B_BAD_WATCHPOINT_ALIGNMENT;
|
||||||
archLength = X86_BREAKPOINT_LENGTH_2;
|
archLength = X86_BREAKPOINT_LENGTH_2;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if ((uint32)address & 0x3)
|
if ((addr_t)address & 0x3)
|
||||||
return B_BAD_WATCHPOINT_ALIGNMENT;
|
return B_BAD_WATCHPOINT_ALIGNMENT;
|
||||||
archLength = X86_BREAKPOINT_LENGTH_4;
|
archLength = X86_BREAKPOINT_LENGTH_4;
|
||||||
break;
|
break;
|
||||||
@@ -352,6 +453,7 @@ check_watch_point_parameters(void* address, uint32 type, int32 length,
|
|||||||
|
|
||||||
// #pragma mark - kernel debugger commands
|
// #pragma mark - kernel debugger commands
|
||||||
|
|
||||||
|
|
||||||
#if KERNEL_BREAKPOINTS
|
#if KERNEL_BREAKPOINTS
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -361,7 +463,7 @@ debugger_breakpoints(int argc, char** argv)
|
|||||||
arch_team_debug_info& info = kernelTeam->debug_info.arch_info;
|
arch_team_debug_info& info = kernelTeam->debug_info.arch_info;
|
||||||
|
|
||||||
for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
|
for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
|
||||||
kprintf("breakpoint[%ld] ", i);
|
kprintf("breakpoint[%" B_PRId32 "] ", i);
|
||||||
|
|
||||||
if (info.breakpoints[i].address != NULL) {
|
if (info.breakpoints[i].address != NULL) {
|
||||||
kprintf("%p ", info.breakpoints[i].address);
|
kprintf("%p ", info.breakpoints[i].address);
|
||||||
@@ -491,7 +593,7 @@ debugger_watchpoint(int argc, char** argv)
|
|||||||
uint32 type = readWrite ? B_DATA_READ_WRITE_WATCHPOINT
|
uint32 type = readWrite ? B_DATA_READ_WRITE_WATCHPOINT
|
||||||
: B_DATA_WRITE_WATCHPOINT;
|
: B_DATA_WRITE_WATCHPOINT;
|
||||||
|
|
||||||
uint32 archType, archLength;
|
size_t archType, archLength;
|
||||||
error = check_watch_point_parameters((void*)address, type, length,
|
error = check_watch_point_parameters((void*)address, type, length,
|
||||||
archType, archLength);
|
archType, archLength);
|
||||||
|
|
||||||
@@ -516,7 +618,7 @@ debugger_single_step(int argc, char** argv)
|
|||||||
// TODO: Since we need an iframe, this doesn't work when KDL wasn't entered
|
// TODO: Since we need an iframe, this doesn't work when KDL wasn't entered
|
||||||
// via an exception.
|
// via an exception.
|
||||||
|
|
||||||
struct iframe* frame = x86_get_current_iframe();
|
iframe* frame = x86_get_current_iframe();
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
kprintf("Failed to get the current iframe!\n");
|
kprintf("Failed to get the current iframe!\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -535,7 +637,7 @@ debugger_single_step(int argc, char** argv)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_clear_team_debug_info(struct arch_team_debug_info *info)
|
arch_clear_team_debug_info(arch_team_debug_info* info)
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++)
|
for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++)
|
||||||
info->breakpoints[i].address = NULL;
|
info->breakpoints[i].address = NULL;
|
||||||
@@ -545,21 +647,21 @@ arch_clear_team_debug_info(struct arch_team_debug_info *info)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_destroy_team_debug_info(struct arch_team_debug_info *info)
|
arch_destroy_team_debug_info(arch_team_debug_info* info)
|
||||||
{
|
{
|
||||||
arch_clear_team_debug_info(info);
|
arch_clear_team_debug_info(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_clear_thread_debug_info(struct arch_thread_debug_info *info)
|
arch_clear_thread_debug_info(arch_thread_debug_info* info)
|
||||||
{
|
{
|
||||||
info->flags = 0;
|
info->flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_destroy_thread_debug_info(struct arch_thread_debug_info *info)
|
arch_destroy_thread_debug_info(arch_thread_debug_info* info)
|
||||||
{
|
{
|
||||||
arch_clear_thread_debug_info(info);
|
arch_clear_thread_debug_info(info);
|
||||||
}
|
}
|
||||||
@@ -568,7 +670,7 @@ arch_destroy_thread_debug_info(struct arch_thread_debug_info *info)
|
|||||||
void
|
void
|
||||||
arch_update_thread_single_step()
|
arch_update_thread_single_step()
|
||||||
{
|
{
|
||||||
if (struct iframe* frame = x86_get_user_iframe()) {
|
if (iframe* frame = x86_get_user_iframe()) {
|
||||||
Thread* thread = thread_get_current_thread();
|
Thread* thread = thread_get_current_thread();
|
||||||
|
|
||||||
// set/clear TF in EFLAGS depending on whether single stepping is
|
// set/clear TF in EFLAGS depending on whether single stepping is
|
||||||
@@ -582,9 +684,9 @@ arch_update_thread_single_step()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_set_debug_cpu_state(const debug_cpu_state *cpuState)
|
arch_set_debug_cpu_state(const debug_cpu_state* cpuState)
|
||||||
{
|
{
|
||||||
if (struct iframe *frame = x86_get_user_iframe()) {
|
if (iframe* frame = x86_get_user_iframe()) {
|
||||||
// For the floating point state to be correct the calling function must
|
// For the floating point state to be correct the calling function must
|
||||||
// not use these registers (not even indirectly).
|
// not use these registers (not even indirectly).
|
||||||
if (gHasSSE) {
|
if (gHasSSE) {
|
||||||
@@ -597,39 +699,21 @@ arch_set_debug_cpu_state(const debug_cpu_state *cpuState)
|
|||||||
memcpy(thread->arch_info.fpu_state, &cpuState->extended_registers,
|
memcpy(thread->arch_info.fpu_state, &cpuState->extended_registers,
|
||||||
sizeof(cpuState->extended_registers));
|
sizeof(cpuState->extended_registers));
|
||||||
x86_fxrstor(thread->arch_info.fpu_state);
|
x86_fxrstor(thread->arch_info.fpu_state);
|
||||||
|
#ifndef __x86_64__
|
||||||
} else {
|
} else {
|
||||||
// TODO: Implement! We need to convert the format first.
|
// TODO: Implement! We need to convert the format first.
|
||||||
// x86_frstor(&cpuState->extended_registers);
|
// x86_frstor(&cpuState->extended_registers);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
set_iframe_registers(frame, cpuState);
|
||||||
// frame->gs = cpuState->gs;
|
|
||||||
// frame->fs = cpuState->fs;
|
|
||||||
// frame->es = cpuState->es;
|
|
||||||
// frame->ds = cpuState->ds;
|
|
||||||
frame->di = cpuState->edi;
|
|
||||||
frame->si = cpuState->esi;
|
|
||||||
frame->bp = cpuState->ebp;
|
|
||||||
// frame->esp = cpuState->esp;
|
|
||||||
frame->bx = cpuState->ebx;
|
|
||||||
frame->dx = cpuState->edx;
|
|
||||||
frame->cx = cpuState->ecx;
|
|
||||||
frame->ax = cpuState->eax;
|
|
||||||
// frame->vector = cpuState->vector;
|
|
||||||
// frame->error_code = cpuState->error_code;
|
|
||||||
frame->ip = cpuState->eip;
|
|
||||||
// frame->cs = cpuState->cs;
|
|
||||||
frame->flags = (frame->flags & ~X86_EFLAGS_USER_SETTABLE_FLAGS)
|
|
||||||
| (cpuState->eflags & X86_EFLAGS_USER_SETTABLE_FLAGS);
|
|
||||||
frame->user_sp = cpuState->user_esp;
|
|
||||||
// frame->user_ss = cpuState->user_ss;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
arch_get_debug_cpu_state(debug_cpu_state *cpuState)
|
arch_get_debug_cpu_state(debug_cpu_state* cpuState)
|
||||||
{
|
{
|
||||||
if (struct iframe *frame = x86_get_user_iframe()) {
|
if (iframe* frame = x86_get_user_iframe()) {
|
||||||
// For the floating point state to be correct the calling function must
|
// For the floating point state to be correct the calling function must
|
||||||
// not use these registers (not even indirectly).
|
// not use these registers (not even indirectly).
|
||||||
if (gHasSSE) {
|
if (gHasSSE) {
|
||||||
@@ -642,12 +726,14 @@ arch_get_debug_cpu_state(debug_cpu_state *cpuState)
|
|||||||
// unlike fnsave, fxsave doesn't reinit the FPU state
|
// unlike fnsave, fxsave doesn't reinit the FPU state
|
||||||
memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state,
|
memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state,
|
||||||
sizeof(cpuState->extended_registers));
|
sizeof(cpuState->extended_registers));
|
||||||
|
#ifndef __x86_64__
|
||||||
} else {
|
} else {
|
||||||
x86_fnsave(&cpuState->extended_registers);
|
x86_fnsave(&cpuState->extended_registers);
|
||||||
x86_frstor(&cpuState->extended_registers);
|
x86_frstor(&cpuState->extended_registers);
|
||||||
// fnsave reinits the FPU state after saving, so we need to
|
// fnsave reinits the FPU state after saving, so we need to
|
||||||
// load it again
|
// load it again
|
||||||
// TODO: Convert to fxsave format!
|
// TODO: Convert to fxsave format!
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
get_iframe_registers(frame, cpuState);
|
get_iframe_registers(frame, cpuState);
|
||||||
}
|
}
|
||||||
@@ -655,7 +741,7 @@ arch_get_debug_cpu_state(debug_cpu_state *cpuState)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_set_breakpoint(void *address)
|
arch_set_breakpoint(void* address)
|
||||||
{
|
{
|
||||||
return set_breakpoint(address, X86_INSTRUCTION_BREAKPOINT,
|
return set_breakpoint(address, X86_INSTRUCTION_BREAKPOINT,
|
||||||
X86_BREAKPOINT_LENGTH_1);
|
X86_BREAKPOINT_LENGTH_1);
|
||||||
@@ -663,16 +749,16 @@ arch_set_breakpoint(void *address)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_clear_breakpoint(void *address)
|
arch_clear_breakpoint(void* address)
|
||||||
{
|
{
|
||||||
return clear_breakpoint(address, false);
|
return clear_breakpoint(address, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_set_watchpoint(void *address, uint32 type, int32 length)
|
arch_set_watchpoint(void* address, uint32 type, int32 length)
|
||||||
{
|
{
|
||||||
uint32 archType, archLength;
|
size_t archType, archLength;
|
||||||
status_t error = check_watch_point_parameters(address, type, length,
|
status_t error = check_watch_point_parameters(address, type, length,
|
||||||
archType, archLength);
|
archType, archLength);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -683,14 +769,14 @@ arch_set_watchpoint(void *address, uint32 type, int32 length)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_clear_watchpoint(void *address)
|
arch_clear_watchpoint(void* address)
|
||||||
{
|
{
|
||||||
return clear_breakpoint(address, true);
|
return clear_breakpoint(address, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
arch_has_breakpoints(struct arch_team_debug_info *info)
|
arch_has_breakpoints(arch_team_debug_info* info)
|
||||||
{
|
{
|
||||||
// Reading info->dr7 is atomically, so we don't need to lock. The caller
|
// Reading info->dr7 is atomically, so we don't need to lock. The caller
|
||||||
// has to ensure, that the info doesn't go away.
|
// has to ensure, that the info doesn't go away.
|
||||||
@@ -701,7 +787,7 @@ arch_has_breakpoints(struct arch_team_debug_info *info)
|
|||||||
#if KERNEL_BREAKPOINTS
|
#if KERNEL_BREAKPOINTS
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_set_kernel_breakpoint(void *address)
|
arch_set_kernel_breakpoint(void* address)
|
||||||
{
|
{
|
||||||
status_t error = set_kernel_breakpoint(address, X86_INSTRUCTION_BREAKPOINT,
|
status_t error = set_kernel_breakpoint(address, X86_INSTRUCTION_BREAKPOINT,
|
||||||
X86_BREAKPOINT_LENGTH_1);
|
X86_BREAKPOINT_LENGTH_1);
|
||||||
@@ -716,7 +802,7 @@ arch_set_kernel_breakpoint(void *address)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_clear_kernel_breakpoint(void *address)
|
arch_clear_kernel_breakpoint(void* address)
|
||||||
{
|
{
|
||||||
status_t error = clear_kernel_breakpoint(address, false);
|
status_t error = clear_kernel_breakpoint(address, false);
|
||||||
|
|
||||||
@@ -730,9 +816,9 @@ arch_clear_kernel_breakpoint(void *address)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_set_kernel_watchpoint(void *address, uint32 type, int32 length)
|
arch_set_kernel_watchpoint(void* address, uint32 type, int32 length)
|
||||||
{
|
{
|
||||||
uint32 archType, archLength;
|
size_t archType, archLength;
|
||||||
status_t error = check_watch_point_parameters(address, type, length,
|
status_t error = check_watch_point_parameters(address, type, length,
|
||||||
archType, archLength);
|
archType, archLength);
|
||||||
|
|
||||||
@@ -749,7 +835,7 @@ arch_set_kernel_watchpoint(void *address, uint32 type, int32 length)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_clear_kernel_watchpoint(void *address)
|
arch_clear_kernel_watchpoint(void* address)
|
||||||
{
|
{
|
||||||
status_t error = clear_kernel_breakpoint(address, true);
|
status_t error = clear_kernel_breakpoint(address, true);
|
||||||
|
|
||||||
@@ -771,9 +857,9 @@ arch_clear_kernel_watchpoint(void *address)
|
|||||||
* Interrupts are disabled. \a frame is unused, i.e. can be \c NULL.
|
* Interrupts are disabled. \a frame is unused, i.e. can be \c NULL.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
x86_init_user_debug_at_kernel_exit(struct iframe *frame)
|
x86_init_user_debug_at_kernel_exit(iframe* frame)
|
||||||
{
|
{
|
||||||
Thread *thread = thread_get_current_thread();
|
Thread* thread = thread_get_current_thread();
|
||||||
|
|
||||||
if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_DEFINED))
|
if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_DEFINED))
|
||||||
return;
|
return;
|
||||||
@@ -800,14 +886,14 @@ x86_init_user_debug_at_kernel_exit(struct iframe *frame)
|
|||||||
void
|
void
|
||||||
x86_exit_user_debug_at_kernel_entry()
|
x86_exit_user_debug_at_kernel_entry()
|
||||||
{
|
{
|
||||||
Thread *thread = thread_get_current_thread();
|
Thread* thread = thread_get_current_thread();
|
||||||
|
|
||||||
// We need to save the current values of dr6 and dr7 in the CPU structure,
|
// We need to save the current values of dr6 and dr7 in the CPU structure,
|
||||||
// since in case of a debug exception we might overwrite them before
|
// since in case of a debug exception we might overwrite them before
|
||||||
// x86_handle_debug_exception() is called. Debug exceptions occur when
|
// x86_handle_debug_exception() is called. Debug exceptions occur when
|
||||||
// hitting a hardware break/watchpoint or when single-stepping.
|
// hitting a hardware break/watchpoint or when single-stepping.
|
||||||
asm("movl %%dr6, %0" : "=r"(thread->cpu->arch.dr6));
|
asm("mov %%dr6, %0" : "=r"(thread->cpu->arch.dr6));
|
||||||
asm("movl %%dr7, %0" : "=r"(thread->cpu->arch.dr7));
|
asm("mov %%dr7, %0" : "=r"(thread->cpu->arch.dr7));
|
||||||
|
|
||||||
// The remainder needs only be done, when user breakpoints are installed.
|
// The remainder needs only be done, when user breakpoints are installed.
|
||||||
if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_INSTALLED))
|
if (!(thread->flags & THREAD_FLAGS_BREAKPOINTS_INSTALLED))
|
||||||
@@ -833,7 +919,7 @@ x86_exit_user_debug_at_kernel_entry()
|
|||||||
* Interrupts are disabled and will possibly be enabled by the function.
|
* Interrupts are disabled and will possibly be enabled by the function.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
x86_handle_debug_exception(struct iframe *frame)
|
x86_handle_debug_exception(iframe* frame)
|
||||||
{
|
{
|
||||||
Thread* thread = thread_get_current_thread();
|
Thread* thread = thread_get_current_thread();
|
||||||
|
|
||||||
@@ -842,14 +928,14 @@ x86_handle_debug_exception(struct iframe *frame)
|
|||||||
// x86_exit_user_debug_at_kernel_entry() has already been invoked and dr6
|
// x86_exit_user_debug_at_kernel_entry() has already been invoked and dr6
|
||||||
// and dr7 are stored in the cpu info. Otherwise we need to fetch the
|
// and dr7 are stored in the cpu info. Otherwise we need to fetch the
|
||||||
// current values from the registers.
|
// current values from the registers.
|
||||||
uint32 dr6;
|
size_t dr6;
|
||||||
uint32 dr7;
|
size_t dr7;
|
||||||
if (IFRAME_IS_USER(frame)) {
|
if (IFRAME_IS_USER(frame)) {
|
||||||
dr6 = thread->cpu->arch.dr6;
|
dr6 = thread->cpu->arch.dr6;
|
||||||
dr7 = thread->cpu->arch.dr7;
|
dr7 = thread->cpu->arch.dr7;
|
||||||
} else {
|
} else {
|
||||||
asm("movl %%dr6, %0" : "=r"(dr6));
|
asm("mov %%dr6, %0" : "=r"(dr6));
|
||||||
asm("movl %%dr7, %0" : "=r"(dr7));
|
asm("mov %%dr7, %0" : "=r"(dr7));
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("x86_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, dr7));
|
TRACE(("x86_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, dr7));
|
||||||
@@ -862,7 +948,7 @@ x86_handle_debug_exception(struct iframe *frame)
|
|||||||
bool watchpoint = true;
|
bool watchpoint = true;
|
||||||
for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
|
for (int32 i = 0; i < X86_BREAKPOINT_COUNT; i++) {
|
||||||
if (dr6 & (1 << sDR6B[i])) {
|
if (dr6 & (1 << sDR6B[i])) {
|
||||||
uint32 type = (dr7 >> sDR7RW[i]) & 0x3;
|
size_t type = (dr7 >> sDR7RW[i]) & 0x3;
|
||||||
if (type == X86_INSTRUCTION_BREAKPOINT)
|
if (type == X86_INSTRUCTION_BREAKPOINT)
|
||||||
watchpoint = false;
|
watchpoint = false;
|
||||||
}
|
}
|
||||||
@@ -972,7 +1058,7 @@ x86_handle_debug_exception(struct iframe *frame)
|
|||||||
* Interrupts are disabled and will possibly be enabled by the function.
|
* Interrupts are disabled and will possibly be enabled by the function.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
x86_handle_breakpoint_exception(struct iframe *frame)
|
x86_handle_breakpoint_exception(iframe* frame)
|
||||||
{
|
{
|
||||||
TRACE(("x86_handle_breakpoint_exception()\n"));
|
TRACE(("x86_handle_breakpoint_exception()\n"));
|
||||||
|
|
||||||
@@ -994,7 +1080,7 @@ void
|
|||||||
x86_init_user_debug()
|
x86_init_user_debug()
|
||||||
{
|
{
|
||||||
// get debug settings
|
// get debug settings
|
||||||
if (void *handle = load_driver_settings("kernel")) {
|
if (void* handle = load_driver_settings("kernel")) {
|
||||||
sQEmuSingleStepHack = get_driver_boolean_parameter(handle,
|
sQEmuSingleStepHack = get_driver_boolean_parameter(handle,
|
||||||
"qemu_single_step_hack", false, false);;
|
"qemu_single_step_hack", false, false);;
|
||||||
|
|
||||||
|
|||||||
@@ -77,8 +77,9 @@ static status_t
|
|||||||
debugger_write(port_id port, int32 code, const void *buffer, size_t bufferSize,
|
debugger_write(port_id port, int32 code, const void *buffer, size_t bufferSize,
|
||||||
bool dontWait)
|
bool dontWait)
|
||||||
{
|
{
|
||||||
TRACE(("debugger_write(): thread: %ld, team %ld, port: %ld, code: %lx, message: %p, "
|
TRACE(("debugger_write(): thread: %" B_PRId32 ", team %" B_PRId32 ", "
|
||||||
"size: %lu, dontWait: %d\n", thread_get_current_thread()->id,
|
"port: %" B_PRId32 ", code: %" B_PRIx32 ", message: %p, size: %lu, "
|
||||||
|
"dontWait: %d\n", thread_get_current_thread()->id,
|
||||||
thread_get_current_thread()->team->id, port, code, buffer, bufferSize,
|
thread_get_current_thread()->team->id, port, code, buffer, bufferSize,
|
||||||
dontWait));
|
dontWait));
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ debugger_write(port_id port, int32 code, const void *buffer, size_t bufferSize,
|
|||||||
error = acquire_sem_etc(writeLock, 1,
|
error = acquire_sem_etc(writeLock, 1,
|
||||||
dontWait ? (uint32)B_RELATIVE_TIMEOUT : (uint32)B_KILL_CAN_INTERRUPT, 0);
|
dontWait ? (uint32)B_RELATIVE_TIMEOUT : (uint32)B_KILL_CAN_INTERRUPT, 0);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
TRACE(("debugger_write() done1: %lx\n", error));
|
TRACE(("debugger_write() done1: %" B_PRIx32 "\n", error));
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ debugger_write(port_id port, int32 code, const void *buffer, size_t bufferSize,
|
|||||||
// release the write lock
|
// release the write lock
|
||||||
release_sem(writeLock);
|
release_sem(writeLock);
|
||||||
|
|
||||||
TRACE(("debugger_write() done: %lx\n", error));
|
TRACE(("debugger_write() done: %" B_PRIx32 "\n", error));
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -529,8 +530,9 @@ thread_hit_debug_event_internal(debug_debugger_message event,
|
|||||||
restart = false;
|
restart = false;
|
||||||
Thread *thread = thread_get_current_thread();
|
Thread *thread = thread_get_current_thread();
|
||||||
|
|
||||||
TRACE(("thread_hit_debug_event(): thread: %ld, event: %lu, message: %p, "
|
TRACE(("thread_hit_debug_event(): thread: %" B_PRId32 ", event: %" B_PRIu32
|
||||||
"size: %ld\n", thread->id, (uint32)event, message, size));
|
", message: %p, size: %" B_PRId32 "\n", thread->id, (uint32)event,
|
||||||
|
message, size));
|
||||||
|
|
||||||
// check, if there's a debug port already
|
// check, if there's a debug port already
|
||||||
bool setPort = !(atomic_get(&thread->debug_info.flags)
|
bool setPort = !(atomic_get(&thread->debug_info.flags)
|
||||||
@@ -567,8 +569,8 @@ thread_hit_debug_event_internal(debug_debugger_message event,
|
|||||||
= (thread->team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED);
|
= (thread->team->debug_info.flags & B_TEAM_DEBUG_DEBUGGER_INSTALLED);
|
||||||
if (thread->id == thread->team->debug_info.nub_thread) {
|
if (thread->id == thread->team->debug_info.nub_thread) {
|
||||||
// Ugh, we're the nub thread. We shouldn't be here.
|
// Ugh, we're the nub thread. We shouldn't be here.
|
||||||
TRACE(("thread_hit_debug_event(): Misdirected nub thread: %ld\n",
|
TRACE(("thread_hit_debug_event(): Misdirected nub thread: %" B_PRId32
|
||||||
thread->id));
|
"\n", thread->id));
|
||||||
|
|
||||||
error = B_ERROR;
|
error = B_ERROR;
|
||||||
} else if (debuggerInstalled || !requireDebugger) {
|
} else if (debuggerInstalled || !requireDebugger) {
|
||||||
@@ -614,8 +616,8 @@ thread_hit_debug_event_internal(debug_debugger_message event,
|
|||||||
delete_port(deletePort);
|
delete_port(deletePort);
|
||||||
|
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
TRACE(("thread_hit_debug_event() error: thread: %ld, error: %lx\n",
|
TRACE(("thread_hit_debug_event() error: thread: %" B_PRId32 ", error: "
|
||||||
thread->id, error));
|
"%" B_PRIx32 "\n", thread->id, error));
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,8 +629,9 @@ thread_hit_debug_event_internal(debug_debugger_message event,
|
|||||||
origin->team = thread->team->id;
|
origin->team = thread->team->id;
|
||||||
origin->nub_port = nubPort;
|
origin->nub_port = nubPort;
|
||||||
|
|
||||||
TRACE(("thread_hit_debug_event(): thread: %ld, sending message to "
|
TRACE(("thread_hit_debug_event(): thread: %" B_PRId32 ", sending "
|
||||||
"debugger port %ld\n", thread->id, debuggerPort));
|
"message to debugger port %" B_PRId32 "\n", thread->id,
|
||||||
|
debuggerPort));
|
||||||
|
|
||||||
error = debugger_write(debuggerPort, event, message, size, false);
|
error = debugger_write(debuggerPort, event, message, size, false);
|
||||||
}
|
}
|
||||||
@@ -648,15 +651,15 @@ thread_hit_debug_event_internal(debug_debugger_message event,
|
|||||||
|
|
||||||
if (commandMessageSize < 0) {
|
if (commandMessageSize < 0) {
|
||||||
error = commandMessageSize;
|
error = commandMessageSize;
|
||||||
TRACE(("thread_hit_debug_event(): thread: %ld, failed "
|
TRACE(("thread_hit_debug_event(): thread: %" B_PRId32 ", failed "
|
||||||
"to receive message from port %ld: %lx\n",
|
"to receive message from port %" B_PRId32 ": %" B_PRIx32 "\n",
|
||||||
thread->id, port, error));
|
thread->id, port, error));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case B_DEBUGGED_THREAD_MESSAGE_CONTINUE:
|
case B_DEBUGGED_THREAD_MESSAGE_CONTINUE:
|
||||||
TRACE(("thread_hit_debug_event(): thread: %ld: "
|
TRACE(("thread_hit_debug_event(): thread: %" B_PRId32 ": "
|
||||||
"B_DEBUGGED_THREAD_MESSAGE_CONTINUE\n",
|
"B_DEBUGGED_THREAD_MESSAGE_CONTINUE\n",
|
||||||
thread->id));
|
thread->id));
|
||||||
result = commandMessage.continue_thread.handle_event;
|
result = commandMessage.continue_thread.handle_event;
|
||||||
@@ -667,7 +670,7 @@ thread_hit_debug_event_internal(debug_debugger_message event,
|
|||||||
|
|
||||||
case B_DEBUGGED_THREAD_SET_CPU_STATE:
|
case B_DEBUGGED_THREAD_SET_CPU_STATE:
|
||||||
{
|
{
|
||||||
TRACE(("thread_hit_debug_event(): thread: %ld: "
|
TRACE(("thread_hit_debug_event(): thread: %" B_PRId32 ": "
|
||||||
"B_DEBUGGED_THREAD_SET_CPU_STATE\n",
|
"B_DEBUGGED_THREAD_SET_CPU_STATE\n",
|
||||||
thread->id));
|
thread->id));
|
||||||
arch_set_debug_cpu_state(
|
arch_set_debug_cpu_state(
|
||||||
@@ -720,9 +723,9 @@ thread_hit_debug_event_internal(debug_debugger_message event,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TRACE(("thread_hit_debug_event(): thread: %ld, failed to send "
|
TRACE(("thread_hit_debug_event(): thread: %" B_PRId32 ", failed to send "
|
||||||
"message to debugger port %ld: %lx\n", thread->id,
|
"message to debugger port %" B_PRId32 ": %" B_PRIx32 "\n",
|
||||||
debuggerPort, error));
|
thread->id, debuggerPort, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the thread debug info
|
// update the thread debug info
|
||||||
@@ -993,8 +996,8 @@ void
|
|||||||
user_debug_team_deleted(team_id teamID, port_id debuggerPort)
|
user_debug_team_deleted(team_id teamID, port_id debuggerPort)
|
||||||
{
|
{
|
||||||
if (debuggerPort >= 0) {
|
if (debuggerPort >= 0) {
|
||||||
TRACE(("user_debug_team_deleted(team: %ld, debugger port: %ld)\n",
|
TRACE(("user_debug_team_deleted(team: %" B_PRId32 ", debugger port: "
|
||||||
teamID, debuggerPort));
|
"%" B_PRId32 ")\n", teamID, debuggerPort));
|
||||||
|
|
||||||
debug_team_deleted message;
|
debug_team_deleted message;
|
||||||
message.origin.thread = -1;
|
message.origin.thread = -1;
|
||||||
@@ -1541,7 +1544,8 @@ broadcast_debugged_thread_message(Thread *nubThread, int32 code,
|
|||||||
code, message, size);
|
code, message, size);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
TRACE(("broadcast_debugged_thread_message(): Failed to send "
|
TRACE(("broadcast_debugged_thread_message(): Failed to send "
|
||||||
"message to thread %ld: %lx\n", thread->id, error));
|
"message to thread %" B_PRId32 ": %" B_PRIx32 "\n",
|
||||||
|
thread->id, error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1551,8 +1555,8 @@ broadcast_debugged_thread_message(Thread *nubThread, int32 code,
|
|||||||
static void
|
static void
|
||||||
nub_thread_cleanup(Thread *nubThread)
|
nub_thread_cleanup(Thread *nubThread)
|
||||||
{
|
{
|
||||||
TRACE(("nub_thread_cleanup(%ld): debugger port: %ld\n", nubThread->id,
|
TRACE(("nub_thread_cleanup(%" B_PRId32 "): debugger port: %" B_PRId32 "\n",
|
||||||
nubThread->team->debug_info.debugger_port));
|
nubThread->id, nubThread->team->debug_info.debugger_port));
|
||||||
|
|
||||||
ConditionVariable debugChangeCondition;
|
ConditionVariable debugChangeCondition;
|
||||||
prepare_debugger_change(nubThread->team, debugChangeCondition);
|
prepare_debugger_change(nubThread->team, debugChangeCondition);
|
||||||
@@ -1654,8 +1658,8 @@ debug_nub_thread(void *)
|
|||||||
RELEASE_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info);
|
RELEASE_TEAM_DEBUG_INFO_LOCK(nubThread->team->debug_info);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
TRACE(("debug_nub_thread() thread: %ld, team %ld, nub port: %ld\n",
|
TRACE(("debug_nub_thread() thread: %" B_PRId32 ", team %" B_PRId32 ", nub "
|
||||||
nubThread->id, nubThread->team->id, port));
|
"port: %" B_PRId32 "\n", nubThread->id, nubThread->team->id, port));
|
||||||
|
|
||||||
// notify all threads that a debugger has been installed
|
// notify all threads that a debugger has been installed
|
||||||
broadcast_debugged_thread_message(nubThread,
|
broadcast_debugged_thread_message(nubThread,
|
||||||
@@ -1674,8 +1678,8 @@ debug_nub_thread(void *)
|
|||||||
// thread, we need to update that.
|
// thread, we need to update that.
|
||||||
nub_thread_cleanup(nubThread);
|
nub_thread_cleanup(nubThread);
|
||||||
|
|
||||||
TRACE(("nub thread %ld: terminating: %lx\n", nubThread->id,
|
TRACE(("nub thread %" B_PRId32 ": terminating: %lx\n",
|
||||||
messageSize));
|
nubThread->id, messageSize));
|
||||||
|
|
||||||
return messageSize;
|
return messageSize;
|
||||||
}
|
}
|
||||||
@@ -1719,10 +1723,10 @@ debug_nub_thread(void *)
|
|||||||
}
|
}
|
||||||
reply.read_memory.error = result;
|
reply.read_memory.error = result;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_READ_MEMORY: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_READ_MEMORY: "
|
||||||
"reply port: %ld, address: %p, size: %ld, result: %lx, "
|
"reply port: %" B_PRId32 ", address: %p, size: %" B_PRId32
|
||||||
"read: %ld\n", nubThread->id, replyPort, address, size,
|
", result: %" B_PRIx32 ", read: %ld\n", nubThread->id,
|
||||||
result, bytesRead));
|
replyPort, address, size, result, bytesRead));
|
||||||
|
|
||||||
// send only as much data as necessary
|
// send only as much data as necessary
|
||||||
reply.read_memory.size = bytesRead;
|
reply.read_memory.size = bytesRead;
|
||||||
@@ -1755,10 +1759,10 @@ debug_nub_thread(void *)
|
|||||||
}
|
}
|
||||||
reply.write_memory.error = result;
|
reply.write_memory.error = result;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_WRITE_MEMORY: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_WRITE_MEMORY: "
|
||||||
"reply port: %ld, address: %p, size: %ld, result: %lx, "
|
"reply port: %" B_PRId32 ", address: %p, size: %" B_PRId32
|
||||||
"written: %ld\n", nubThread->id, replyPort, address, size,
|
", result: %" B_PRIx32 ", written: %ld\n", nubThread->id,
|
||||||
result, bytesWritten));
|
replyPort, address, size, result, bytesWritten));
|
||||||
|
|
||||||
reply.write_memory.size = bytesWritten;
|
reply.write_memory.size = bytesWritten;
|
||||||
sendReply = true;
|
sendReply = true;
|
||||||
@@ -1772,8 +1776,8 @@ debug_nub_thread(void *)
|
|||||||
int32 flags = message.set_team_flags.flags
|
int32 flags = message.set_team_flags.flags
|
||||||
& B_TEAM_DEBUG_USER_FLAG_MASK;
|
& B_TEAM_DEBUG_USER_FLAG_MASK;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_TEAM_FLAGS: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_SET_TEAM_FLAGS"
|
||||||
"flags: %lx\n", nubThread->id, flags));
|
": flags: %" B_PRIx32 "\n", nubThread->id, flags));
|
||||||
|
|
||||||
Team *team = thread_get_current_thread()->team;
|
Team *team = thread_get_current_thread()->team;
|
||||||
|
|
||||||
@@ -1797,9 +1801,9 @@ debug_nub_thread(void *)
|
|||||||
int32 flags = message.set_thread_flags.flags
|
int32 flags = message.set_thread_flags.flags
|
||||||
& B_THREAD_DEBUG_USER_FLAG_MASK;
|
& B_THREAD_DEBUG_USER_FLAG_MASK;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_THREAD_FLAGS: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_SET_THREAD_FLAGS"
|
||||||
"thread: %ld, flags: %lx\n", nubThread->id, threadID,
|
": thread: %" B_PRId32 ", flags: %" B_PRIx32 "\n",
|
||||||
flags));
|
nubThread->id, threadID, flags));
|
||||||
|
|
||||||
// set the flags
|
// set the flags
|
||||||
Thread* thread = Thread::GetAndLock(threadID);
|
Thread* thread = Thread::GetAndLock(threadID);
|
||||||
@@ -1831,9 +1835,10 @@ debug_nub_thread(void *)
|
|||||||
handleEvent = message.continue_thread.handle_event;
|
handleEvent = message.continue_thread.handle_event;
|
||||||
singleStep = message.continue_thread.single_step;
|
singleStep = message.continue_thread.single_step;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CONTINUE_THREAD: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_CONTINUE_THREAD"
|
||||||
"thread: %ld, handle event: %lu, single step: %d\n",
|
": thread: %" B_PRId32 ", handle event: %" B_PRIu32 ", "
|
||||||
nubThread->id, threadID, handleEvent, singleStep));
|
"single step: %d\n", nubThread->id, threadID, handleEvent,
|
||||||
|
singleStep));
|
||||||
|
|
||||||
// find the thread and get its debug port
|
// find the thread and get its debug port
|
||||||
port_id threadDebugPort = -1;
|
port_id threadDebugPort = -1;
|
||||||
@@ -1861,8 +1866,8 @@ debug_nub_thread(void *)
|
|||||||
const debug_cpu_state &cpuState
|
const debug_cpu_state &cpuState
|
||||||
= message.set_cpu_state.cpu_state;
|
= message.set_cpu_state.cpu_state;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_CPU_STATE: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_SET_CPU_STATE"
|
||||||
"thread: %ld\n", nubThread->id, threadID));
|
": thread: %" B_PRId32 "\n", nubThread->id, threadID));
|
||||||
|
|
||||||
// find the thread and get its debug port
|
// find the thread and get its debug port
|
||||||
port_id threadDebugPort = -1;
|
port_id threadDebugPort = -1;
|
||||||
@@ -1888,8 +1893,8 @@ debug_nub_thread(void *)
|
|||||||
thread_id threadID = message.get_cpu_state.thread;
|
thread_id threadID = message.get_cpu_state.thread;
|
||||||
replyPort = message.get_cpu_state.reply_port;
|
replyPort = message.get_cpu_state.reply_port;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_CPU_STATE: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_GET_CPU_STATE"
|
||||||
"thread: %ld\n", nubThread->id, threadID));
|
": thread: %" B_PRId32 "\n", nubThread->id, threadID));
|
||||||
|
|
||||||
// find the thread and get its debug port
|
// find the thread and get its debug port
|
||||||
port_id threadDebugPort = -1;
|
port_id threadDebugPort = -1;
|
||||||
@@ -1921,8 +1926,8 @@ debug_nub_thread(void *)
|
|||||||
replyPort = message.set_breakpoint.reply_port;
|
replyPort = message.set_breakpoint.reply_port;
|
||||||
void *address = message.set_breakpoint.address;
|
void *address = message.set_breakpoint.address;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_BREAKPOINT: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_SET_BREAKPOINT"
|
||||||
"address: %p\n", nubThread->id, address));
|
": address: %p\n", nubThread->id, address));
|
||||||
|
|
||||||
// check the address
|
// check the address
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
@@ -1951,8 +1956,8 @@ debug_nub_thread(void *)
|
|||||||
// get the parameters
|
// get the parameters
|
||||||
void *address = message.clear_breakpoint.address;
|
void *address = message.clear_breakpoint.address;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CLEAR_BREAKPOINT: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_CLEAR_BREAKPOINT"
|
||||||
"address: %p\n", nubThread->id, address));
|
": address: %p\n", nubThread->id, address));
|
||||||
|
|
||||||
// check the address
|
// check the address
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
@@ -1979,9 +1984,9 @@ debug_nub_thread(void *)
|
|||||||
uint32 type = message.set_watchpoint.type;
|
uint32 type = message.set_watchpoint.type;
|
||||||
int32 length = message.set_watchpoint.length;
|
int32 length = message.set_watchpoint.length;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_WATCHPOINT: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_SET_WATCHPOINT"
|
||||||
"address: %p, type: %lu, length: %ld\n", nubThread->id,
|
": address: %p, type: %" B_PRIu32 ", length: %" B_PRId32 "\n",
|
||||||
address, type, length));
|
nubThread->id, address, type, length));
|
||||||
|
|
||||||
// check the address and size
|
// check the address and size
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
@@ -2014,8 +2019,8 @@ debug_nub_thread(void *)
|
|||||||
// get the parameters
|
// get the parameters
|
||||||
void *address = message.clear_watchpoint.address;
|
void *address = message.clear_watchpoint.address;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_CLEAR_WATCHPOINT: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_CLEAR_WATCHPOINT"
|
||||||
"address: %p\n", nubThread->id, address));
|
": address: %p\n", nubThread->id, address));
|
||||||
|
|
||||||
// check the address
|
// check the address
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
@@ -2043,10 +2048,11 @@ debug_nub_thread(void *)
|
|||||||
uint32 ignoreOp = message.set_signal_masks.ignore_op;
|
uint32 ignoreOp = message.set_signal_masks.ignore_op;
|
||||||
uint32 ignoreOnceOp = message.set_signal_masks.ignore_once_op;
|
uint32 ignoreOnceOp = message.set_signal_masks.ignore_once_op;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_SIGNAL_MASKS: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_SET_SIGNAL_MASKS"
|
||||||
"thread: %ld, ignore: %llx (op: %lu), ignore once: %llx "
|
": thread: %" B_PRId32 ", ignore: %" B_PRIx64 " (op: %"
|
||||||
"(op: %lu)\n", nubThread->id, threadID, ignore,
|
B_PRIu32 "), ignore once: %" B_PRIx64 " (op: %" B_PRIu32
|
||||||
ignoreOp, ignoreOnce, ignoreOnceOp));
|
")\n", nubThread->id, threadID, ignore, ignoreOp,
|
||||||
|
ignoreOnce, ignoreOnceOp));
|
||||||
|
|
||||||
// set the masks
|
// set the masks
|
||||||
Thread* thread = Thread::GetAndLock(threadID);
|
Thread* thread = Thread::GetAndLock(threadID);
|
||||||
@@ -2114,10 +2120,11 @@ debug_nub_thread(void *)
|
|||||||
} else
|
} else
|
||||||
result = B_BAD_THREAD_ID;
|
result = B_BAD_THREAD_ID;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_SIGNAL_MASKS: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_GET_SIGNAL_MASKS"
|
||||||
"reply port: %ld, thread: %ld, ignore: %llx, "
|
": reply port: %" B_PRId32 ", thread: %" B_PRId32 ", "
|
||||||
"ignore once: %llx, result: %lx\n", nubThread->id,
|
"ignore: %" B_PRIx64 ", ignore once: %" B_PRIx64 ", result: "
|
||||||
replyPort, threadID, ignore, ignoreOnce, result));
|
"%" B_PRIx32 "\n", nubThread->id, replyPort, threadID,
|
||||||
|
ignore, ignoreOnce, result));
|
||||||
|
|
||||||
// prepare the message
|
// prepare the message
|
||||||
reply.get_signal_masks.error = result;
|
reply.get_signal_masks.error = result;
|
||||||
@@ -2134,9 +2141,9 @@ debug_nub_thread(void *)
|
|||||||
int signal = message.set_signal_handler.signal;
|
int signal = message.set_signal_handler.signal;
|
||||||
struct sigaction &handler = message.set_signal_handler.handler;
|
struct sigaction &handler = message.set_signal_handler.handler;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER"
|
||||||
"signal: %d, handler: %p\n", nubThread->id,
|
": signal: %d, handler: %p\n", nubThread->id, signal,
|
||||||
signal, handler.sa_handler));
|
handler.sa_handler));
|
||||||
|
|
||||||
// set the handler
|
// set the handler
|
||||||
sigaction(signal, &handler, NULL);
|
sigaction(signal, &handler, NULL);
|
||||||
@@ -2157,9 +2164,9 @@ debug_nub_thread(void *)
|
|||||||
result = errno;
|
result = errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER"
|
||||||
"reply port: %ld, signal: %d, handler: %p\n", nubThread->id,
|
": reply port: %" B_PRId32 ", signal: %d, handler: %p\n",
|
||||||
replyPort, signal,
|
nubThread->id, replyPort, signal,
|
||||||
reply.get_signal_handler.handler.sa_handler));
|
reply.get_signal_handler.handler.sa_handler));
|
||||||
|
|
||||||
// prepare the message
|
// prepare the message
|
||||||
@@ -2171,8 +2178,8 @@ debug_nub_thread(void *)
|
|||||||
|
|
||||||
case B_DEBUG_MESSAGE_PREPARE_HANDOVER:
|
case B_DEBUG_MESSAGE_PREPARE_HANDOVER:
|
||||||
{
|
{
|
||||||
TRACE(("nub thread %ld: B_DEBUG_MESSAGE_PREPARE_HANDOVER\n",
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_MESSAGE_PREPARE_HANDOVER"
|
||||||
nubThread->id));
|
"\n", nubThread->id));
|
||||||
|
|
||||||
Team *team = nubThread->team;
|
Team *team = nubThread->team;
|
||||||
|
|
||||||
@@ -2228,9 +2235,9 @@ debug_nub_thread(void *)
|
|||||||
B_DEBUG_MIN_PROFILE_INTERVAL);
|
B_DEBUG_MIN_PROFILE_INTERVAL);
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_START_PROFILER: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_START_PROFILER: "
|
||||||
"thread: %ld, sample area: %ld\n", nubThread->id, threadID,
|
"thread: %" B_PRId32 ", sample area: %" B_PRId32 "\n",
|
||||||
sampleArea));
|
nubThread->id, threadID, sampleArea));
|
||||||
|
|
||||||
if (stackDepth < 1)
|
if (stackDepth < 1)
|
||||||
stackDepth = 1;
|
stackDepth = 1;
|
||||||
@@ -2331,8 +2338,8 @@ debug_nub_thread(void *)
|
|||||||
replyPort = message.stop_profiler.reply_port;
|
replyPort = message.stop_profiler.reply_port;
|
||||||
status_t result = B_OK;
|
status_t result = B_OK;
|
||||||
|
|
||||||
TRACE(("nub thread %ld: B_DEBUG_STOP_PROFILER: "
|
TRACE(("nub thread %" B_PRId32 ": B_DEBUG_STOP_PROFILER: "
|
||||||
"thread: %ld\n", nubThread->id, threadID));
|
"thread: %" B_PRId32 "\n", nubThread->id, threadID));
|
||||||
|
|
||||||
area_id sampleArea = -1;
|
area_id sampleArea = -1;
|
||||||
addr_t* samples = NULL;
|
addr_t* samples = NULL;
|
||||||
@@ -2407,8 +2414,9 @@ debug_nub_thread(void *)
|
|||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
// The debugger port is either not longer existing or we got
|
// The debugger port is either not longer existing or we got
|
||||||
// interrupted by a kill signal. In either case we terminate.
|
// interrupted by a kill signal. In either case we terminate.
|
||||||
TRACE(("nub thread %ld: failed to send reply to port %ld: %s\n",
|
TRACE(("nub thread %" B_PRId32 ": failed to send reply to port "
|
||||||
nubThread->id, replyPort, strerror(error)));
|
"%" B_PRId32 ": %s\n", nubThread->id, replyPort,
|
||||||
|
strerror(error)));
|
||||||
|
|
||||||
nub_thread_cleanup(nubThread);
|
nub_thread_cleanup(nubThread);
|
||||||
return error;
|
return error;
|
||||||
@@ -2470,8 +2478,9 @@ static port_id
|
|||||||
install_team_debugger(team_id teamID, port_id debuggerPort,
|
install_team_debugger(team_id teamID, port_id debuggerPort,
|
||||||
thread_id causingThread, bool useDefault, bool dontReplace)
|
thread_id causingThread, bool useDefault, bool dontReplace)
|
||||||
{
|
{
|
||||||
TRACE(("install_team_debugger(team: %ld, port: %ld, default: %d, "
|
TRACE(("install_team_debugger(team: %" B_PRId32 ", port: %" B_PRId32 ", "
|
||||||
"dontReplace: %d)\n", teamID, debuggerPort, useDefault, dontReplace));
|
"default: %d, dontReplace: %d)\n", teamID, debuggerPort, useDefault,
|
||||||
|
dontReplace));
|
||||||
|
|
||||||
if (useDefault)
|
if (useDefault)
|
||||||
debuggerPort = atomic_get(&sDefaultDebuggerPort);
|
debuggerPort = atomic_get(&sDefaultDebuggerPort);
|
||||||
@@ -2481,7 +2490,7 @@ install_team_debugger(team_id teamID, port_id debuggerPort,
|
|||||||
status_t error = get_port_info(debuggerPort, &debuggerPortInfo);
|
status_t error = get_port_info(debuggerPort, &debuggerPortInfo);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
TRACE(("install_team_debugger(): Failed to get debugger port info: "
|
TRACE(("install_team_debugger(): Failed to get debugger port info: "
|
||||||
"%lx\n", error));
|
"%" B_PRIx32 "\n", error));
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
team_id debuggerTeam = debuggerPortInfo.team;
|
team_id debuggerTeam = debuggerPortInfo.team;
|
||||||
@@ -2490,7 +2499,8 @@ install_team_debugger(team_id teamID, port_id debuggerPort,
|
|||||||
// debugged team.
|
// debugged team.
|
||||||
if (debuggerTeam == team_get_kernel_team_id() || debuggerTeam == teamID) {
|
if (debuggerTeam == team_get_kernel_team_id() || debuggerTeam == teamID) {
|
||||||
TRACE(("install_team_debugger(): Can't debug kernel or debugger team. "
|
TRACE(("install_team_debugger(): Can't debug kernel or debugger team. "
|
||||||
"debugger: %ld, debugged: %ld\n", debuggerTeam, teamID));
|
"debugger: %" B_PRId32 ", debugged: %" B_PRId32 "\n", debuggerTeam,
|
||||||
|
teamID));
|
||||||
return B_NOT_ALLOWED;
|
return B_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2618,13 +2628,14 @@ install_team_debugger(team_id teamID, port_id debuggerPort,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("install_team_debugger() done: handed over to debugger: team: "
|
TRACE(("install_team_debugger() done: handed over to debugger: team: "
|
||||||
"%ld, port: %ld\n", debuggerTeam, debuggerPort));
|
"%" B_PRId32 ", port: %" B_PRId32 "\n", debuggerTeam,
|
||||||
|
debuggerPort));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done || error != B_OK) {
|
if (done || error != B_OK) {
|
||||||
TRACE(("install_team_debugger() done1: %ld\n",
|
TRACE(("install_team_debugger() done1: %" B_PRId32 "\n",
|
||||||
(error == B_OK ? result : error)));
|
(error == B_OK ? result : error)));
|
||||||
finish_debugger_change(team);
|
finish_debugger_change(team);
|
||||||
return (error == B_OK ? result : error);
|
return (error == B_OK ? result : error);
|
||||||
@@ -2708,7 +2719,7 @@ install_team_debugger(team_id teamID, port_id debuggerPort,
|
|||||||
delete breakpointManager;
|
delete breakpointManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("install_team_debugger() done2: %ld\n",
|
TRACE(("install_team_debugger() done2: %" B_PRId32 "\n",
|
||||||
(error == B_OK ? result : error)));
|
(error == B_OK ? result : error)));
|
||||||
return (error == B_OK ? result : error);
|
return (error == B_OK ? result : error);
|
||||||
}
|
}
|
||||||
@@ -2759,7 +2770,8 @@ _user_disable_debugger(int state)
|
|||||||
{
|
{
|
||||||
Team *team = thread_get_current_thread()->team;
|
Team *team = thread_get_current_thread()->team;
|
||||||
|
|
||||||
TRACE(("_user_disable_debugger(%d): team: %ld\n", state, team->id));
|
TRACE(("_user_disable_debugger(%d): team: %" B_PRId32 "\n", state,
|
||||||
|
team->id));
|
||||||
|
|
||||||
cpu_status cpuState = disable_interrupts();
|
cpu_status cpuState = disable_interrupts();
|
||||||
GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
|
GRAB_TEAM_DEBUG_INFO_LOCK(team->debug_info);
|
||||||
@@ -2853,7 +2865,8 @@ _user_remove_team_debugger(team_id teamID)
|
|||||||
status_t
|
status_t
|
||||||
_user_debug_thread(thread_id threadID)
|
_user_debug_thread(thread_id threadID)
|
||||||
{
|
{
|
||||||
TRACE(("[%ld] _user_debug_thread(%ld)\n", find_thread(NULL), threadID));
|
TRACE(("[%" B_PRId32 "] _user_debug_thread(%" B_PRId32 ")\n",
|
||||||
|
find_thread(NULL), threadID));
|
||||||
|
|
||||||
// get the thread
|
// get the thread
|
||||||
Thread* thread = Thread::GetAndLock(threadID);
|
Thread* thread = Thread::GetAndLock(threadID);
|
||||||
|
|||||||
@@ -2506,8 +2506,6 @@ elf_init(kernel_args *args)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
// TODO: x86_64
|
|
||||||
#ifndef __x86_64__
|
|
||||||
/*! Reads the symbol and string table for the kernel image with the given ID.
|
/*! Reads the symbol and string table for the kernel image with the given ID.
|
||||||
\a _symbolCount and \a _stringTableSize are both in- and output parameters.
|
\a _symbolCount and \a _stringTableSize are both in- and output parameters.
|
||||||
When called they call the size of the buffers given by \a symbolTable and
|
When called they call the size of the buffers given by \a symbolTable and
|
||||||
@@ -2519,7 +2517,7 @@ elf_init(kernel_args *args)
|
|||||||
values in the table to get the actual symbol addresses.
|
values in the table to get the actual symbol addresses.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
_user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable,
|
_user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
|
||||||
int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
|
int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
|
||||||
addr_t* _imageDelta)
|
addr_t* _imageDelta)
|
||||||
{
|
{
|
||||||
@@ -2551,7 +2549,7 @@ _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable,
|
|||||||
|
|
||||||
// get the tables and infos
|
// get the tables and infos
|
||||||
addr_t imageDelta = image->text_region.delta;
|
addr_t imageDelta = image->text_region.delta;
|
||||||
const Elf32_Sym* symbols;
|
const elf_sym* symbols;
|
||||||
int32 symbolCount;
|
int32 symbolCount;
|
||||||
const char* strings;
|
const char* strings;
|
||||||
|
|
||||||
@@ -2579,7 +2577,7 @@ _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable,
|
|||||||
// copy symbol table
|
// copy symbol table
|
||||||
int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
|
int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
|
||||||
if (symbolTable != NULL && symbolsToCopy > 0) {
|
if (symbolTable != NULL && symbolsToCopy > 0) {
|
||||||
if (user_memcpy(symbolTable, symbols, sizeof(Elf32_Sym) * symbolsToCopy)
|
if (user_memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy)
|
||||||
!= B_OK) {
|
!= B_OK) {
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
}
|
}
|
||||||
@@ -2605,4 +2603,3 @@ _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable,
|
|||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|||||||
Reference in New Issue
Block a user