Backported the new stack crawl command ("sc", not "bt" like in NewOS) from

NewOS. Untested yet, though.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@750 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-08-13 21:42:53 +00:00
parent ef8d7092e8
commit 5ca8da7a4b
10 changed files with 301 additions and 90 deletions
+5 -4
View File
@@ -1,9 +1,10 @@
/*
/*
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#ifndef _NEWOS_KERNEL_ARCH_DEBUG
#define _NEWOS_KERNEL_ARCH_DEBUG
#ifndef _KERNEL_ARCH_DEBUG_H
#define _KERNEL_ARCH_DEBUG_H
#endif
int arch_dbg_init(kernel_args *ka);
#endif /* _KERNEL_ARCH_DEBUG_H */
@@ -82,6 +82,28 @@ typedef struct pdentry {
unsigned int addr:20;
} pdentry;
struct iframe {
unsigned int gs;
unsigned int fs;
unsigned int es;
unsigned int ds;
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int esp;
unsigned int ebx;
unsigned int edx;
unsigned int ecx;
unsigned int eax;
unsigned int vector;
unsigned int error_code;
unsigned int eip;
unsigned int cs;
unsigned int flags;
unsigned int user_esp;
unsigned int user_ss;
};
#define nop() __asm__ ("nop"::)
void setup_system_time(unsigned int cv_factor);
@@ -93,6 +115,9 @@ void i386_swap_pgdir(addr new_pgdir);
void i386_fsave_swap(void *old_fpu_state, void *new_fpu_state);
void i386_fxsave_swap(void *old_fpu_state, void *new_fpu_state);
#define read_ebp(value) \
__asm__("movl %%ebp,%0" : "=r" (value))
#define read_dr3(value) \
__asm__("movl %%dr3,%0" : "=r" (value))
@@ -11,6 +11,11 @@ extern "C" {
#include <arch/cpu.h>
void i386_push_iframe(struct thread *t, struct iframe *frame);
void i386_pop_iframe(struct thread *t);
extern inline struct thread *arch_thread_get_current_thread(void) {
struct thread *t;
read_dr3(t);
@@ -10,10 +10,17 @@ struct farcall {
unsigned int *ss;
};
#define IFRAME_TRACE_DEPTH 4
// 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;
// 512 byte floating point save point
uint8 fpu_state[512];
};
@@ -22,5 +29,4 @@ struct arch_team {
// nothing here
};
#endif
#endif /* _KERNEL_ARCH_x86_THREAD_STRUCT_H */
+2 -2
View File
@@ -11,7 +11,7 @@ int elf_load_uspace(const char *path, struct team *t, int flags, addr *entry);
image_id elf_load_kspace(const char *path, const char *sym_prepend);
int elf_unload_kspace( const char *path);
addr elf_lookup_symbol(image_id id, const char *symbol);
int elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t length);
int elf_init(kernel_args *ka);
#endif
#endif /* _KERNEL_ELF_H */
+88 -1
View File
@@ -2,8 +2,95 @@
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel.h>
#include <debug.h>
#include <arch/debug.h>
#include <Errors.h>
#include <kernel.h>
#include <thread.h>
#include <debug.h>
#include <elf.h>
#include <arch/debug.h>
#include <arch/x86/arch_cpu.h>
static int
dbg_stack_trace(int argc, char **argv)
{
struct thread *t;
uint32 ebp;
int i;
if (argc < 2)
t = thread_get_current_thread();
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);
}
dprintf("stack trace for thread 0x%x '%s'\n", t->id, t->name);
dprintf("frame \tcaller:<base function+offset>\n");
dprintf("-------------------------------\n");
read_ebp(ebp);
for (;;) {
bool is_iframe = 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)) {
// it's an iframe
is_iframe = true;
}
}
if (is_iframe) {
struct iframe *frame = (struct iframe *)(ebp + 8);
dprintf("iframe at %p\n", frame);
dprintf(" eax\t0x%x\tebx\t0x%x\tecx\t0x%x\tedx\t0x%x\n", frame->eax, frame->ebx, frame->ecx, frame->edx);
dprintf(" esi\t0x%x\tedi\t0x%x\tebp\t0x%x\tesp\t0x%x\n", frame->esi, frame->edi, frame->ebp, frame->esp);
dprintf(" eip\t0x%x\teflags\t0x%x", frame->eip, frame->flags);
if ((frame->error_code & 0x4) != 0) {
// from user space
dprintf("\tuser esp\t0x%x", frame->user_esp);
}
dprintf("\n");
dprintf(" vector\t0x%x\terror code\t0x%x\n", frame->vector, frame->error_code);
ebp = frame->ebp;
} else {
uint32 eip = *((uint32 *)ebp + 1);
char symname[256];
addr base_address;
if (eip == 0 || ebp == 0)
break;
if (elf_lookup_symbol_address(eip, &base_address, symname, sizeof(symname)) >= 0)
dprintf("%p\t%p:<%p+%p>\t'%s'\n", (void *)ebp, (void *)eip, (void *)base_address, (void *)(eip - base_address), symname);
else
dprintf("%p\t%p\n", (void *)ebp, (void *)eip);
ebp = *(uint32 *)ebp;
}
}
return 0;
}
int
arch_dbg_init(kernel_args *ka)
{
// at this stage, the debugger command system is alive
add_debugger_command("sc", &dbg_stack_trace, "Stack crawl for current thread");
return B_NO_ERROR;
}
// XXX will put stack trace and disassembly routines here
+54 -39
View File
@@ -2,6 +2,7 @@
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel.h>
#include <vm.h>
#include <debug.h>
@@ -30,31 +31,11 @@
#define MAX_ARGS 16
struct int_frame {
unsigned int gs;
unsigned int fs;
unsigned int es;
unsigned int ds;
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int esp;
unsigned int ebx;
unsigned int edx;
unsigned int ecx;
unsigned int eax;
unsigned int vector;
unsigned int error_code;
unsigned int eip;
unsigned int cs;
unsigned int flags;
unsigned int user_esp;
unsigned int user_ss;
};
static desc_table *idt = NULL;
static void interrupt_ack(int n)
static void
interrupt_ack(int n)
{
if(n >= 0x20 && n < 0x30) {
// 8239 controlled interrupt
@@ -64,7 +45,9 @@ static void interrupt_ack(int n)
}
}
static void _set_gate(desc_table *gate_addr, unsigned int addr, int type, int dpl)
static void
_set_gate(desc_table *gate_addr, unsigned int addr, int type, int dpl)
{
unsigned int gate1; // first byte of gate desc
unsigned int gate2; // second byte of gate desc
@@ -76,11 +59,14 @@ static void _set_gate(desc_table *gate_addr, unsigned int addr, int type, int dp
gate_addr->b = gate2;
}
void arch_int_enable_io_interrupt(int irq)
void
arch_int_enable_io_interrupt(int irq)
{
if (irq < 0 || irq >= 0x10)
return;
dprintf("arch_int_enable_io_interrupt: irq %d\n", irq);
dprintf("arch_int_enable_io_interrupt: irq %d\n", irq);
/* if this is a external interrupt via 8239, enable it here */
if (irq < 8)
out8(in8(0x21) & ~(1 << irq), 0x21);
@@ -88,7 +74,9 @@ dprintf("arch_int_enable_io_interrupt: irq %d\n", irq);
out8(in8(0xa1) & ~(1 << (irq - 8)), 0xa1);
}
void arch_int_disable_io_interrupt(int irq)
void
arch_int_disable_io_interrupt(int irq)
{
/* never disable slave pic line IRQ 2 */
if (irq < 0 || irq >= 0x10 || irq == 2)
@@ -100,29 +88,39 @@ void arch_int_disable_io_interrupt(int irq)
out8(in8(0xa1) | (1 << (irq - 8)), 0xa1);
}
static void set_intr_gate(int n, void *addr)
static void
set_intr_gate(int n, void *addr)
{
_set_gate(&idt[n], (unsigned int)addr, 14, 0);
}
/* XXX - currently unused and static...
static void set_trap_gate(int n, void *addr)
static void
set_trap_gate(int n, void *addr)
{
_set_gate(&idt[n], (unsigned int)addr, 15, 0);
}
*/
static void set_system_gate(int n, void *addr)
static void
set_system_gate(int n, void *addr)
{
_set_gate(&idt[n], (unsigned int)addr, 15, 3);
}
void arch_int_enable_interrupts(void)
void
arch_int_enable_interrupts(void)
{
asm("sti");
}
int arch_int_disable_interrupts(void)
int
arch_int_disable_interrupts(void)
{
int flags;
@@ -132,7 +130,9 @@ int arch_int_disable_interrupts(void)
return flags & 0x200 ? 1 : 0;
}
void arch_int_restore_interrupts(int oldstate)
void
arch_int_restore_interrupts(int oldstate)
{
int flags = oldstate ? 0x200 : 0;
@@ -146,7 +146,9 @@ void arch_int_restore_interrupts(int oldstate)
: : "r" (flags), "r" (0));
}
bool arch_int_is_interrupts_enabled(void)
bool
arch_int_is_interrupts_enabled(void)
{
int flags;
@@ -155,10 +157,16 @@ bool arch_int_is_interrupts_enabled(void)
return flags & 0x200 ? 1 : 0;
}
void i386_handle_trap(struct int_frame frame); /* keep the compiler happy, this function must be called only from assembly */
void i386_handle_trap(struct int_frame frame)
void i386_handle_trap(struct iframe frame); /* keep the compiler happy, this function must be called only from assembly */
void
i386_handle_trap(struct iframe frame)
{
int ret = B_HANDLED_INTERRUPT;
struct thread *thread = thread_get_current_thread();
if (thread)
i386_push_iframe(thread, &frame);
// if(frame.vector != 0x20)
// dprintf("i386_handle_trap: vector 0x%x, ip 0x%x, cpu %d\n", frame.vector, frame.eip, smp_get_current_cpu());
@@ -250,13 +258,18 @@ void i386_handle_trap(struct int_frame frame)
restore_interrupts(state);
}
if(frame.cs == USER_CODE_SEG || frame.vector == 99) {
if (frame.cs == USER_CODE_SEG || frame.vector == 99) {
thread_atkernel_exit();
}
// dprintf("0x%x cpu %d!\n", thread_get_current_thread_id(), smp_get_current_cpu());
if (thread)
i386_pop_iframe(thread);
}
int arch_int_init(kernel_args *ka)
int
arch_int_init(kernel_args *ka)
{
idt = (desc_table *)ka->arch_args.vir_idt;
@@ -320,7 +333,9 @@ int arch_int_init(kernel_args *ka)
return 0;
}
int arch_int_init2(kernel_args *ka)
int
arch_int_init2(kernel_args *ka)
{
idt = (desc_table *)ka->arch_args.vir_idt;
vm_create_anonymous_region(vm_get_kernel_aspace_id(), "idt", (void *)&idt,
+42 -10
View File
@@ -2,6 +2,7 @@
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel.h>
#include <stage2.h>
#include <debug.h>
@@ -12,15 +13,36 @@
#include <int.h>
#include <string.h>
int arch_team_init_team_struct(struct team *p, bool kernel)
{
return 0;
}
// from arch_interrupts.S
extern void i386_stack_init( struct farcall *interrupt_stack_offset );
int arch_thread_init_thread_struct(struct thread *t)
void
i386_push_iframe(struct thread *thread, struct iframe *frame)
{
ASSERT(thread->arch_info.iframe_ptr < IFRAME_TRACE_DEPTH);
thread->arch_info.iframes[thread->arch_info.iframe_ptr++] = frame;
}
void
i386_pop_iframe(struct thread *thread)
{
ASSERT(thread->arch_info.iframe_ptr > 0);
thread->arch_info.iframe_ptr--;
}
int
arch_team_init_team_struct(struct team *p, bool kernel)
{
return 0;
}
int
arch_thread_init_thread_struct(struct thread *t)
{
// set up an initial state (stack & fpu)
memset(&t->arch_info, 0, sizeof(t->arch_info));
@@ -32,7 +54,9 @@ int arch_thread_init_thread_struct(struct thread *t)
return 0;
}
int arch_thread_initialize_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void))
int
arch_thread_initialize_kthread_stack(struct thread *t, int (*start_func)(void), void (*entry_func)(void), void (*exit_func)(void))
{
unsigned int *kstack = (unsigned int *)t->kernel_stack_base;
unsigned int kstack_size = KSTACK_SIZE;
@@ -74,12 +98,16 @@ int arch_thread_initialize_kthread_stack(struct thread *t, int (*start_func)(voi
return 0;
}
void arch_thread_switch_kstack_and_call(struct thread *t, addr new_kstack, void (*func)(void *), void *arg)
void
arch_thread_switch_kstack_and_call(struct thread *t, addr new_kstack, void (*func)(void *), void *arg)
{
i386_switch_stack_and_call(new_kstack, func, arg);
}
void arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
void
arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
{
addr new_pgdir;
#if 0
@@ -138,7 +166,9 @@ void arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
i386_context_switch(&t_from->arch_info, &t_to->arch_info, new_pgdir);
}
void arch_thread_dump_info(void *info)
void
arch_thread_dump_info(void *info)
{
struct arch_thread *at = (struct arch_thread *)info;
@@ -147,7 +177,9 @@ void arch_thread_dump_info(void *info)
dprintf("\tfpu_state at %p\n", at->fpu_state);
}
void arch_thread_enter_uspace(addr entry, void *args, addr ustack_top)
void
arch_thread_enter_uspace(addr entry, void *args, addr ustack_top)
{
dprintf("arch_thread_entry_uspace: entry 0x%lx, args %p, ustack_top 0x%lx\n",
entry, args, ustack_top);
+53 -19
View File
@@ -4,6 +4,7 @@
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <kernel.h>
#include <debug.h>
#include <arch/int.h>
@@ -52,7 +53,9 @@ static char *args[MAX_ARGS] = { NULL, };
#define distance(a, b) ((a) < (b) ? (b) - (a) : (a) - (b))
static int debug_read_line(char *buf, int max_len)
static int
debug_read_line(char *buf, int max_len)
{
char c;
int ptr = 0;
@@ -160,21 +163,23 @@ static int debug_read_line(char *buf, int max_len)
return ptr;
}
static int debug_parse_line(char *buf, char **argv, int *argc, int max_args)
static int
debug_parse_line(char *buf, char **argv, int *argc, int max_args)
{
int pos = 0;
strcpy(parse_line, buf);
if(!isspace(parse_line[0])) {
if (!isspace(parse_line[0])) {
argv[0] = parse_line;
*argc = 1;
} else {
*argc = 0;
}
while(parse_line[pos] != '\0') {
if(isspace(parse_line[pos])) {
while (parse_line[pos] != '\0') {
if (isspace(parse_line[pos])) {
parse_line[pos] = '\0';
// scan all of the whitespace out of this
while(isspace(parse_line[++pos]))
@@ -193,7 +198,9 @@ static int debug_parse_line(char *buf, char **argv, int *argc, int max_args)
return *argc;
}
static void kernel_debugger_loop()
static void
kernel_debugger_loop()
{
int argc;
struct debugger_command *cmd;
@@ -226,7 +233,9 @@ static void kernel_debugger_loop()
}
}
void kernel_debugger(const char * message)
void
kernel_debugger(const char * message)
{
dbg_save_registers(&(dbg_register_file[smp_get_current_cpu()][0]));
@@ -239,7 +248,9 @@ void kernel_debugger(const char * message)
kernel_debugger_loop();
}
int panic(const char *fmt, ...)
int
panic(const char *fmt, ...)
{
int ret = 0;
va_list args;
@@ -270,7 +281,9 @@ int panic(const char *fmt, ...)
return ret;
}
int dprintf(const char *fmt, ...)
int
dprintf(const char *fmt, ...)
{
va_list args;
char temp[512];
@@ -286,7 +299,9 @@ int dprintf(const char *fmt, ...)
return ret;
}
char dbg_putch(char c)
char
dbg_putch(char c)
{
char ret;
int flags = disable_interrupts();
@@ -303,7 +318,9 @@ char dbg_putch(char c)
return ret;
}
void dbg_puts(const char *s)
void
dbg_puts(const char *s)
{
int flags = disable_interrupts();
acquire_spinlock(&dbg_spinlock);
@@ -315,7 +332,9 @@ void dbg_puts(const char *s)
restore_interrupts(flags);
}
int add_debugger_command(const char * name, int (*func)(int, char **), const char * desc)
int
add_debugger_command(const char * name, int (*func)(int, char **), const char * desc)
{
int flags;
struct debugger_command *cmd;
@@ -340,7 +359,9 @@ int add_debugger_command(const char * name, int (*func)(int, char **), const cha
return B_NO_ERROR;
}
int remove_debugger_command(const char * name, int (*func)(int, char **))
int
remove_debugger_command(const char * name, int (*func)(int, char **))
{
int flags;
struct debugger_command *cmd;
@@ -378,13 +399,16 @@ int remove_debugger_command(const char * name, int (*func)(int, char **))
}
static int cmd_reboot(int argc, char **argv)
static int
cmd_reboot(int argc, char **argv)
{
reboot();
return 0; // I'll be really suprised if this line ever run! ;-)
}
static int cmd_help(int argc, char **argv)
static int
cmd_help(int argc, char **argv)
{
struct debugger_command *cmd;
@@ -398,30 +422,40 @@ static int cmd_help(int argc, char **argv)
return 0;
}
int dbg_init(kernel_args *ka)
int
dbg_init(kernel_args *ka)
{
commands = NULL;
return arch_dbg_con_init(ka);
}
int dbg_init2(kernel_args *ka)
int
dbg_init2(kernel_args *ka)
{
add_debugger_command("help", &cmd_help, "List all debugger commands");
add_debugger_command("reboot", &cmd_reboot, "Reboot");
add_debugger_command("gdb", &cmd_gdb, "Connect to remote gdb");
dbg_init(ka);
return B_NO_ERROR;
}
bool dbg_set_serial_debug(bool new_val)
bool
dbg_set_serial_debug(bool new_val)
{
int temp = serial_debug_on;
serial_debug_on = new_val;
return temp;
}
bool dbg_get_serial_debug()
bool
dbg_get_serial_debug()
{
return serial_debug_on;
}
+19 -13
View File
@@ -84,8 +84,8 @@ static image_id next_image_id = 0;
#define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)])
static int
get_address_symbol_info(addr address, char *text, int maxtextlen)
int
elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t length)
{
struct elf_image_info **ptr;
struct elf_image_info *image;
@@ -102,7 +102,8 @@ get_address_symbol_info(addr address, char *text, int maxtextlen)
found_sym = 0;
found_image = 0;
found_delta = 0x7fffffff;
for(ptr = &kernel_images; *ptr; ptr = &(*ptr)->next) {
for (ptr = &kernel_images; *ptr; ptr = &(*ptr)->next) {
image = *ptr;
PRINT((" image %p, base = %p, size = %p\n", image, (void *)image->regions[0].start, (void *)image->regions[0].size));
@@ -112,7 +113,7 @@ get_address_symbol_info(addr address, char *text, int maxtextlen)
PRINT((" searching...\n"));
found_image = image;
for (i = 0; i < HASHTABSIZE(image); i++) {
for(j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
long d;
sym = &image->syms[j];
@@ -131,17 +132,22 @@ get_address_symbol_info(addr address, char *text, int maxtextlen)
}
break;
}
if (found_sym == 0) {
PRINT(("symbol not found!\n"));
strlcpy(text, "symbol not found", maxtextlen);
rv = -1;
} else {
if (found_sym != 0) {
PRINT(("symbol at %p, in image %p, name = %s\n", found_sym, found_image, found_image->name));
PRINT(("name index %d, '%s'\n", found_sym->st_name, SYMNAME(found_image, found_sym)));
PRINT(("addr = %#lx, offset = %#lx\n",(found_sym->st_value + found_image->regions[0].delta),found_delta));
// XXX should honor maxtextlen here
sprintf(text, "<%#lx:%s + %#lx> %s", (found_sym->st_value + found_image->regions[0].delta), SYMNAME(found_image, found_sym), found_delta, found_image->name);
strlcpy(text, SYMNAME(found_image, found_sym), length);
if (baseAddress)
*baseAddress = found_sym->st_value + found_image->regions[0].delta;
rv = 0;
} else {
PRINT(("symbol not found!\n"));
strlcpy(text, "symbol not found", length);
rv = -1;
}
mutex_unlock(&image_lock);
@@ -161,8 +167,8 @@ print_address_info(int argc, char **argv)
}
address = atoul(argv[1]);
get_address_symbol_info(address, text, sizeof(text));
elf_lookup_symbol_address(address, NULL, text, sizeof(text));
dprintf("%p = %s\n",(void *)address,text);
return 0;
}