aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/core
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2015-03-11 17:59:28 +0100
committerAlex Auvolat <alex@adnab.me>2015-03-11 17:59:28 +0100
commit0b76aff59b586d87ee0449bc7deda878f4633515 (patch)
tree8fd773681e302d84bc1f33c2a2bdf791f0b0df95 /src/kernel/core
parent64b9108a58d3483e9b63511c4cf74b12dceeb0f6 (diff)
downloadkogata-0b76aff59b586d87ee0449bc7deda878f4633515.tar.gz
kogata-0b76aff59b586d87ee0449bc7deda878f4633515.zip
Add better stack tracing technology (now uses kernel memory map!)
Diffstat (limited to 'src/kernel/core')
-rw-r--r--src/kernel/core/idt.c16
-rw-r--r--src/kernel/core/kmain.c6
-rw-r--r--src/kernel/core/kmalloc.c4
-rw-r--r--src/kernel/core/paging.c2
-rw-r--r--src/kernel/core/region.c18
-rw-r--r--src/kernel/core/sys.c58
-rw-r--r--src/kernel/core/thread.c31
7 files changed, 100 insertions, 35 deletions
diff --git a/src/kernel/core/idt.c b/src/kernel/core/idt.c
index d963b4d..457e5ae 100644
--- a/src/kernel/core/idt.c
+++ b/src/kernel/core/idt.c
@@ -91,7 +91,8 @@ static isr_handler_t ex_handlers[32] = {0};
/* Called in interrupt.s when an exception fires (interrupt 0 to 31) */
void idt_ex_handler(registers_t *regs) {
- dbg_printf("ex%d.", regs->int_no);
+ /*dbg_printf("ex%d.", regs->int_no);*/
+
if (ex_handlers[regs->int_no] != 0) {
ex_handlers[regs->int_no](regs);
} else {
@@ -115,7 +116,7 @@ void idt_ex_handler(registers_t *regs) {
void idt_irq_handler(registers_t *regs) {
int st = enter_critical(CL_EXCL); // if someone tries to yield(), an assert will fail
- dbg_printf("irq%d.", regs->err_code);
+ if (regs->err_code != 0) dbg_printf("irq%d.", regs->err_code);
if (regs->err_code > 7) {
outb(0xA0, 0x20);
@@ -278,15 +279,8 @@ void dbg_dump_registers(registers_t *regs) {
dbg_printf("| EIP: 0x%p CS : 0x%p DS : 0x%p SS : 0x%p\n", regs->eip, regs->cs, regs->ds, regs->ss);
dbg_printf("| EFl: 0x%p I# : 0x%p Err: 0x%p\n", regs->eflags, regs->int_no, regs->err_code);
dbg_printf("- Stack trace:\n");
-
- uint32_t ebp = regs->ebp, eip = regs->eip;
- int i = 0;
- while (ebp >= K_HIGHHALF_ADDR && eip >= K_HIGHHALF_ADDR && i++ < 10) {
- dbg_printf("| 0x%p EIP: 0x%p\n", ebp, eip);
- uint32_t *d = (uint32_t*)ebp;
- ebp = d[0];
- eip = d[1];
- }
+
+ kernel_stacktrace(regs->ebp, regs->eip);
dbg_printf("\\\n");
}
diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c
index 005f449..3ee2238 100644
--- a/src/kernel/core/kmain.c
+++ b/src/kernel/core/kmain.c
@@ -248,6 +248,12 @@ fs_t *setup_iofs(multiboot_info_t *mbd) {
ASSERT(nullfs_add_ram_file(iofs, name,
(char*)mods[i].mod_start,
len, FM_READ | FM_MMAP));
+
+ if (strncmp(modname, "kernel.map", 10) == 0) {
+ // remark: load_kernel_symbol_map modifies the data region,
+ // which is not a problem because nullfs_add_ram_file copied the thing already
+ load_kernel_symbol_map((char*)mods[i].mod_start, len);
+ }
}
return iofs;
diff --git a/src/kernel/core/kmalloc.c b/src/kernel/core/kmalloc.c
index cc20487..53ac83c 100644
--- a/src/kernel/core/kmalloc.c
+++ b/src/kernel/core/kmalloc.c
@@ -8,7 +8,7 @@
#include <region.h>
#include <freemem.h>
-static void* page_alloc_fun_for_kmalloc(size_t bytes) {
+void* page_alloc_fun_for_kmalloc(size_t bytes) {
void* addr = region_alloc(bytes, "Core kernel heap");
if (addr == 0) return 0;
@@ -59,7 +59,7 @@ void kmalloc_setup() {
region_free_unmap_free);
}
-static void* malloc0(size_t sz) {
+void* malloc0(size_t sz) {
void* res = 0;
mutex_lock(&malloc_mutex);
diff --git a/src/kernel/core/paging.c b/src/kernel/core/paging.c
index cefb8c3..fa22879 100644
--- a/src/kernel/core/paging.c
+++ b/src/kernel/core/paging.c
@@ -68,7 +68,6 @@ void page_fault_handler(registers_t *regs) {
if ((size_t)vaddr < PAGE_SIZE) {
dbg_printf("Null pointer dereference in kernel code (0x%p)\n", vaddr);
dbg_dump_registers(regs);
- dbg_print_region_info();
PANIC("Null pointer dereference in kernel code.");
} else if ((size_t)vaddr < K_HIGHHALF_ADDR) {
if (pd->user_pfh == 0) {
@@ -110,7 +109,6 @@ void page_fault_handler(registers_t *regs) {
dbg_printf("Kernel pagefault in region with no handler at 0x%p (%s region)\n", vaddr, region);
dbg_dump_registers(regs);
- dbg_print_region_info();
PANIC("Unhandled kernel space page fault");
}
}
diff --git a/src/kernel/core/region.c b/src/kernel/core/region.c
index 1f1958f..c4c34d1 100644
--- a/src/kernel/core/region.c
+++ b/src/kernel/core/region.c
@@ -35,13 +35,13 @@ STATIC_MUTEX(ra_mutex); // region allocator mutex
// HELPER FUNCTIONS FOR THE MANIPULATION OF THE REGION LISTS //
// ========================================================= //
-static void add_unused_descriptor(descriptor_t *d) {
+void add_unused_descriptor(descriptor_t *d) {
n_unused_descriptors++;
d->unused_descriptor.next = first_unused_descriptor;
first_unused_descriptor = d;
}
-static descriptor_t *get_unused_descriptor() {
+descriptor_t *get_unused_descriptor() {
descriptor_t *r = first_unused_descriptor;
if (r != 0) {
first_unused_descriptor = r->unused_descriptor.next;
@@ -50,7 +50,7 @@ static descriptor_t *get_unused_descriptor() {
return r;
}
-static void remove_free_region(descriptor_t *d) {
+void remove_free_region(descriptor_t *d) {
if (first_free_region_by_size == d) {
first_free_region_by_size = d->free.next_by_size;
} else {
@@ -73,7 +73,7 @@ static void remove_free_region(descriptor_t *d) {
}
}
-static void add_free_region(descriptor_t *d) {
+void add_free_region(descriptor_t *d) {
/*dbg_printf("Add free region 0x%p - 0x%p\n", d->free.addr, d->free.size + d->free.addr);*/
// Find position of region in address-ordered list
// Possibly concatenate free region
@@ -155,7 +155,7 @@ static void add_free_region(descriptor_t *d) {
}
}
-static descriptor_t *find_used_region(void* addr) {
+descriptor_t *find_used_region(void* addr) {
for (descriptor_t *i = first_used_region; i != 0; i = i->used.next_by_addr) {
if (addr >= i->used.i.addr && addr < i->used.i.addr + i->used.i.size) return i;
if (i->used.i.addr > addr) break;
@@ -163,7 +163,7 @@ static descriptor_t *find_used_region(void* addr) {
return 0;
}
-static void add_used_region(descriptor_t *d) {
+void add_used_region(descriptor_t *d) {
descriptor_t *i = first_used_region;
ASSERT(i->used.i.addr < d->used.i.addr); // first region by address is never free
@@ -180,7 +180,7 @@ static void add_used_region(descriptor_t *d) {
ASSERT(false);
}
-static void remove_used_region(descriptor_t *d) {
+void remove_used_region(descriptor_t *d) {
if (first_used_region == d) {
first_used_region = d->used.next_by_addr;
} else {
@@ -220,7 +220,7 @@ void region_allocator_init(void* kernel_data_end) {
first_used_region = u0;
}
-static void region_free_inner(void* addr) {
+void region_free_inner(void* addr) {
descriptor_t *d = find_used_region(addr);
if (d == 0) return;
@@ -237,7 +237,7 @@ void region_free(void* addr) {
mutex_unlock(&ra_mutex);
}
-static void* region_alloc_inner(size_t size, char* type, bool use_reserve) {
+void* region_alloc_inner(size_t size, char* type, bool use_reserve) {
size = PAGE_ALIGN_UP(size);
for (descriptor_t *i = first_free_region_by_size; i != 0; i = i->free.first_bigger) {
diff --git a/src/kernel/core/sys.c b/src/kernel/core/sys.c
index 8be6c7f..554c95e 100644
--- a/src/kernel/core/sys.c
+++ b/src/kernel/core/sys.c
@@ -1,6 +1,9 @@
#include <sys.h>
#include <dbglog.h>
#include <thread.h>
+#include <string.h>
+
+#include <btree.h>
// Kernel panic and kernel assert failure
@@ -9,6 +12,15 @@ static void panic_do(const char* type, const char *msg, const char* file, int li
asm volatile("cli;");
dbg_printf("/\n| %s:\t%s\n", type, msg);
dbg_printf("| File: \t%s:%i\n", file, line);
+
+ dbg_printf("- trace\n");
+ dbg_printf("| current thread: 0x%p\n", current_thread);
+ uint32_t *ebp;
+ asm volatile("mov %%ebp, %0":"=r"(ebp));
+ kernel_stacktrace(ebp[0], ebp[1]);
+
+ dbg_print_region_info();
+
dbg_printf("| System halted -_-'\n");
dbg_printf("\\---------------------------------------------------------/");
BOCHS_BREAKPOINT;
@@ -26,4 +38,50 @@ void panic_assert(const char* assertion, const char* file, int line) {
panic_do("ASSERT FAILED", assertion, file, line);
}
+// ---- kernel symbol map
+
+btree_t *kernel_symbol_map = 0;
+
+void load_kernel_symbol_map(char* text, size_t len) {
+ kernel_symbol_map = create_btree(id_key_cmp_fun, 0);
+ ASSERT (kernel_symbol_map != 0);
+
+ dbg_printf("Loading kernel symbol map...\n");
+
+ char* it = text;
+ while (it < text + len) {
+ char* eol = it;
+ while (eol < text + len && *eol != 0 && *eol != '\n') eol++;
+ if (eol >= text + len) break;
+ *eol = 0;
+
+ if (it[16] == '0' && it[17] == 'x' && it[34] == ' ' && it[49] == ' ') {
+ uint32_t addr = 0;
+ for (unsigned i = 18; i < 34; i++) {
+ addr *= 16;
+ if (it[i] >= '0' && it[i] <= '9') addr += it[i] - '0';
+ if (it[i] >= 'a' && it[i] <= 'f') addr += it[i] - 'a' + 10;
+ }
+ btree_add(kernel_symbol_map, (void*)addr, it + 50);
+ }
+
+ it = eol + 1;
+ }
+}
+
+void kernel_stacktrace(uint32_t ebp, uint32_t eip) {
+ int i = 0;
+ while (ebp >= K_HIGHHALF_ADDR && eip >= K_HIGHHALF_ADDR && i++ < 10) {
+ char* sym = 0;
+ if (kernel_symbol_map != 0) sym = btree_lower(kernel_symbol_map, (void*)eip);
+
+ dbg_printf("| 0x%p EIP: 0x%p %s\n", ebp, eip, sym);
+
+ uint32_t *d = (uint32_t*)ebp;
+ ebp = d[0];
+ eip = d[1];
+ }
+}
+
+
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c
index 19ad6c8..1009ec7 100644
--- a/src/kernel/core/thread.c
+++ b/src/kernel/core/thread.c
@@ -120,7 +120,7 @@ void run_scheduler() {
// At this point, interrupts are disabled
// This function is expected NEVER TO RETURN
- thread_t *prev_thread = current_thread;
+ /*thread_t *prev_thread = current_thread;*/
if (current_thread != 0 && current_thread->state == T_STATE_RUNNING) {
current_thread->last_ran = get_kernel_time();
@@ -129,7 +129,7 @@ void run_scheduler() {
}
current_thread = dequeue_thread();
- if (current_thread != prev_thread) dbg_printf("[0x%p]\n", current_thread);
+ /*if (current_thread != prev_thread) dbg_printf("[0x%p]\n", current_thread);*/
if (current_thread != 0) {
thread_t *ptr = current_thread;
@@ -146,7 +146,7 @@ void run_scheduler() {
}
}
-static void run_thread(void (*entry)(void*), void* data) {
+void run_thread(void (*entry)(void*), void* data) {
ASSERT(current_thread->state == T_STATE_RUNNING);
dbg_printf("Begin thread 0x%p (in process %d)\n",
@@ -210,6 +210,10 @@ thread_t *new_thread(entry_t entry, void* data) {
t->next_in_proc = 0;
t->user_ex_handler = 0;
+ t->waiting_on = 0;
+ t->n_waiting_on = 0;
+ t->next_waiter = 0;
+
return t;
}
@@ -285,11 +289,11 @@ bool wait_on_many(void** x, size_t n) {
// ---- Set ourselves as the waiting thread for all the requested objets
- dbg_printf("Wait on many:");
- for (size_t i = 0; i < n; i++) {
- dbg_printf(" 0x%p", x[i]);
- }
- dbg_printf("\n");
+ /*dbg_printf("Wait on many:");*/
+ /*for (size_t i = 0; i < n; i++) {*/
+ /*dbg_printf(" 0x%p", x[i]);*/
+ /*}*/
+ /*dbg_printf("\n");*/
current_thread->waiting_on = x;
current_thread->n_waiting_on = n;
@@ -310,8 +314,12 @@ bool wait_on_many(void** x, size_t n) {
if (waiters == current_thread) {
waiters = current_thread->next_waiter;
} else {
+ ASSERT(waiters != 0);
for (thread_t *w = waiters; w->next_waiter != 0; w = w->next_waiter) {
- if (w->next_waiter == current_thread) w->next_waiter = current_thread->next_waiter;
+ if (w->next_waiter == current_thread) {
+ w->next_waiter = current_thread->next_waiter;
+ break;
+ }
}
}
@@ -368,12 +376,12 @@ bool resume_on(void* x) {
int st = enter_critical(CL_NOINT);
- dbg_printf("Resume on 0x%p:", x);
+ /*dbg_printf("Resume on 0x%p:", x);*/
for (thread_t *t = waiters; t != 0; t = t->next_waiter) {
for (int i = 0; i < t->n_waiting_on; i++) {
if (t->waiting_on[i] == x) {
- dbg_printf(" 0x%p", t);
+ /*dbg_printf(" 0x%p", t);*/
if (t->state == T_STATE_PAUSED) {
t->state = T_STATE_RUNNING;
@@ -386,6 +394,7 @@ bool resume_on(void* x) {
}
}
}
+ /*dbg_printf("\n");*/
exit_critical(st);