diff --git a/headers/private/kernel/arch/debug.h b/headers/private/kernel/arch/debug.h index 534f64c8de..6efbb5db9b 100644 --- a/headers/private/kernel/arch/debug.h +++ b/headers/private/kernel/arch/debug.h @@ -28,6 +28,10 @@ bool arch_debug_contains_call(struct thread *thread, const char *symbol, addr_t start, addr_t end); void arch_debug_save_registers(int *); +bool arch_is_debug_variable_defined(const char* variableName); +status_t arch_set_debug_variable(const char* variableName, uint64 value); +status_t arch_get_debug_variable(const char* variableName, uint64* value); + #ifdef __cplusplus } #endif diff --git a/src/system/kernel/arch/m68k/arch_debug.cpp b/src/system/kernel/arch/m68k/arch_debug.cpp index 9895430860..155467f049 100644 --- a/src/system/kernel/arch/m68k/arch_debug.cpp +++ b/src/system/kernel/arch/m68k/arch_debug.cpp @@ -347,6 +347,30 @@ arch_debug_get_interrupt_pc() } +bool +arch_is_debug_variable_defined(const char* variableName) +{ + // TODO: Implement! + return false; +} + + +status_t +arch_set_debug_variable(const char* variableName, uint64 value) +{ + // TODO: Implement! + return B_ENTRY_NOT_FOUND; +} + + +status_t +arch_get_debug_variable(const char* variableName, uint64* value) +{ + // TODO: Implement! + return B_ENTRY_NOT_FOUND; +} + + status_t arch_debug_init(kernel_args *args) { diff --git a/src/system/kernel/arch/ppc/arch_debug.cpp b/src/system/kernel/arch/ppc/arch_debug.cpp index bfa7fd3c4e..86144f1f76 100644 --- a/src/system/kernel/arch/ppc/arch_debug.cpp +++ b/src/system/kernel/arch/ppc/arch_debug.cpp @@ -294,6 +294,30 @@ arch_debug_get_interrupt_pc() } +bool +arch_is_debug_variable_defined(const char* variableName) +{ + // TODO: Implement! + return false; +} + + +status_t +arch_set_debug_variable(const char* variableName, uint64 value) +{ + // TODO: Implement! + return B_ENTRY_NOT_FOUND; +} + + +status_t +arch_get_debug_variable(const char* variableName, uint64* value) +{ + // TODO: Implement! + return B_ENTRY_NOT_FOUND; +} + + status_t arch_debug_init(kernel_args *args) { diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index c3dc9b667c..cc81a129a7 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -271,6 +271,88 @@ get_previous_iframe(struct thread* thread, struct iframe* frame) } +static struct iframe* +get_current_iframe(struct thread* thread) +{ + if (thread == thread_get_current_thread()) + return i386_get_current_iframe(); + + addr_t ebp = thread->arch_info.current_stack.esp[2]; + // NOTE: This doesn't work, if the thread is running (on another CPU). + return find_previous_iframe(thread, ebp); +} + + +uint32* +find_debug_variable(const char* variableName, bool& settable) +{ + struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); + if (frame == NULL) + return NULL; + + settable = false; + + if (strcmp(variableName, "gs") == 0) { + return &frame->gs; + } else if (strcmp(variableName, "fs") == 0) { + return &frame->fs; + } else if (strcmp(variableName, "es") == 0) { + return &frame->es; + } else if (strcmp(variableName, "ds") == 0) { + return &frame->ds; + } else if (strcmp(variableName, "cs") == 0) { + return &frame->cs; + } else if (strcmp(variableName, "edi") == 0) { + settable = true; + return &frame->edi; + } else if (strcmp(variableName, "esi") == 0) { + settable = true; + return &frame->esi; + } else if (strcmp(variableName, "ebp") == 0) { + settable = true; + return &frame->ebp; + } else if (strcmp(variableName, "esp") == 0) { + settable = true; + return &frame->esp; + } else if (strcmp(variableName, "ebx") == 0) { + settable = true; + return &frame->ebx; + } else if (strcmp(variableName, "edx") == 0) { + settable = true; + return &frame->edx; + } else if (strcmp(variableName, "ecx") == 0) { + settable = true; + return &frame->ecx; + } else if (strcmp(variableName, "eax") == 0) { + settable = true; + return &frame->eax; + } else if (strcmp(variableName, "orig_eax") == 0) { + settable = true; + return &frame->orig_eax; + } else if (strcmp(variableName, "orig_edx") == 0) { + settable = true; + return &frame->orig_edx; + } else if (strcmp(variableName, "eip") == 0) { + settable = true; + return &frame->eip; + } else if (strcmp(variableName, "eflags") == 0) { + settable = true; + return &frame->flags; + } + + if (IFRAME_IS_USER(frame)) { + if (strcmp(variableName, "user_esp") == 0) { + settable = true; + return &frame->user_esp; + } else if (strcmp(variableName, "user_ss") == 0) { + return &frame->user_ss; + } + } + + return NULL; +} + + static int stack_trace(int argc, char **argv) { @@ -703,30 +785,59 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, return count; } -/*! Returns the program counter of this thread where the innermost interrupts - happened. Returns \c NULL, if there's none or a problem occurred retrieving - it. + +/*! Returns the program counter of the currently debugged (respectively this) + thread where the innermost interrupts happened. Returns \c NULL, if there's + none or a problem occurred retrieving it. */ void* arch_debug_get_interrupt_pc() { - struct thread* thread = debug_get_debugged_thread(); + struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); + if (frame == NULL) + return NULL; - if (thread == thread_get_current_thread()) { - struct iframe* frame = i386_get_current_iframe(); - if (frame == NULL) - return NULL; - - return (void*)(addr_t)frame->eip; - } - - addr_t ebp = thread->arch_info.current_stack.esp[2]; - // NOTE: This doesn't work, if the thread is running (on another CPU). - struct iframe* frame = find_previous_iframe(thread, ebp); return (void*)(addr_t)frame->eip; } +bool +arch_is_debug_variable_defined(const char* variableName) +{ + bool settable; + return find_debug_variable(variableName, settable); +} + + +status_t +arch_set_debug_variable(const char* variableName, uint64 value) +{ + bool settable; + uint32* variable = find_debug_variable(variableName, settable); + if (variable == NULL) + return B_ENTRY_NOT_FOUND; + + if (!settable) + return B_NOT_ALLOWED; + + *variable = (uint32)value; + return B_OK; +} + + +status_t +arch_get_debug_variable(const char* variableName, uint64* value) +{ + bool settable; + uint32* variable = find_debug_variable(variableName, settable); + if (variable == NULL) + return B_ENTRY_NOT_FOUND; + + *value = *variable; + return B_OK; +} + + status_t arch_debug_init(kernel_args *args) { diff --git a/src/system/kernel/debug/debug_parser.cpp b/src/system/kernel/debug/debug_parser.cpp index 2a03c10c97..5076d4fd38 100644 --- a/src/system/kernel/debug/debug_parser.cpp +++ b/src/system/kernel/debug/debug_parser.cpp @@ -278,9 +278,11 @@ public: TOKEN_CONSTANT); fCurrentToken.value = strtoull(fCurrentToken.string, NULL, 0); - } else if (isalpha(*fCurrentChar) || *fCurrentChar == '_') { + } else if (isalpha(*fCurrentChar) || *fCurrentChar == '_' + || *fCurrentChar == '$') { // identifier const char* begin = fCurrentChar; + fCurrentChar++; while (*fCurrentChar != 0 && (isalpha(*fCurrentChar) || *fCurrentChar == '_' || isdigit(*fCurrentChar))) { diff --git a/src/system/kernel/debug/debug_variables.cpp b/src/system/kernel/debug/debug_variables.cpp index 8950f9c8f8..b782f1a2ed 100644 --- a/src/system/kernel/debug/debug_variables.cpp +++ b/src/system/kernel/debug/debug_variables.cpp @@ -9,6 +9,7 @@ #include +#include #include #include @@ -16,7 +17,9 @@ static const int kVariableCount = 64; static const int kTemporaryVariableCount = 32; static const char kTemporaryVariablePrefix = '_'; -static const char* const kCommandReturnValueVariable = "_"; +static const char kArchSpecificVariablePrefix = '$'; +static const char* const kCommandReturnValueVariable = "_"; + struct Variable { char name[MAX_DEBUG_VARIABLE_NAME_LEN]; @@ -60,6 +63,13 @@ is_temporary_variable(const char* variableName) } +static inline bool +is_arch_specific_variable(const char* variableName) +{ + return variableName[0] == kArchSpecificVariablePrefix; +} + + static void dequeue_temporary_variable(TemporaryVariable* variable) { @@ -117,7 +127,7 @@ get_variable(const char* variableName, bool create) // temporary variable for (int i = 0; i < kTemporaryVariableCount; i++) { TemporaryVariable* variable = sTemporaryVariables + i; - + if (!variable->IsUsed()) { if (freeSlot == NULL) freeSlot = variable; @@ -131,7 +141,7 @@ get_variable(const char* variableName, bool create) // persistent variable for (int i = 0; i < kVariableCount; i++) { Variable* variable = sVariables + i; - + if (!variable->IsUsed()) { if (freeSlot == NULL) freeSlot = variable; @@ -226,13 +236,20 @@ cmd_variables(int argc, char **argv) bool is_debug_variable_defined(const char* variableName) { - return get_variable(variableName, false) != NULL; + if (get_variable(variableName, false) != NULL) + return true; + + return is_arch_specific_variable(variableName) + && arch_is_debug_variable_defined(variableName + 1); } bool set_debug_variable(const char* variableName, uint64 value) { + if (is_arch_specific_variable(variableName)) + return arch_set_debug_variable(variableName + 1, value) == B_OK; + if (Variable* variable = get_variable(variableName, true)) { variable->value = value; touch_variable(variable); @@ -251,6 +268,12 @@ get_debug_variable(const char* variableName, uint64 defaultValue) return variable->value; } + uint64 value; + if (is_arch_specific_variable(variableName) + && arch_get_debug_variable(variableName + 1, &value) == B_OK) { + return value; + } + return defaultValue; }