The "where" or "sc" command now switches the page directory to the specified thread
to be able to follow the stack trace into userland. No symbols there, yet, though. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14697 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fcd75d6357
commit
7b7c38a2a7
@ -83,13 +83,15 @@ void x86_write_msr(uint32 register, uint64 value);
|
||||
void x86_set_task_gate(int32 n, int32 segment);
|
||||
struct tss *x86_get_main_tss(void);
|
||||
|
||||
|
||||
#define read_ebp(value) \
|
||||
__asm__("movl %%ebp,%0" : "=r" (value))
|
||||
|
||||
#define read_cr3(value) \
|
||||
__asm__("movl %%cr3,%0" : "=r" (value))
|
||||
|
||||
#define write_cr3(value) \
|
||||
__asm__("movl %0,%%cr3" : : "r" (value))
|
||||
|
||||
#define read_dr3(value) \
|
||||
__asm__("movl %%dr3,%0" : "=r" (value))
|
||||
|
||||
|
@ -19,6 +19,7 @@ extern "C" {
|
||||
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 *x86_next_page_directory(struct thread *from, struct thread *to);
|
||||
|
||||
void i386_return_from_signal();
|
||||
void i386_end_return_from_signal();
|
||||
|
@ -74,6 +74,7 @@ stack_trace(int argc, char **argv)
|
||||
uint32 previousLocations[NUM_PREVIOUS_LOCATIONS];
|
||||
struct iframe_stack *frameStack;
|
||||
struct thread *thread;
|
||||
addr_t oldPageDirectory = 0;
|
||||
uint32 ebp;
|
||||
int32 i, num = 0, last = 0;
|
||||
|
||||
@ -90,6 +91,18 @@ stack_trace(int argc, char **argv)
|
||||
|
||||
// read %ebp from the thread's stack stored by a pushad
|
||||
ebp = thread->arch_info.current_stack.esp[2];
|
||||
|
||||
if (id != thread_get_current_thread_id()) {
|
||||
// switch to the page directory of the new thread to be
|
||||
// able to follow the stack trace into userland
|
||||
addr_t newPageDirectory = (addr_t)x86_next_page_directory(
|
||||
thread_get_current_thread(), thread);
|
||||
|
||||
if (newPageDirectory != 0) {
|
||||
read_cr3(oldPageDirectory);
|
||||
write_cr3(newPageDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We don't have a thread pointer early in the boot process
|
||||
@ -185,6 +198,11 @@ stack_trace(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldPageDirectory != 0) {
|
||||
// switch back to the previous page directory to no cause any troubles
|
||||
write_cr3(oldPageDirectory);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,29 @@ i386_get_user_iframe(void)
|
||||
}
|
||||
|
||||
|
||||
inline void *
|
||||
x86_next_page_directory(struct thread *from, struct thread *to)
|
||||
{
|
||||
if (from->team->aspace != NULL && to->team->aspace != NULL) {
|
||||
// they are both uspace threads
|
||||
if (from->team == to->team) {
|
||||
// dont change the pgdir, same address space
|
||||
return NULL;
|
||||
}
|
||||
// switching to a new address space
|
||||
return i386_translation_map_get_pgdir(&to->team->aspace->translation_map);
|
||||
} else if (from->team->aspace == NULL && to->team->aspace == NULL) {
|
||||
// they must both be kspace threads
|
||||
return NULL;
|
||||
} else if (to->team->aspace == NULL) {
|
||||
// the one we're switching to is kspace
|
||||
return i386_translation_map_get_pgdir(&to->team->kaspace->translation_map);
|
||||
}
|
||||
|
||||
return i386_translation_map_get_pgdir(&to->team->aspace->translation_map);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
set_fs_register(uint32 segment)
|
||||
{
|
||||
@ -225,9 +248,9 @@ arch_thread_switch_kstack_and_call(struct thread *t, addr_t new_kstack, void (*f
|
||||
|
||||
|
||||
void
|
||||
arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
|
||||
arch_thread_context_switch(struct thread *from, struct thread *to)
|
||||
{
|
||||
void *new_pgdir;
|
||||
addr_t newPageDirectory;
|
||||
|
||||
#if 0
|
||||
int i;
|
||||
@ -242,42 +265,25 @@ arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
|
||||
for (i = 0; i < 11; i++)
|
||||
dprintf("*esp[%d] (0x%x) = 0x%x\n", i, ((unsigned int *)new_at->esp + i), *((unsigned int *)new_at->esp + i));
|
||||
#endif
|
||||
i386_set_tss_and_kstack(t_to->kernel_stack_base + KERNEL_STACK_SIZE);
|
||||
i386_set_tss_and_kstack(to->kernel_stack_base + KERNEL_STACK_SIZE);
|
||||
|
||||
// set TLS GDT entry to the current thread - since this action is
|
||||
// dependent on the current CPU, we have to do it here
|
||||
if (t_to->user_local_storage != NULL)
|
||||
set_tls_context(t_to);
|
||||
if (to->user_local_storage != NULL)
|
||||
set_tls_context(to);
|
||||
|
||||
if (t_from->team->aspace != NULL && t_to->team->aspace != NULL) {
|
||||
// they are both uspace threads
|
||||
if (t_from->team == t_to->team) {
|
||||
// dont change the pgdir, same address space
|
||||
new_pgdir = NULL;
|
||||
} else {
|
||||
// switching to a new address space
|
||||
new_pgdir = i386_translation_map_get_pgdir(&t_to->team->aspace->translation_map);
|
||||
}
|
||||
} else if (t_from->team->aspace == NULL && t_to->team->aspace == NULL) {
|
||||
// they must both be kspace threads
|
||||
new_pgdir = NULL;
|
||||
} else if (t_to->team->aspace == NULL) {
|
||||
// the one we're switching to is kspace
|
||||
new_pgdir = i386_translation_map_get_pgdir(&t_to->team->kaspace->translation_map);
|
||||
} else {
|
||||
new_pgdir = i386_translation_map_get_pgdir(&t_to->team->aspace->translation_map);
|
||||
}
|
||||
newPageDirectory = (addr_t)x86_next_page_directory(from, to);
|
||||
|
||||
if (((uint32)new_pgdir % B_PAGE_SIZE) != 0)
|
||||
panic("arch_thread_context_switch: bad pgdir 0x%lx\n", new_pgdir);
|
||||
if ((newPageDirectory % B_PAGE_SIZE) != 0)
|
||||
panic("arch_thread_context_switch: bad pgdir 0x%lx\n", newPageDirectory);
|
||||
|
||||
// reinit debugging; necessary, if the thread was preempted after
|
||||
// initializing debugging before returning to userland
|
||||
if (t_to->team->aspace != NULL)
|
||||
i386_reinit_user_debug_after_context_switch(t_to);
|
||||
if (to->team->aspace != NULL)
|
||||
i386_reinit_user_debug_after_context_switch(to);
|
||||
|
||||
i386_fsave_swap(t_from->arch_info.fpu_state, t_to->arch_info.fpu_state);
|
||||
i386_context_switch(&t_from->arch_info, &t_to->arch_info, (addr_t)new_pgdir);
|
||||
i386_fsave_swap(from->arch_info.fpu_state, to->arch_info.fpu_state);
|
||||
i386_context_switch(&from->arch_info, &to->arch_info, newPageDirectory);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user