Added support for architecture specific debug variables, e.g. for
referencing iframe registers. Their prefix is "$". E.g. "$eax" refers to the eax register of the current iframe. The features cooperates with the "in_context" command, i.e. "in_context 92 $eip = 0" will set the eip register of thread 92 to 0 (thus sealing its fate ;-)). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27192 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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))) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <arch/debug.h>
|
||||
#include <debug.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user