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:
Ingo Weinhold
2008-08-24 23:01:43 +00:00
parent 23fdebca54
commit 18f2a9c17d
6 changed files with 208 additions and 20 deletions
+4
View File
@@ -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)
{
+24
View File
@@ -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)
{
+126 -15
View File
@@ -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)
{
+3 -1
View File
@@ -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))) {
+27 -4
View File
@@ -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;
}