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:
Axel Dörfler
2005-04-04 14:13:25 +00:00
parent edb5566393
commit 9d06770cdc
5 changed files with 79 additions and 55 deletions
+12 -11
View File
@@ -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];
+35 -23
View File
@@ -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
+8 -2
View File
@@ -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);
}
+12 -11
View File
@@ -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;
}