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:
@@ -1,9 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
#ifndef _NEWOS_KERNEL_ARCH_DEBUG
|
#ifndef _KERNEL_ARCH_DEBUG_H
|
||||||
#define _NEWOS_KERNEL_ARCH_DEBUG
|
#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;
|
unsigned int addr:20;
|
||||||
} pdentry;
|
} 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"::)
|
#define nop() __asm__ ("nop"::)
|
||||||
|
|
||||||
void setup_system_time(unsigned int cv_factor);
|
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_fsave_swap(void *old_fpu_state, void *new_fpu_state);
|
||||||
void i386_fxsave_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) \
|
#define read_dr3(value) \
|
||||||
__asm__("movl %%dr3,%0" : "=r" (value))
|
__asm__("movl %%dr3,%0" : "=r" (value))
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ extern "C" {
|
|||||||
|
|
||||||
#include <arch/cpu.h>
|
#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) {
|
extern inline struct thread *arch_thread_get_current_thread(void) {
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
read_dr3(t);
|
read_dr3(t);
|
||||||
|
|||||||
@@ -10,10 +10,17 @@ struct farcall {
|
|||||||
unsigned int *ss;
|
unsigned int *ss;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define IFRAME_TRACE_DEPTH 4
|
||||||
|
|
||||||
// architecture specific thread info
|
// architecture specific thread info
|
||||||
struct arch_thread {
|
struct arch_thread {
|
||||||
struct farcall current_stack;
|
struct farcall current_stack;
|
||||||
struct farcall interrupt_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
|
// 512 byte floating point save point
|
||||||
uint8 fpu_state[512];
|
uint8 fpu_state[512];
|
||||||
};
|
};
|
||||||
@@ -22,5 +29,4 @@ struct arch_team {
|
|||||||
// nothing here
|
// nothing here
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif /* _KERNEL_ARCH_x86_THREAD_STRUCT_H */
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
image_id elf_load_kspace(const char *path, const char *sym_prepend);
|
||||||
int elf_unload_kspace( const char *path);
|
int elf_unload_kspace( const char *path);
|
||||||
addr elf_lookup_symbol(image_id id, const char *symbol);
|
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);
|
int elf_init(kernel_args *ka);
|
||||||
|
|
||||||
#endif
|
#endif /* _KERNEL_ELF_H */
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,95 @@
|
|||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <arch/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
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <vm.h>
|
#include <vm.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -30,31 +31,11 @@
|
|||||||
|
|
||||||
#define MAX_ARGS 16
|
#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 desc_table *idt = NULL;
|
||||||
|
|
||||||
static void interrupt_ack(int n)
|
|
||||||
|
static void
|
||||||
|
interrupt_ack(int n)
|
||||||
{
|
{
|
||||||
if(n >= 0x20 && n < 0x30) {
|
if(n >= 0x20 && n < 0x30) {
|
||||||
// 8239 controlled interrupt
|
// 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 gate1; // first byte of gate desc
|
||||||
unsigned int gate2; // second 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;
|
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)
|
if (irq < 0 || irq >= 0x10)
|
||||||
return;
|
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 this is a external interrupt via 8239, enable it here */
|
||||||
if (irq < 8)
|
if (irq < 8)
|
||||||
out8(in8(0x21) & ~(1 << irq), 0x21);
|
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);
|
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 */
|
/* never disable slave pic line IRQ 2 */
|
||||||
if (irq < 0 || irq >= 0x10 || 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);
|
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);
|
_set_gate(&idt[n], (unsigned int)addr, 14, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* XXX - currently unused and static...
|
/* 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);
|
_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);
|
_set_gate(&idt[n], (unsigned int)addr, 15, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_int_enable_interrupts(void)
|
|
||||||
|
void
|
||||||
|
arch_int_enable_interrupts(void)
|
||||||
{
|
{
|
||||||
asm("sti");
|
asm("sti");
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_int_disable_interrupts(void)
|
|
||||||
|
int
|
||||||
|
arch_int_disable_interrupts(void)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
@@ -132,7 +130,9 @@ int arch_int_disable_interrupts(void)
|
|||||||
return flags & 0x200 ? 1 : 0;
|
return flags & 0x200 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_int_restore_interrupts(int oldstate)
|
|
||||||
|
void
|
||||||
|
arch_int_restore_interrupts(int oldstate)
|
||||||
{
|
{
|
||||||
int flags = oldstate ? 0x200 : 0;
|
int flags = oldstate ? 0x200 : 0;
|
||||||
|
|
||||||
@@ -146,7 +146,9 @@ void arch_int_restore_interrupts(int oldstate)
|
|||||||
: : "r" (flags), "r" (0));
|
: : "r" (flags), "r" (0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool arch_int_is_interrupts_enabled(void)
|
|
||||||
|
bool
|
||||||
|
arch_int_is_interrupts_enabled(void)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
@@ -155,10 +157,16 @@ bool arch_int_is_interrupts_enabled(void)
|
|||||||
return flags & 0x200 ? 1 : 0;
|
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;
|
int ret = B_HANDLED_INTERRUPT;
|
||||||
|
struct thread *thread = thread_get_current_thread();
|
||||||
|
|
||||||
|
if (thread)
|
||||||
|
i386_push_iframe(thread, &frame);
|
||||||
|
|
||||||
// if(frame.vector != 0x20)
|
// 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());
|
// 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);
|
restore_interrupts(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(frame.cs == USER_CODE_SEG || frame.vector == 99) {
|
if (frame.cs == USER_CODE_SEG || frame.vector == 99) {
|
||||||
thread_atkernel_exit();
|
thread_atkernel_exit();
|
||||||
}
|
}
|
||||||
// dprintf("0x%x cpu %d!\n", thread_get_current_thread_id(), smp_get_current_cpu());
|
// 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;
|
idt = (desc_table *)ka->arch_args.vir_idt;
|
||||||
|
|
||||||
@@ -320,7 +333,9 @@ int arch_int_init(kernel_args *ka)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int arch_int_init2(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
arch_int_init2(kernel_args *ka)
|
||||||
{
|
{
|
||||||
idt = (desc_table *)ka->arch_args.vir_idt;
|
idt = (desc_table *)ka->arch_args.vir_idt;
|
||||||
vm_create_anonymous_region(vm_get_kernel_aspace_id(), "idt", (void *)&idt,
|
vm_create_anonymous_region(vm_get_kernel_aspace_id(), "idt", (void *)&idt,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <stage2.h>
|
#include <stage2.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -12,15 +13,36 @@
|
|||||||
#include <int.h>
|
#include <int.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int arch_team_init_team_struct(struct team *p, bool kernel)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// from arch_interrupts.S
|
// from arch_interrupts.S
|
||||||
extern void i386_stack_init( struct farcall *interrupt_stack_offset );
|
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)
|
// set up an initial state (stack & fpu)
|
||||||
memset(&t->arch_info, 0, sizeof(t->arch_info));
|
memset(&t->arch_info, 0, sizeof(t->arch_info));
|
||||||
@@ -32,7 +54,9 @@ int arch_thread_init_thread_struct(struct thread *t)
|
|||||||
return 0;
|
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 = (unsigned int *)t->kernel_stack_base;
|
||||||
unsigned int kstack_size = KSTACK_SIZE;
|
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;
|
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);
|
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;
|
addr new_pgdir;
|
||||||
#if 0
|
#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);
|
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;
|
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);
|
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",
|
dprintf("arch_thread_entry_uspace: entry 0x%lx, args %p, ustack_top 0x%lx\n",
|
||||||
entry, args, ustack_top);
|
entry, args, ustack_top);
|
||||||
|
|||||||
+53
-19
@@ -4,6 +4,7 @@
|
|||||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
** Distributed under the terms of the NewOS License.
|
** Distributed under the terms of the NewOS License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <arch/int.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))
|
#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;
|
char c;
|
||||||
int ptr = 0;
|
int ptr = 0;
|
||||||
@@ -160,21 +163,23 @@ static int debug_read_line(char *buf, int max_len)
|
|||||||
return ptr;
|
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;
|
int pos = 0;
|
||||||
|
|
||||||
strcpy(parse_line, buf);
|
strcpy(parse_line, buf);
|
||||||
|
|
||||||
if(!isspace(parse_line[0])) {
|
if (!isspace(parse_line[0])) {
|
||||||
argv[0] = parse_line;
|
argv[0] = parse_line;
|
||||||
*argc = 1;
|
*argc = 1;
|
||||||
} else {
|
} else {
|
||||||
*argc = 0;
|
*argc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(parse_line[pos] != '\0') {
|
while (parse_line[pos] != '\0') {
|
||||||
if(isspace(parse_line[pos])) {
|
if (isspace(parse_line[pos])) {
|
||||||
parse_line[pos] = '\0';
|
parse_line[pos] = '\0';
|
||||||
// scan all of the whitespace out of this
|
// scan all of the whitespace out of this
|
||||||
while(isspace(parse_line[++pos]))
|
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;
|
return *argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kernel_debugger_loop()
|
|
||||||
|
static void
|
||||||
|
kernel_debugger_loop()
|
||||||
{
|
{
|
||||||
int argc;
|
int argc;
|
||||||
struct debugger_command *cmd;
|
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]));
|
dbg_save_registers(&(dbg_register_file[smp_get_current_cpu()][0]));
|
||||||
|
|
||||||
@@ -239,7 +248,9 @@ void kernel_debugger(const char * message)
|
|||||||
kernel_debugger_loop();
|
kernel_debugger_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
int panic(const char *fmt, ...)
|
|
||||||
|
int
|
||||||
|
panic(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -270,7 +281,9 @@ int panic(const char *fmt, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dprintf(const char *fmt, ...)
|
|
||||||
|
int
|
||||||
|
dprintf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
char temp[512];
|
char temp[512];
|
||||||
@@ -286,7 +299,9 @@ int dprintf(const char *fmt, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char dbg_putch(char c)
|
|
||||||
|
char
|
||||||
|
dbg_putch(char c)
|
||||||
{
|
{
|
||||||
char ret;
|
char ret;
|
||||||
int flags = disable_interrupts();
|
int flags = disable_interrupts();
|
||||||
@@ -303,7 +318,9 @@ char dbg_putch(char c)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dbg_puts(const char *s)
|
|
||||||
|
void
|
||||||
|
dbg_puts(const char *s)
|
||||||
{
|
{
|
||||||
int flags = disable_interrupts();
|
int flags = disable_interrupts();
|
||||||
acquire_spinlock(&dbg_spinlock);
|
acquire_spinlock(&dbg_spinlock);
|
||||||
@@ -315,7 +332,9 @@ void dbg_puts(const char *s)
|
|||||||
restore_interrupts(flags);
|
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;
|
int flags;
|
||||||
struct debugger_command *cmd;
|
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;
|
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;
|
int flags;
|
||||||
struct debugger_command *cmd;
|
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();
|
reboot();
|
||||||
return 0; // I'll be really suprised if this line ever run! ;-)
|
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;
|
struct debugger_command *cmd;
|
||||||
|
|
||||||
@@ -398,30 +422,40 @@ static int cmd_help(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dbg_init(kernel_args *ka)
|
|
||||||
|
int
|
||||||
|
dbg_init(kernel_args *ka)
|
||||||
{
|
{
|
||||||
commands = NULL;
|
commands = NULL;
|
||||||
|
|
||||||
return arch_dbg_con_init(ka);
|
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("help", &cmd_help, "List all debugger commands");
|
||||||
add_debugger_command("reboot", &cmd_reboot, "Reboot");
|
add_debugger_command("reboot", &cmd_reboot, "Reboot");
|
||||||
add_debugger_command("gdb", &cmd_gdb, "Connect to remote gdb");
|
add_debugger_command("gdb", &cmd_gdb, "Connect to remote gdb");
|
||||||
|
|
||||||
|
dbg_init(ka);
|
||||||
|
|
||||||
return B_NO_ERROR;
|
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;
|
int temp = serial_debug_on;
|
||||||
serial_debug_on = new_val;
|
serial_debug_on = new_val;
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dbg_get_serial_debug()
|
|
||||||
|
bool
|
||||||
|
dbg_get_serial_debug()
|
||||||
{
|
{
|
||||||
return serial_debug_on;
|
return serial_debug_on;
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-13
@@ -84,8 +84,8 @@ static image_id next_image_id = 0;
|
|||||||
#define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)])
|
#define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)])
|
||||||
|
|
||||||
|
|
||||||
static int
|
int
|
||||||
get_address_symbol_info(addr address, char *text, int maxtextlen)
|
elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t length)
|
||||||
{
|
{
|
||||||
struct elf_image_info **ptr;
|
struct elf_image_info **ptr;
|
||||||
struct elf_image_info *image;
|
struct elf_image_info *image;
|
||||||
@@ -102,7 +102,8 @@ get_address_symbol_info(addr address, char *text, int maxtextlen)
|
|||||||
found_sym = 0;
|
found_sym = 0;
|
||||||
found_image = 0;
|
found_image = 0;
|
||||||
found_delta = 0x7fffffff;
|
found_delta = 0x7fffffff;
|
||||||
for(ptr = &kernel_images; *ptr; ptr = &(*ptr)->next) {
|
|
||||||
|
for (ptr = &kernel_images; *ptr; ptr = &(*ptr)->next) {
|
||||||
image = *ptr;
|
image = *ptr;
|
||||||
|
|
||||||
PRINT((" image %p, base = %p, size = %p\n", image, (void *)image->regions[0].start, (void *)image->regions[0].size));
|
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"));
|
PRINT((" searching...\n"));
|
||||||
found_image = image;
|
found_image = image;
|
||||||
for (i = 0; i < HASHTABSIZE(image); i++) {
|
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;
|
long d;
|
||||||
sym = &image->syms[j];
|
sym = &image->syms[j];
|
||||||
|
|
||||||
@@ -131,17 +132,22 @@ get_address_symbol_info(addr address, char *text, int maxtextlen)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (found_sym == 0) {
|
|
||||||
PRINT(("symbol not found!\n"));
|
if (found_sym != 0) {
|
||||||
strlcpy(text, "symbol not found", maxtextlen);
|
|
||||||
rv = -1;
|
|
||||||
} else {
|
|
||||||
PRINT(("symbol at %p, in image %p, name = %s\n", found_sym, found_image, found_image->name));
|
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(("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));
|
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;
|
rv = 0;
|
||||||
|
} else {
|
||||||
|
PRINT(("symbol not found!\n"));
|
||||||
|
strlcpy(text, "symbol not found", length);
|
||||||
|
rv = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&image_lock);
|
mutex_unlock(&image_lock);
|
||||||
@@ -161,8 +167,8 @@ print_address_info(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
address = atoul(argv[1]);
|
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);
|
dprintf("%p = %s\n",(void *)address,text);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user