The iframe stack is now in a special structure iframe_stack.
Introduced a gBootFrameStack that is used until the first thread structure is available - this allows stack crawls and useful register dumps during early startup. Could also be solved differently by making sure there is always a thread structure installed in %dr3 (ie. the boot thread would get a static thread structure instead of a static iframe stack only). This might be a better solution as i386_handle_trap() would no longer need to check for an existing thread structure. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12230 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,22 +1,23 @@
|
||||
/*
|
||||
** Copyright 2002-2004, The Haiku Team. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
**
|
||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
* Copyright 2002-2005, The Haiku Team. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#ifndef _KERNEL_ARCH_x86_THREAD_H
|
||||
#define _KERNEL_ARCH_x86_THREAD_H
|
||||
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
|
||||
void i386_push_iframe(struct thread *t, struct iframe *frame);
|
||||
void i386_pop_iframe(struct thread *t);
|
||||
void x86_push_iframe(struct iframe_stack *stack, struct iframe *frame);
|
||||
void x86_pop_iframe(struct iframe_stack *stack);
|
||||
struct iframe *i386_get_user_iframe(void);
|
||||
|
||||
void i386_return_from_signal();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
** Copyright 2002-2004, The Haiku Team. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
**
|
||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
* Copyright 2002-2005, The Haiku Team. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
#ifndef _KERNEL_ARCH_x86_THREAD_STRUCT_H
|
||||
#define _KERNEL_ARCH_x86_THREAD_STRUCT_H
|
||||
|
||||
@@ -19,14 +19,18 @@ struct farcall {
|
||||
|
||||
#define IFRAME_TRACE_DEPTH 4
|
||||
|
||||
struct iframe_stack {
|
||||
struct iframe *frames[IFRAME_TRACE_DEPTH];
|
||||
int32 index;
|
||||
};
|
||||
|
||||
// architecture specific thread info
|
||||
struct arch_thread {
|
||||
struct farcall current_stack;
|
||||
struct farcall interrupt_stack;
|
||||
|
||||
// used to track interrupts on this thread
|
||||
struct iframe *iframes[IFRAME_TRACE_DEPTH];
|
||||
int iframe_ptr;
|
||||
struct iframe_stack iframes;
|
||||
|
||||
// 512 byte floating point save point
|
||||
uint8 fpu_state[512];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2004, Axel Dörfler, [email protected].
|
||||
* Copyright 2002-2005, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
@@ -11,13 +11,15 @@
|
||||
#include <debug.h>
|
||||
#include <thread.h>
|
||||
#include <elf.h>
|
||||
#include <arch/debug.h>
|
||||
|
||||
#include <arch/debug.h>
|
||||
#include <arch_cpu.h>
|
||||
|
||||
|
||||
#define NUM_PREVIOUS_LOCATIONS 16
|
||||
|
||||
extern struct iframe_stack gBootFrameStack;
|
||||
|
||||
|
||||
static bool
|
||||
already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp)
|
||||
@@ -45,50 +47,60 @@ static int
|
||||
dbg_stack_trace(int argc, char **argv)
|
||||
{
|
||||
uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
|
||||
struct thread *t;
|
||||
struct iframe_stack *frameStack;
|
||||
struct thread *thread;
|
||||
uint32 ebp;
|
||||
int32 i, num = 0, last = 0;
|
||||
|
||||
if (argc < 2)
|
||||
t = thread_get_current_thread();
|
||||
else {
|
||||
if (argc < 2) {
|
||||
thread = thread_get_current_thread();
|
||||
if (thread != NULL)
|
||||
frameStack = &thread->arch_info.iframes;
|
||||
else
|
||||
frameStack = &gBootFrameStack;
|
||||
} else {
|
||||
dprintf("not supported\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < t->arch_info.iframe_ptr; i++) {
|
||||
char *temp = (char *)t->arch_info.iframes[i];
|
||||
dprintf("iframe %p %p %p\n", temp, temp + sizeof(struct iframe), temp + sizeof(struct iframe) - 8);
|
||||
for (i = 0; i < frameStack->index; i++) {
|
||||
dprintf("iframe %p (end = %p)\n",
|
||||
frameStack->frames[i], frameStack->frames[i] + 1);
|
||||
}
|
||||
|
||||
dprintf("stack trace for thread 0x%lx \"%s\"\n", t->id, t->name);
|
||||
// We don't have a thread pointer early in the boot process
|
||||
if (thread != NULL) {
|
||||
dprintf("stack trace for thread 0x%lx \"%s\"\n", thread->id, thread->name);
|
||||
|
||||
dprintf(" kernel stack: %p to %p\n",
|
||||
(void *)t->kernel_stack_base, (void *)(t->kernel_stack_base + KERNEL_STACK_SIZE));
|
||||
if (t->user_stack_base != 0) {
|
||||
dprintf(" user stack: %p to %p\n", (void *)t->user_stack_base,
|
||||
(void *)(t->user_stack_base + t->user_stack_size));
|
||||
dprintf(" kernel stack: %p to %p\n",
|
||||
(void *)thread->kernel_stack_base, (void *)(thread->kernel_stack_base + KERNEL_STACK_SIZE));
|
||||
if (thread->user_stack_base != 0) {
|
||||
dprintf(" user stack: %p to %p\n", (void *)thread->user_stack_base,
|
||||
(void *)(thread->user_stack_base + thread->user_stack_size));
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("frame caller <image>:function + offset\n");
|
||||
|
||||
read_ebp(ebp);
|
||||
for (;;) {
|
||||
bool is_iframe = false;
|
||||
bool isIFrame = false;
|
||||
// see if the ebp matches the iframe
|
||||
for (i = 0; i < t->arch_info.iframe_ptr; i++) {
|
||||
if (ebp == ((uint32)t->arch_info.iframes[i] - 8)) {
|
||||
for (i = 0; i < frameStack->index; i++) {
|
||||
if (ebp == ((uint32)frameStack->frames[i] - 8)) {
|
||||
// it's an iframe
|
||||
is_iframe = true;
|
||||
isIFrame = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_iframe) {
|
||||
if (isIFrame) {
|
||||
struct iframe *frame = (struct iframe *)(ebp + 8);
|
||||
|
||||
dprintf("iframe at %p\n", frame);
|
||||
dprintf(" eax 0x%-9x ebx 0x%-9x ecx 0x%-9x edx 0x%x\n", frame->eax, frame->ebx, frame->ecx, frame->edx);
|
||||
dprintf(" esi 0x%-9x edi 0x%-9x ebp 0x%-9x esp 0x%x\n", frame->esi, frame->edi, frame->ebp, frame->esp);
|
||||
dprintf(" eax 0x%-9x ebx 0x%-9x ecx 0x%-9x edx 0x%x\n",
|
||||
frame->eax, frame->ebx, frame->ecx, frame->edx);
|
||||
dprintf(" esi 0x%-9x edi 0x%-9x ebp 0x%-9x esp 0x%x\n",
|
||||
frame->esi, frame->edi, frame->ebp, frame->esp);
|
||||
dprintf(" eip 0x%-9x eflags 0x%-9x", frame->eip, frame->flags);
|
||||
if ((frame->error_code & 0x4) != 0) {
|
||||
// from user space
|
||||
@@ -136,7 +148,7 @@ dbg_stack_trace(int argc, char **argv)
|
||||
|
||||
|
||||
int
|
||||
arch_dbg_init(kernel_args *ka)
|
||||
arch_dbg_init(kernel_args *args)
|
||||
{
|
||||
// at this stage, the debugger command system is alive
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ typedef struct {
|
||||
} desc_table;
|
||||
static desc_table *idt = NULL;
|
||||
|
||||
struct iframe_stack gBootFrameStack;
|
||||
|
||||
|
||||
static void
|
||||
interrupt_ack(int n)
|
||||
@@ -191,7 +193,9 @@ i386_handle_trap(struct iframe frame)
|
||||
int ret = B_HANDLED_INTERRUPT;
|
||||
|
||||
if (thread)
|
||||
i386_push_iframe(thread, &frame);
|
||||
x86_push_iframe(&thread->arch_info.iframes, &frame);
|
||||
else
|
||||
x86_push_iframe(&gBootFrameStack, &frame);
|
||||
|
||||
if (frame.cs == USER_CODE_SEG) {
|
||||
i386_exit_user_debug_at_kernel_entry();
|
||||
@@ -307,7 +311,9 @@ i386_handle_trap(struct iframe frame)
|
||||
// dprintf("0x%x cpu %d!\n", thread_get_current_thread_id(), smp_get_current_cpu());
|
||||
|
||||
if (thread)
|
||||
i386_pop_iframe(thread);
|
||||
x86_pop_iframe(&thread->arch_info.iframes);
|
||||
else
|
||||
x86_pop_iframe(&gBootFrameStack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -58,18 +58,18 @@ arch_thread_init(struct kernel_args *args)
|
||||
|
||||
|
||||
void
|
||||
i386_push_iframe(struct thread *thread, struct iframe *frame)
|
||||
x86_push_iframe(struct iframe_stack *stack, struct iframe *frame)
|
||||
{
|
||||
ASSERT(thread->arch_info.iframe_ptr < IFRAME_TRACE_DEPTH);
|
||||
thread->arch_info.iframes[thread->arch_info.iframe_ptr++] = frame;
|
||||
ASSERT(stack->index < IFRAME_TRACE_DEPTH);
|
||||
stack->frames[stack->index++] = frame;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
i386_pop_iframe(struct thread *thread)
|
||||
x86_pop_iframe(struct iframe_stack *stack)
|
||||
{
|
||||
ASSERT(thread->arch_info.iframe_ptr > 0);
|
||||
thread->arch_info.iframe_ptr--;
|
||||
ASSERT(stack->index > 0);
|
||||
stack->index--;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,8 +84,8 @@ i386_get_current_iframe(void)
|
||||
{
|
||||
struct thread *thread = thread_get_current_thread();
|
||||
|
||||
ASSERT(thread->arch_info.iframe_ptr >= 0);
|
||||
return thread->arch_info.iframes[thread->arch_info.iframe_ptr - 1];
|
||||
ASSERT(thread->arch_info.iframes.index >= 0);
|
||||
return thread->arch_info.iframes.frames[thread->arch_info.iframes.index - 1];
|
||||
}
|
||||
|
||||
|
||||
@@ -95,15 +95,16 @@ i386_get_current_iframe(void)
|
||||
* \return The iframe, or \c NULL, if there is no such iframe (e.g. when
|
||||
* the thread is a kernel thread).
|
||||
*/
|
||||
|
||||
struct iframe *
|
||||
i386_get_user_iframe(void)
|
||||
{
|
||||
struct thread *thread = thread_get_current_thread();
|
||||
int i;
|
||||
|
||||
for (i = thread->arch_info.iframe_ptr - 1; i >= 0; i--) {
|
||||
struct iframe *frame = thread->arch_info.iframes[i];
|
||||
if (frame->cs == USER_CODE_SEG)
|
||||
for (i = thread->arch_info.iframes.index - 1; i >= 0; i--) {
|
||||
struct iframe *frame = thread->arch_info.iframes.frames[i];
|
||||
if (frame->cs == USER_CODE_SEG)
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user