Implemented the rest of the kernel debugger functions for x86_64.

Merged with the x86 implementations, mostly the same except for a
few differences. GDB stub is currently broken, will investigate
later.
This commit is contained in:
Alex Smith
2012-07-13 14:09:09 +01:00
parent e690e5ab3b
commit bcb07a319b
6 changed files with 336 additions and 424 deletions
+8 -1
View File
@@ -29,9 +29,16 @@ struct iframe {
uint64 cs; uint64 cs;
uint64 flags; uint64 flags;
// Only present when the iframe is a userland iframe (IFRAME_IS_USER()). // SP and SS are unconditionally present on x86_64, make both names
// available.
union {
uint64 sp;
uint64 user_sp; uint64 user_sp;
};
union {
uint64 ss;
uint64 user_ss; uint64 user_ss;
};
} _PACKED; } _PACKED;
#define IFRAME_IS_USER(f) (((f)->cs & DPL_USER) == DPL_USER) #define IFRAME_IS_USER(f) (((f)->cs & DPL_USER) == DPL_USER)
@@ -48,6 +48,8 @@ struct arch_thread {
// 512 byte floating point save point - this must be 16 byte aligned // 512 byte floating point save point - this must be 16 byte aligned
uint8 fpu_state[512] _ALIGNED(16); uint8 fpu_state[512] _ALIGNED(16);
addr_t GetFramePointer() const;
} _ALIGNED(16); } _ALIGNED(16);
@@ -64,4 +66,26 @@ struct arch_fork_arg {
}; };
#endif /* _KERNEL_ARCH_x86_THREAD_TYPES_H */ #ifdef __x86_64__
inline addr_t
arch_thread::GetFramePointer() const
{
return current_stack[1];
}
#else
inline addr_t
arch_thread::GetFramePointer() const
{
return current_stack.esp[2];
}
#endif // __x86_64__
#endif // _KERNEL_ARCH_x86_THREAD_TYPES_H
-209
View File
@@ -51,215 +51,6 @@ arch_commpage_init_post_cpus(void)
} }
void
arch_debug_save_registers(struct arch_debug_registers* registers)
{
}
struct stack_frame {
struct stack_frame *previous;
addr_t return_address;
};
static bool
is_iframe(addr_t frame)
{
addr_t previousFrame = *(addr_t*)frame;
return ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0
&& previousFrame != 0);
}
static void
print_iframe(struct iframe* frame)
{
bool isUser = IFRAME_IS_USER(frame);
kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
isUser ? (uint64*)(frame + 1) : &frame->user_sp);
kprintf(" rax 0x%-16lx rbx 0x%-16lx rcx 0x%lx\n", frame->ax,
frame->bx, frame->cx);
kprintf(" rdx 0x%-16lx rsi 0x%-16lx rdi 0x%lx\n", frame->dx,
frame->si, frame->di);
kprintf(" rbp 0x%-16lx r8 0x%-16lx r9 0x%lx\n", frame->bp,
frame->r8, frame->r9);
kprintf(" r10 0x%-16lx r11 0x%-16lx r12 0x%lx\n", frame->r10,
frame->r11, frame->r12);
kprintf(" r13 0x%-16lx r14 0x%-16lx r15 0x%lx\n", frame->r13,
frame->r14, frame->r15);
kprintf(" rip 0x%-16lx rflags 0x%-16lx", frame->ip, frame->flags);
if (isUser) {
// from user space
kprintf("user rsp 0x%lx", frame->user_sp);
}
kprintf("\n");
kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector,
frame->error_code);
}
static status_t
lookup_symbol(addr_t address, addr_t* _baseAddress, const char** _symbolName,
const char** _imageName, bool* _exactMatch)
{
status_t status = B_ENTRY_NOT_FOUND;
if (IS_KERNEL_ADDRESS(address)) {
status = elf_debug_lookup_symbol_address(address, _baseAddress,
_symbolName, _imageName, _exactMatch);
}
return status;
}
static void
print_stack_frame(addr_t rip, addr_t rbp, addr_t nextRbp, int32 callIndex)
{
const char* symbol;
const char* image;
addr_t baseAddress;
bool exactMatch;
status_t status;
addr_t diff;
diff = nextRbp - rbp;
// kernel space/user space switch
if (diff & (1L << 63))
diff = 0;
status = lookup_symbol(rip, &baseAddress, &symbol, &image, &exactMatch);
kprintf("%2d %016lx (+%4ld) %016lx ", callIndex, rbp, diff, rip);
if (status == B_OK) {
if (symbol != NULL)
kprintf("<%s>:%s%s", image, symbol, exactMatch ? "" : " (nearest)");
else
kprintf("<%s@%p>:unknown", image, (void*)baseAddress);
kprintf(" + 0x%04lx\n", rip - baseAddress);
} else {
VMArea *area = VMAddressSpace::Kernel()->LookupArea(rip);
if (area != NULL) {
kprintf("%d:%s@%p + %#lx\n", area->id, area->name,
(void*)area->Base(), rip - area->Base());
} else
kprintf("\n");
}
}
void
arch_debug_stack_trace(void)
{
addr_t rbp = x86_get_stack_frame();
kprintf("frame caller <image>:function"
" + offset\n");
for (int32 callIndex = 0;; callIndex++) {
if (rbp == 0)
break;
if (is_iframe(rbp)) {
struct iframe* frame = (struct iframe*)rbp;
print_iframe(frame);
print_stack_frame(frame->ip, rbp, frame->bp, callIndex);
rbp = frame->bp;
} else {
stack_frame* frame = (stack_frame*)rbp;
if (frame->return_address == 0)
break;
print_stack_frame(frame->return_address, rbp,
(frame->previous != NULL) ? (addr_t)frame->previous : rbp,
callIndex);
rbp = (addr_t)frame->previous;
}
}
}
bool
arch_debug_contains_call(Thread *thread, const char *symbol,
addr_t start, addr_t end)
{
return false;
}
void *
arch_debug_get_caller(void)
{
return NULL;
}
int32
arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
int32 skipIframes, int32 skipFrames, uint32 flags)
{
return 0;
}
void*
arch_debug_get_interrupt_pc(bool* _isSyscall)
{
return NULL;
}
void
arch_debug_unset_current_thread(void)
{
}
bool
arch_is_debug_variable_defined(const char* variableName)
{
return false;
}
status_t
arch_set_debug_variable(const char* variableName, uint64 value)
{
return B_OK;
}
status_t
arch_get_debug_variable(const char* variableName, uint64* value)
{
return B_OK;
}
ssize_t
arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
{
return B_ERROR;
}
status_t
arch_debug_init(kernel_args *args)
{
return B_OK;
}
void void
arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer,
void (*function)(void*), void* parameter) void (*function)(void*), void* parameter)
+1 -1
View File
@@ -51,7 +51,6 @@ if $(TARGET_ARCH) = x86_64 {
vm86.cpp vm86.cpp
arch_commpage.cpp arch_commpage.cpp
arch_debug.cpp
arch_user_debugger.cpp arch_user_debugger.cpp
ioapic.cpp ioapic.cpp
irq_routing_table.cpp irq_routing_table.cpp
@@ -78,6 +77,7 @@ if $(TARGET_ARCH) = x86_64 {
local archGenericSources = local archGenericSources =
arch_cpu.cpp arch_cpu.cpp
arch_debug.cpp
arch_debug_console.cpp arch_debug_console.cpp
arch_elf.cpp arch_elf.cpp
arch_int.cpp arch_int.cpp
+295 -199
View File
@@ -1,6 +1,7 @@
/* /*
* Copyright 2009-2011, Ingo Weinhold, [email protected]. * Copyright 2009-2011, Ingo Weinhold, [email protected].
* Copyright 2002-2008, Axel Dörfler, [email protected]. * Copyright 2002-2008, Axel Dörfler, [email protected].
* Copyright 2012, Alex Smith, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2001, Travis Geiselbrecht. All rights reserved. * Copyright 2001, Travis Geiselbrecht. All rights reserved.
@@ -28,11 +29,9 @@
#include <vm/VMAddressSpace.h> #include <vm/VMAddressSpace.h>
#include <vm/VMArea.h> #include <vm/VMArea.h>
#include <arch_cpu.h>
struct stack_frame { struct stack_frame {
struct stack_frame *previous; stack_frame* previous;
addr_t return_address; addr_t return_address;
}; };
@@ -40,19 +39,19 @@ struct stack_frame {
static bool static bool
already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp) already_visited(addr_t* visited, int32* _last, int32* _num, addr_t bp)
{ {
int32 last = *_last; int32 last = *_last;
int32 num = *_num; int32 num = *_num;
int32 i; int32 i;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == ebp) if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == bp)
return true; return true;
} }
*_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS; *_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS;
visited[last] = ebp; visited[last] = bp;
if (num < NUM_PREVIOUS_LOCATIONS) if (num < NUM_PREVIOUS_LOCATIONS)
*_num = num + 1; *_num = num + 1;
@@ -64,14 +63,14 @@ already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp)
/*! Safe to be called only from outside the debugger. /*! Safe to be called only from outside the debugger.
*/ */
static status_t static status_t
get_next_frame_no_debugger(addr_t ebp, addr_t *_next, addr_t *_eip) get_next_frame_no_debugger(addr_t bp, addr_t* _next, addr_t* _ip)
{ {
// TODO: Do this more efficiently in assembly. // TODO: Do this more efficiently in assembly.
stack_frame frame; stack_frame frame;
if (user_memcpy(&frame, (void*)ebp, sizeof(frame)) != B_OK) if (user_memcpy(&frame, (void*)bp, sizeof(frame)) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
*_eip = frame.return_address; *_ip = frame.return_address;
*_next = (addr_t)frame.previous; *_next = (addr_t)frame.previous;
return B_OK; return B_OK;
@@ -81,13 +80,13 @@ get_next_frame_no_debugger(addr_t ebp, addr_t *_next, addr_t *_eip)
/*! Safe to be called only from inside the debugger. /*! Safe to be called only from inside the debugger.
*/ */
static status_t static status_t
get_next_frame_debugger(addr_t ebp, addr_t *_next, addr_t *_eip) get_next_frame_debugger(addr_t bp, addr_t* _next, addr_t* _ip)
{ {
stack_frame frame; stack_frame frame;
if (debug_memcpy(B_CURRENT_TEAM, &frame, (void*)ebp, sizeof(frame)) != B_OK) if (debug_memcpy(B_CURRENT_TEAM, &frame, (void*)bp, sizeof(frame)) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
*_eip = frame.return_address; *_ip = frame.return_address;
*_next = (addr_t)frame.previous; *_next = (addr_t)frame.previous;
return B_OK; return B_OK;
@@ -95,8 +94,8 @@ get_next_frame_debugger(addr_t ebp, addr_t *_next, addr_t *_eip)
static status_t static status_t
lookup_symbol(Thread* thread, addr_t address, addr_t *_baseAddress, lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress,
const char **_symbolName, const char **_imageName, bool *_exactMatch) const char** _symbolName, const char** _imageName, bool* _exactMatch)
{ {
status_t status = B_ENTRY_NOT_FOUND; status_t status = B_ENTRY_NOT_FOUND;
@@ -120,6 +119,9 @@ lookup_symbol(Thread* thread, addr_t address, addr_t *_baseAddress,
} }
#ifndef __x86_64__
static void static void
set_debug_argument_variable(int32 index, uint64 value) set_debug_argument_variable(int32 index, uint64 value)
{ {
@@ -307,31 +309,53 @@ print_demangled_call(const char* image, const char* symbol, addr_t args,
} }
#else // __x86_64__
static status_t
print_demangled_call(const char* image, const char* symbol, addr_t args,
bool noObjectMethod, bool addDebugVariables)
{
// Since x86_64 uses registers rather than the stack for the first 6
// arguments we cannot use the same method as x86 to read the function
// arguments. Maybe we need DWARF support in the kernel debugger. For now
// just print out the function signature without the argument values.
// TODO x86_64.
return B_NOT_SUPPORTED;
}
#endif // __x86_64__
static void static void
print_stack_frame(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, print_stack_frame(Thread* thread, addr_t ip, addr_t bp, addr_t nextBp,
int32 callIndex, bool demangle) int32 callIndex, bool demangle)
{ {
const char *symbol, *image; const char* symbol;
const char* image;
addr_t baseAddress; addr_t baseAddress;
bool exactMatch; bool exactMatch;
status_t status; status_t status;
addr_t diff; addr_t diff;
diff = nextEbp - ebp; diff = nextBp - bp;
// kernel space/user space switch // MSB set = kernel space/user space switch
if (diff & 0x80000000) if (diff & ~((addr_t)-1 >> 1))
diff = 0; diff = 0;
status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image, status = lookup_symbol(thread, ip, &baseAddress, &symbol, &image,
&exactMatch); &exactMatch);
kprintf("%2ld %08lx (+%4ld) %08lx ", callIndex, ebp, diff, eip); kprintf("%2" B_PRId32 " %0*lx (+%4ld) %0*lx ", callIndex,
B_PRINTF_POINTER_WIDTH, bp, diff, B_PRINTF_POINTER_WIDTH, ip);
if (status == B_OK) { if (status == B_OK) {
if (exactMatch && demangle) { if (exactMatch && demangle) {
status = print_demangled_call(image, symbol, nextEbp + 8, false, status = print_demangled_call(image, symbol,
false); nextBp + sizeof(stack_frame), false, false);
} }
if (!exactMatch || !demangle || status != B_OK) { if (!exactMatch || !demangle || status != B_OK) {
@@ -339,19 +363,19 @@ print_stack_frame(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
kprintf("<%s>:%s%s", image, symbol, kprintf("<%s>:%s%s", image, symbol,
exactMatch ? "" : " (nearest)"); exactMatch ? "" : " (nearest)");
} else } else
kprintf("<%s@%p>:unknown", image, (void *)baseAddress); kprintf("<%s@%p>:unknown", image, (void*)baseAddress);
} }
kprintf(" + 0x%04lx\n", eip - baseAddress); kprintf(" + %#04lx\n", ip - baseAddress);
} else { } else {
VMArea *area = NULL; VMArea *area = NULL;
if (thread != NULL && thread->team != NULL if (thread != NULL && thread->team != NULL
&& thread->team->address_space != NULL) { && thread->team->address_space != NULL) {
area = thread->team->address_space->LookupArea(eip); area = thread->team->address_space->LookupArea(ip);
} }
if (area != NULL) { if (area != NULL) {
kprintf("%ld:%s@%p + %#lx\n", area->id, area->name, kprintf("%" B_PRId32 ":%s@%p + %#lx\n", area->id, area->name,
(void*)area->Base(), eip - area->Base()); (void*)area->Base(), ip - area->Base());
} else } else
kprintf("\n"); kprintf("\n");
} }
@@ -359,45 +383,65 @@ print_stack_frame(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
static void static void
print_iframe(struct iframe *frame) print_iframe(iframe* frame)
{ {
bool isUser = IFRAME_IS_USER(frame); bool isUser = IFRAME_IS_USER(frame);
kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
isUser ? (uint32*)(frame + 1) : &frame->user_sp);
kprintf(" eax 0x%-9lx ebx 0x%-9lx ecx 0x%-9lx edx 0x%lx\n", #ifdef __x86_64__
kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
frame + 1);
kprintf(" rax %#-18lx rbx %#-18lx rcx %#lx\n", frame->ax,
frame->bx, frame->cx);
kprintf(" rdx %#-18lx rsi %#-18lx rdi %#lx\n", frame->dx,
frame->si, frame->di);
kprintf(" rbp %#-18lx r8 %#-18lx r9 %#lx\n", frame->bp,
frame->r8, frame->r9);
kprintf(" r10 %#-18lx r11 %#-18lx r12 %#lx\n", frame->r10,
frame->r11, frame->r12);
kprintf(" r13 %#-18lx r14 %#-18lx r15 %#lx\n", frame->r13,
frame->r14, frame->r15);
kprintf(" rip %#-18lx rsp %#-18lx rflags %#lx\n", frame->ip,
frame->sp, frame->flags);
#else
kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame,
isUser ? (void*)(frame + 1) : (void*)&frame->user_sp);
kprintf(" eax %#-10lx ebx %#-10lx ecx %#-10lx edx %#lx\n",
frame->ax, frame->bx, frame->cx, frame->dx); frame->ax, frame->bx, frame->cx, frame->dx);
kprintf(" esi 0x%-9lx edi 0x%-9lx ebp 0x%-9lx esp 0x%lx\n", kprintf(" esi %#-10lx edi %#-10lx ebp %#-10lx esp %#lx\n",
frame->si, frame->di, frame->bp, frame->sp); frame->si, frame->di, frame->bp, frame->sp);
kprintf(" eip 0x%-9lx eflags 0x%-9lx", frame->ip, frame->flags); kprintf(" eip %#-10lx eflags %#-10lx", frame->ip, frame->flags);
if (isUser) { if (isUser) {
// from user space // from user space
kprintf("user esp 0x%lx", frame->user_sp); kprintf("user esp %#lx", frame->user_sp);
} }
kprintf("\n"); kprintf("\n");
kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector, #endif
kprintf(" vector: %#lx, error code: %#lx\n", frame->vector,
frame->error_code); frame->error_code);
} }
static bool static bool
setup_for_thread(char *arg, Thread **_thread, uint32 *_ebp, setup_for_thread(char* arg, Thread** _thread, addr_t* _bp,
uint32 *_oldPageDirectory) phys_addr_t* _oldPageDirectory)
{ {
Thread *thread = NULL; Thread* thread = NULL;
if (arg != NULL) { if (arg != NULL) {
thread_id id = strtoul(arg, NULL, 0); thread_id id = strtoul(arg, NULL, 0);
thread = Thread::GetDebug(id); thread = Thread::GetDebug(id);
if (thread == NULL) { if (thread == NULL) {
kprintf("could not find thread %ld\n", id); kprintf("could not find thread %" B_PRId32 "\n", id);
return false; return false;
} }
if (id != thread_get_current_thread_id()) { if (id != thread_get_current_thread_id()) {
// switch to the page directory of the new thread to be // switch to the page directory of the new thread to be
// able to follow the stack trace into userland // able to follow the stack trace into userland
uint32 newPageDirectory = x86_next_page_directory( phys_addr_t newPageDirectory = x86_next_page_directory(
thread_get_current_thread(), thread); thread_get_current_thread(), thread);
if (newPageDirectory != 0) { if (newPageDirectory != 0) {
@@ -413,10 +457,10 @@ setup_for_thread(char *arg, Thread **_thread, uint32 *_ebp,
thread->cpu->cpu_num); thread->cpu->cpu_num);
if (registers == NULL) if (registers == NULL)
return false; return false;
*_ebp = registers->bp; *_bp = registers->bp;
} else { } else {
// read %ebp from the thread's stack stored by a pushad // Read frame pointer from the thread's stack.
*_ebp = thread->arch_info.current_stack.esp[2]; *_bp = thread->arch_info.GetFramePointer();
} }
} else } else
thread = NULL; thread = NULL;
@@ -474,13 +518,13 @@ is_iframe(Thread* thread, addr_t frame)
} }
static struct iframe * static iframe*
find_previous_iframe(Thread *thread, addr_t frame) find_previous_iframe(Thread* thread, addr_t frame)
{ {
// iterate backwards through the stack frames, until we hit an iframe // iterate backwards through the stack frames, until we hit an iframe
while (is_kernel_stack_address(thread, frame)) { while (is_kernel_stack_address(thread, frame)) {
if (is_iframe(thread, frame)) if (is_iframe(thread, frame))
return (struct iframe*)frame; return (iframe*)frame;
frame = *(addr_t*)frame; frame = *(addr_t*)frame;
} }
@@ -489,8 +533,8 @@ find_previous_iframe(Thread *thread, addr_t frame)
} }
static struct iframe* static iframe*
get_previous_iframe(Thread* thread, struct iframe* frame) get_previous_iframe(Thread* thread, iframe* frame)
{ {
if (frame == NULL) if (frame == NULL)
return NULL; return NULL;
@@ -499,90 +543,83 @@ get_previous_iframe(Thread* thread, struct iframe* frame)
} }
static struct iframe* static iframe*
get_current_iframe(Thread* thread) get_current_iframe(Thread* thread)
{ {
if (thread == thread_get_current_thread()) if (thread == thread_get_current_thread())
return x86_get_current_iframe(); return x86_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). // NOTE: This doesn't work, if the thread is running (on another CPU).
return find_previous_iframe(thread, ebp); return find_previous_iframe(thread, thread->arch_info.GetFramePointer());
} }
uint32* #define CHECK_DEBUG_VARIABLE(_name, _member, _settable) \
if (strcmp(variableName, _name) == 0) { \
settable = _settable; \
return &_member; \
}
static size_t*
find_debug_variable(const char* variableName, bool& settable) find_debug_variable(const char* variableName, bool& settable)
{ {
struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); iframe* frame = get_current_iframe(debug_get_debugged_thread());
if (frame == NULL) if (frame == NULL)
return NULL; return NULL;
settable = false; #ifdef __x86_64__
CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
if (strcmp(variableName, "gs") == 0) { CHECK_DEBUG_VARIABLE("ss", frame->ss, false);
return &frame->gs; CHECK_DEBUG_VARIABLE("r15", frame->r15, true);
} else if (strcmp(variableName, "fs") == 0) { CHECK_DEBUG_VARIABLE("r14", frame->r14, true);
return &frame->fs; CHECK_DEBUG_VARIABLE("r13", frame->r13, true);
} else if (strcmp(variableName, "es") == 0) { CHECK_DEBUG_VARIABLE("r12", frame->r12, true);
return &frame->es; CHECK_DEBUG_VARIABLE("r11", frame->r11, true);
} else if (strcmp(variableName, "ds") == 0) { CHECK_DEBUG_VARIABLE("r10", frame->r10, true);
return &frame->ds; CHECK_DEBUG_VARIABLE("r9", frame->r9, true);
} else if (strcmp(variableName, "cs") == 0) { CHECK_DEBUG_VARIABLE("r8", frame->r8, true);
return &frame->cs; CHECK_DEBUG_VARIABLE("rbp", frame->bp, true);
} else if (strcmp(variableName, "edi") == 0) { CHECK_DEBUG_VARIABLE("rsi", frame->si, true);
settable = true; CHECK_DEBUG_VARIABLE("rdi", frame->di, true);
return &frame->di; CHECK_DEBUG_VARIABLE("rdx", frame->dx, true);
} else if (strcmp(variableName, "esi") == 0) { CHECK_DEBUG_VARIABLE("rcx", frame->cx, true);
settable = true; CHECK_DEBUG_VARIABLE("rbx", frame->bx, true);
return &frame->si; CHECK_DEBUG_VARIABLE("rax", frame->ax, true);
} else if (strcmp(variableName, "ebp") == 0) { CHECK_DEBUG_VARIABLE("rip", frame->ip, true);
settable = true; CHECK_DEBUG_VARIABLE("rflags", frame->flags, true);
return &frame->bp; CHECK_DEBUG_VARIABLE("rsp", frame->sp, true);
} else if (strcmp(variableName, "esp") == 0) { #else
settable = true; CHECK_DEBUG_VARIABLE("gs", frame->gs, false);
return &frame->sp; CHECK_DEBUG_VARIABLE("fs", frame->fs, false);
} else if (strcmp(variableName, "ebx") == 0) { CHECK_DEBUG_VARIABLE("es", frame->es, false);
settable = true; CHECK_DEBUG_VARIABLE("ds", frame->ds, false);
return &frame->bx; CHECK_DEBUG_VARIABLE("cs", frame->cs, false);
} else if (strcmp(variableName, "edx") == 0) { CHECK_DEBUG_VARIABLE("edi", frame->di, true);
settable = true; CHECK_DEBUG_VARIABLE("esi", frame->si, true);
return &frame->dx; CHECK_DEBUG_VARIABLE("ebp", frame->bp, true);
} else if (strcmp(variableName, "ecx") == 0) { CHECK_DEBUG_VARIABLE("esp", frame->sp, true);
settable = true; CHECK_DEBUG_VARIABLE("ebx", frame->bx, true);
return &frame->cx; CHECK_DEBUG_VARIABLE("edx", frame->dx, true);
} else if (strcmp(variableName, "eax") == 0) { CHECK_DEBUG_VARIABLE("ecx", frame->cx, true);
settable = true; CHECK_DEBUG_VARIABLE("eax", frame->ax, true);
return &frame->ax; CHECK_DEBUG_VARIABLE("orig_eax", frame->orig_eax, true);
} else if (strcmp(variableName, "orig_eax") == 0) { CHECK_DEBUG_VARIABLE("orig_edx", frame->orig_edx, true);
settable = true; CHECK_DEBUG_VARIABLE("eip", frame->ip, true);
return &frame->orig_eax; CHECK_DEBUG_VARIABLE("eflags", frame->flags, true);
} else if (strcmp(variableName, "orig_edx") == 0) {
settable = true;
return &frame->orig_edx;
} else if (strcmp(variableName, "eip") == 0) {
settable = true;
return &frame->ip;
} else if (strcmp(variableName, "eflags") == 0) {
settable = true;
return &frame->flags;
}
if (IFRAME_IS_USER(frame)) { if (IFRAME_IS_USER(frame)) {
if (strcmp(variableName, "user_esp") == 0) { CHECK_DEBUG_VARIABLE("user_esp", frame->user_sp, true);
settable = true; CHECK_DEBUG_VARIABLE("user_ss", frame->user_ss, false);
return &frame->user_sp;
} else if (strcmp(variableName, "user_ss") == 0) {
return &frame->user_ss;
}
} }
#endif
return NULL; return NULL;
} }
static int static int
stack_trace(int argc, char **argv) stack_trace(int argc, char** argv)
{ {
static const char* usage = "usage: %s [-d] [ <thread id> ]\n" static const char* usage = "usage: %s [-d] [ <thread id> ]\n"
"Prints a stack trace for the current, respectively the specified\n" "Prints a stack trace for the current, respectively the specified\n"
@@ -603,68 +640,69 @@ stack_trace(int argc, char **argv)
return 0; return 0;
} }
uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; addr_t previousLocations[NUM_PREVIOUS_LOCATIONS];
Thread *thread = NULL; Thread* thread = NULL;
uint32 oldPageDirectory = 0; phys_addr_t oldPageDirectory = 0;
uint32 ebp = x86_get_stack_frame(); addr_t bp = x86_get_stack_frame();
int32 num = 0, last = 0; int32 num = 0, last = 0;
if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL, if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL,
&thread, &ebp, &oldPageDirectory)) &thread, &bp, &oldPageDirectory))
return 0; return 0;
DebuggedThreadSetter threadSetter(thread); DebuggedThreadSetter threadSetter(thread);
if (thread != NULL) { if (thread != NULL) {
kprintf("stack trace for thread %ld \"%s\"\n", thread->id, kprintf("stack trace for thread %" B_PRId32 " \"%s\"\n", thread->id,
thread->name); thread->name);
kprintf(" kernel stack: %p to %p\n", kprintf(" kernel stack: %p to %p\n",
(void *)thread->kernel_stack_base, (void*)thread->kernel_stack_base,
(void *)(thread->kernel_stack_top)); (void*)(thread->kernel_stack_top));
if (thread->user_stack_base != 0) { if (thread->user_stack_base != 0) {
kprintf(" user stack: %p to %p\n", kprintf(" user stack: %p to %p\n",
(void *)thread->user_stack_base, (void*)thread->user_stack_base,
(void *)(thread->user_stack_base + thread->user_stack_size)); (void*)(thread->user_stack_base + thread->user_stack_size));
} }
} }
kprintf("frame caller <image>:function + offset\n"); kprintf("%-*s %-*s <image>:function + offset\n",
B_PRINTF_POINTER_WIDTH, "frame", B_PRINTF_POINTER_WIDTH, "caller");
bool onKernelStack = true; bool onKernelStack = true;
for (int32 callIndex = 0;; callIndex++) { for (int32 callIndex = 0;; callIndex++) {
onKernelStack = onKernelStack onKernelStack = onKernelStack
&& is_kernel_stack_address(thread, ebp); && is_kernel_stack_address(thread, bp);
if (onKernelStack && is_iframe(thread, ebp)) { if (onKernelStack && is_iframe(thread, bp)) {
struct iframe *frame = (struct iframe *)ebp; iframe* frame = (iframe*)bp;
print_iframe(frame); print_iframe(frame);
print_stack_frame(thread, frame->ip, ebp, frame->bp, callIndex, print_stack_frame(thread, frame->ip, bp, frame->bp, callIndex,
demangle); demangle);
ebp = frame->bp; bp = frame->bp;
} else { } else {
addr_t eip, nextEbp; addr_t ip, nextBp;
if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) { if (get_next_frame_debugger(bp, &nextBp, &ip) != B_OK) {
kprintf("%08lx -- read fault\n", ebp); kprintf("%0*lx -- read fault\n", B_PRINTF_POINTER_WIDTH, bp);
break; break;
} }
if (eip == 0 || ebp == 0) if (ip == 0 || bp == 0)
break; break;
print_stack_frame(thread, eip, ebp, nextEbp, callIndex, demangle); print_stack_frame(thread, ip, bp, nextBp, callIndex, demangle);
ebp = nextEbp; bp = nextBp;
} }
if (already_visited(previousLocations, &last, &num, ebp)) { if (already_visited(previousLocations, &last, &num, bp)) {
kprintf("circular stack frame: %p!\n", (void *)ebp); kprintf("circular stack frame: %p!\n", (void*)bp);
break; break;
} }
if (ebp == 0) if (bp == 0)
break; break;
} }
@@ -677,6 +715,7 @@ stack_trace(int argc, char **argv)
} }
#ifndef __x86_64__
static void static void
print_call(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, print_call(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
int32 argCount) int32 argCount)
@@ -759,7 +798,7 @@ show_call(int argc, char **argv)
} }
Thread *thread = NULL; Thread *thread = NULL;
uint32 oldPageDirectory = 0; phys_addr_t oldPageDirectory = 0;
addr_t ebp = x86_get_stack_frame(); addr_t ebp = x86_get_stack_frame();
int32 argCount = 0; int32 argCount = 0;
@@ -835,10 +874,11 @@ show_call(int argc, char **argv)
return 0; return 0;
} }
#endif
static int static int
dump_iframes(int argc, char **argv) dump_iframes(int argc, char** argv)
{ {
static const char* usage = "usage: %s [ <thread id> ]\n" static const char* usage = "usage: %s [ <thread id> ]\n"
"Prints the iframe stack for the current, respectively the specified\n" "Prints the iframe stack for the current, respectively the specified\n"
@@ -850,7 +890,7 @@ dump_iframes(int argc, char **argv)
return 0; return 0;
} }
Thread *thread = NULL; Thread* thread = NULL;
if (argc < 2) { if (argc < 2) {
thread = thread_get_current_thread(); thread = thread_get_current_thread();
@@ -858,7 +898,7 @@ dump_iframes(int argc, char **argv)
thread_id id = strtoul(argv[1], NULL, 0); thread_id id = strtoul(argv[1], NULL, 0);
thread = Thread::GetDebug(id); thread = Thread::GetDebug(id);
if (thread == NULL) { if (thread == NULL) {
kprintf("could not find thread %ld\n", id); kprintf("could not find thread %" B_PRId32 "\n", id);
return 0; return 0;
} }
} else if (argc > 2) { } else if (argc > 2) {
@@ -866,12 +906,14 @@ dump_iframes(int argc, char **argv)
return 0; return 0;
} }
if (thread != NULL) if (thread != NULL) {
kprintf("iframes for thread %ld \"%s\"\n", thread->id, thread->name); kprintf("iframes for thread %" B_PRId32 " \"%s\"\n", thread->id,
thread->name);
}
DebuggedThreadSetter threadSetter(thread); DebuggedThreadSetter threadSetter(thread);
struct iframe* frame = find_previous_iframe(thread, x86_get_stack_frame()); iframe* frame = find_previous_iframe(thread, x86_get_stack_frame());
while (frame != NULL) { while (frame != NULL) {
print_iframe(frame); print_iframe(frame);
frame = get_previous_iframe(thread, frame); frame = get_previous_iframe(thread, frame);
@@ -882,17 +924,17 @@ dump_iframes(int argc, char **argv)
static bool static bool
is_calling(Thread *thread, addr_t eip, const char *pattern, is_calling(Thread* thread, addr_t ip, const char* pattern, addr_t start,
addr_t start, addr_t end) addr_t end)
{ {
if (pattern == NULL) if (pattern == NULL)
return eip >= start && eip < end; return ip >= start && ip < end;
if (!IS_KERNEL_ADDRESS(eip)) if (!IS_KERNEL_ADDRESS(ip))
return false; return false;
const char *symbol; const char* symbol;
if (lookup_symbol(thread, eip, NULL, &symbol, NULL, NULL) != B_OK) if (lookup_symbol(thread, ip, NULL, &symbol, NULL, NULL) != B_OK)
return false; return false;
return strstr(symbol, pattern); return strstr(symbol, pattern);
@@ -933,9 +975,9 @@ cmd_in_context(int argc, char** argv)
} }
// switch the page directory, if necessary // switch the page directory, if necessary
uint32 oldPageDirectory = 0; phys_addr_t oldPageDirectory = 0;
if (thread != thread_get_current_thread()) { if (thread != thread_get_current_thread()) {
uint32 newPageDirectory = x86_next_page_directory( phys_addr_t newPageDirectory = x86_next_page_directory(
thread_get_current_thread(), thread); thread_get_current_thread(), thread);
if (newPageDirectory != 0) { if (newPageDirectory != 0) {
@@ -962,7 +1004,7 @@ cmd_in_context(int argc, char** argv)
void void
arch_debug_save_registers(struct arch_debug_registers* registers) arch_debug_save_registers(arch_debug_registers* registers)
{ {
// get the caller's frame pointer // get the caller's frame pointer
stack_frame* frame = (stack_frame*)x86_get_stack_frame(); stack_frame* frame = (stack_frame*)x86_get_stack_frame();
@@ -978,14 +1020,14 @@ arch_debug_stack_trace(void)
bool bool
arch_debug_contains_call(Thread *thread, const char *symbol, arch_debug_contains_call(Thread* thread, const char* symbol, addr_t start,
addr_t start, addr_t end) addr_t end)
{ {
DebuggedThreadSetter threadSetter(thread); DebuggedThreadSetter threadSetter(thread);
addr_t ebp; addr_t bp;
if (thread == thread_get_current_thread()) if (thread == thread_get_current_thread())
ebp = x86_get_stack_frame(); bp = x86_get_stack_frame();
else { else {
if (thread->state == B_THREAD_RUNNING) { if (thread->state == B_THREAD_RUNNING) {
// The thread is currently running on another CPU. // The thread is currently running on another CPU.
@@ -995,38 +1037,38 @@ arch_debug_contains_call(Thread *thread, const char *symbol,
thread->cpu->cpu_num); thread->cpu->cpu_num);
if (registers == NULL) if (registers == NULL)
return false; return false;
ebp = registers->bp; bp = registers->bp;
} else { } else {
// thread not running // thread not running
ebp = thread->arch_info.current_stack.esp[2]; bp = thread->arch_info.GetFramePointer();
} }
} }
for (;;) { for (;;) {
if (!is_kernel_stack_address(thread, ebp)) if (!is_kernel_stack_address(thread, bp))
break; break;
if (is_iframe(thread, ebp)) { if (is_iframe(thread, bp)) {
struct iframe *frame = (struct iframe *)ebp; iframe* frame = (iframe*)bp;
if (is_calling(thread, frame->ip, symbol, start, end)) if (is_calling(thread, frame->ip, symbol, start, end))
return true; return true;
ebp = frame->bp; bp = frame->bp;
} else { } else {
addr_t eip, nextEbp; addr_t ip, nextBp;
if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK if (get_next_frame_no_debugger(bp, &nextBp, &ip) != B_OK
|| eip == 0 || ebp == 0) || ip == 0 || bp == 0)
break; break;
if (is_calling(thread, eip, symbol, start, end)) if (is_calling(thread, ip, symbol, start, end))
return true; return true;
ebp = nextEbp; bp = nextBp;
} }
if (ebp == 0) if (bp == 0)
break; break;
} }
@@ -1034,11 +1076,11 @@ arch_debug_contains_call(Thread *thread, const char *symbol,
} }
void * void*
arch_debug_get_caller(void) arch_debug_get_caller(void)
{ {
struct stack_frame *frame = (struct stack_frame *)x86_get_stack_frame(); stack_frame* frame = (stack_frame*)x86_get_stack_frame();
return (void *)frame->previous->return_address; return (void*)frame->previous->return_address;
} }
@@ -1064,39 +1106,39 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
Thread* thread = thread_get_current_thread(); Thread* thread = thread_get_current_thread();
int32 count = 0; int32 count = 0;
addr_t ebp = x86_get_stack_frame(); addr_t bp = x86_get_stack_frame();
bool onKernelStack = true; bool onKernelStack = true;
while (ebp != 0 && count < maxCount) { while (bp != 0 && count < maxCount) {
onKernelStack = onKernelStack onKernelStack = onKernelStack
&& is_kernel_stack_address(thread, ebp); && is_kernel_stack_address(thread, bp);
if (!onKernelStack && (flags & STACK_TRACE_USER) == 0) if (!onKernelStack && (flags & STACK_TRACE_USER) == 0)
break; break;
addr_t eip; addr_t ip;
addr_t nextEbp; addr_t nextBp;
if (onKernelStack && is_iframe(thread, ebp)) { if (onKernelStack && is_iframe(thread, bp)) {
struct iframe *frame = (struct iframe*)ebp; iframe* frame = (iframe*)bp;
eip = frame->ip; ip = frame->ip;
nextEbp = frame->bp; nextBp = frame->bp;
if (skipIframes > 0) { if (skipIframes > 0) {
if (--skipIframes == 0) if (--skipIframes == 0)
skipFrames = 0; skipFrames = 0;
} }
} else { } else {
if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK) if (get_next_frame_no_debugger(bp, &nextBp, &ip) != B_OK)
break; break;
} }
if (skipFrames <= 0 if (skipFrames <= 0
&& ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) { && ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) {
returnAddresses[count++] = eip; returnAddresses[count++] = ip;
} else } else
skipFrames--; skipFrames--;
ebp = nextEbp; bp = nextBp;
} }
return count; return count;
@@ -1112,12 +1154,12 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount,
void* void*
arch_debug_get_interrupt_pc(bool* _isSyscall) arch_debug_get_interrupt_pc(bool* _isSyscall)
{ {
struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); iframe* frame = get_current_iframe(debug_get_debugged_thread());
if (frame == NULL) if (frame == NULL)
return NULL; return NULL;
if (_isSyscall != NULL) if (_isSyscall != NULL)
*_isSyscall = frame->vector == 99; *_isSyscall = frame->type == IFRAME_TYPE_SYSCALL;
return (void*)(addr_t)frame->ip; return (void*)(addr_t)frame->ip;
} }
@@ -1129,7 +1171,14 @@ arch_debug_get_interrupt_pc(bool* _isSyscall)
void void
arch_debug_unset_current_thread(void) arch_debug_unset_current_thread(void)
{ {
#ifdef __x86_64__
// Can't just write 0 to the GS base, that will cause the read from %gs:0
// to fault. Instead point it at a NULL pointer, %gs:0 will get this value.
static Thread* unsetThread = NULL;
x86_write_msr(IA32_MSR_GS_BASE, (addr_t)&unsetThread);
#else
x86_write_dr3(NULL); x86_write_dr3(NULL);
#endif
} }
@@ -1145,14 +1194,14 @@ status_t
arch_set_debug_variable(const char* variableName, uint64 value) arch_set_debug_variable(const char* variableName, uint64 value)
{ {
bool settable; bool settable;
uint32* variable = find_debug_variable(variableName, settable); size_t* variable = find_debug_variable(variableName, settable);
if (variable == NULL) if (variable == NULL)
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
if (!settable) if (!settable)
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
*variable = (uint32)value; *variable = (size_t)value;
return B_OK; return B_OK;
} }
@@ -1161,7 +1210,7 @@ status_t
arch_get_debug_variable(const char* variableName, uint64* value) arch_get_debug_variable(const char* variableName, uint64* value)
{ {
bool settable; bool settable;
uint32* variable = find_debug_variable(variableName, settable); size_t* variable = find_debug_variable(variableName, settable);
if (variable == NULL) if (variable == NULL)
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
@@ -1170,6 +1219,12 @@ arch_get_debug_variable(const char* variableName, uint64* value)
} }
struct gdb_register {
int32 type;
int64 value;
};
/*! Writes the contents of the CPU registers at some fixed outer stack frame or /*! Writes the contents of the CPU registers at some fixed outer stack frame or
iframe into the given buffer in the format expected by gdb. iframe into the given buffer in the format expected by gdb.
@@ -1183,10 +1238,36 @@ arch_get_debug_variable(const char* variableName, uint64* value)
ssize_t ssize_t
arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
{ {
struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); iframe* frame = get_current_iframe(debug_get_debugged_thread());
if (frame == NULL) if (frame == NULL)
return B_NOT_SUPPORTED; return B_NOT_SUPPORTED;
#ifdef __x86_64__
// For x86_64 the register order is:
//
// rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
// r8, r9, r10, r11, r12, r13, r14, r15,
// rip, rflags, cs, ss, ds, es, fs, gs
//
// Annoyingly, GDB wants all the registers as 64-bit values, but then
// RFLAGS and the segment registers as 32-bit values, hence the need for
// the type information.
static const int32 kRegisterCount = 24;
gdb_register registers[kRegisterCount] = {
{ B_UINT64_TYPE, frame->ax }, { B_UINT64_TYPE, frame->bx },
{ B_UINT64_TYPE, frame->cx }, { B_UINT64_TYPE, frame->dx },
{ B_UINT64_TYPE, frame->si }, { B_UINT64_TYPE, frame->di },
{ B_UINT64_TYPE, frame->bp }, { B_UINT64_TYPE, frame->sp },
{ B_UINT64_TYPE, frame->r8 }, { B_UINT64_TYPE, frame->r9 },
{ B_UINT64_TYPE, frame->r10 }, { B_UINT64_TYPE, frame->r11 },
{ B_UINT64_TYPE, frame->r12 }, { B_UINT64_TYPE, frame->r13 },
{ B_UINT64_TYPE, frame->r14 }, { B_UINT64_TYPE, frame->r15 },
{ B_UINT64_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags },
{ B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ss },
{ B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
{ B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 },
};
#else
// For x86 the register order is: // For x86 the register order is:
// //
// eax, ecx, edx, ebx, // eax, ecx, edx, ebx,
@@ -1195,23 +1276,36 @@ arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
// cs, ss, ds, es, fs, gs // cs, ss, ds, es, fs, gs
// //
// Note that even though the segment descriptors are actually 16 bits wide, // Note that even though the segment descriptors are actually 16 bits wide,
// gdb requires them as 32 bit integers. Note also that for some reason // gdb requires them as 32 bit integers.
// gdb wants the register dump in *big endian* format.
static const int32 kRegisterCount = 16; static const int32 kRegisterCount = 16;
uint32 registers[kRegisterCount] = { gdb_register registers[kRegisterCount] = {
frame->ax, frame->cx, frame->dx, frame->bx, { B_UINT32_TYPE, frame->ax }, { B_UINT32_TYPE, frame->cx },
frame->sp, frame->bp, frame->si, frame->di, { B_UINT32_TYPE, frame->dx }, { B_UINT32_TYPE, frame->bx },
frame->ip, frame->flags, { B_UINT32_TYPE, frame->sp }, { B_UINT32_TYPE, frame->bp },
frame->cs, frame->ds, frame->ds, frame->es, { B_UINT32_TYPE, frame->si }, { B_UINT32_TYPE, frame->di },
{ B_UINT32_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags },
{ B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ds },
// assume ss == ds // assume ss == ds
frame->fs, frame->gs { B_UINT32_TYPE, frame->ds }, { B_UINT32_TYPE, frame->es },
{ B_UINT32_TYPE, frame->fs }, { B_UINT32_TYPE, frame->gs },
}; };
#endif
const char* const bufferStart = buffer; const char* const bufferStart = buffer;
for (int32 i = 0; i < kRegisterCount; i++) { for (int32 i = 0; i < kRegisterCount; i++) {
int result = snprintf(buffer, bufferSize, "%08" B_PRIx32, // For some reason gdb wants the register dump in *big endian* format.
B_HOST_TO_BENDIAN_INT32(registers[i])); int result = 0;
switch (registers[i].type) {
case B_UINT64_TYPE:
result = snprintf(buffer, bufferSize, "%016" B_PRIx64,
B_HOST_TO_BENDIAN_INT64(registers[i].value));
break;
case B_UINT32_TYPE:
result = snprintf(buffer, bufferSize, "%08" B_PRIx32,
B_HOST_TO_BENDIAN_INT32((uint32)registers[i].value));
break;
}
if (result >= (int)bufferSize) if (result >= (int)bufferSize)
return B_BUFFER_OVERFLOW; return B_BUFFER_OVERFLOW;
@@ -1224,7 +1318,7 @@ arch_debug_gdb_get_registers(char* buffer, size_t bufferSize)
status_t status_t
arch_debug_init(kernel_args *args) arch_debug_init(kernel_args* args)
{ {
// at this stage, the debugger command system is alive // at this stage, the debugger command system is alive
@@ -1234,7 +1328,9 @@ arch_debug_init(kernel_args *args)
"Stack crawl for current thread (or any other)"); "Stack crawl for current thread (or any other)");
add_debugger_command("iframe", &dump_iframes, add_debugger_command("iframe", &dump_iframes,
"Dump iframes for the specified thread"); "Dump iframes for the specified thread");
#ifndef __x86_64__
add_debugger_command("call", &show_call, "Show call with arguments"); add_debugger_command("call", &show_call, "Show call with arguments");
#endif
add_debugger_command_etc("in_context", &cmd_in_context, add_debugger_command_etc("in_context", &cmd_in_context,
"Executes a command in the context of a given thread", "Executes a command in the context of a given thread",
"<thread ID> <command> ...\n" "<thread ID> <command> ...\n"
+3 -9
View File
@@ -108,15 +108,9 @@ x86_get_thread_user_iframe(Thread *thread)
if (thread->state == B_THREAD_RUNNING) if (thread->state == B_THREAD_RUNNING)
return NULL; return NULL;
// Read frame pointer from the thread's stack.
#ifdef __x86_64__
addr_t bp = thread->arch_info.current_stack[1];
#else
addr_t bp = thread->arch_info.current_stack.esp[2];
#endif
// find the user iframe // find the user iframe
struct iframe* frame = find_previous_iframe(thread, bp); struct iframe* frame = find_previous_iframe(thread,
thread->arch_info.GetFramePointer());
while (frame != NULL) { while (frame != NULL) {
if (IFRAME_IS_USER(frame)) if (IFRAME_IS_USER(frame))
@@ -136,7 +130,7 @@ x86_get_current_iframe(void)
phys_addr_t phys_addr_t
x86_next_page_directory(Thread *from, Thread *to) x86_next_page_directory(Thread* from, Thread* to)
{ {
VMAddressSpace* toAddressSpace = to->team->address_space; VMAddressSpace* toAddressSpace = to->team->address_space;
if (from->team->address_space == toAddressSpace) { if (from->team->address_space == toAddressSpace) {