Detect segfaults in modules and print information

This commit is contained in:
Kevin Lange 2014-03-16 14:39:39 -07:00
parent 711285f2b6
commit cc0c32f278
6 changed files with 90 additions and 37 deletions

View File

@ -14,9 +14,10 @@ typedef struct {
module_defs * mod_info;
void * bin_data;
hashmap_t * symbols;
uintptr_t end;
} module_data_t;
extern void * module_load_direct(void * blob);
extern void * module_load_direct(void * blob, size_t size);
extern void * module_load(char * filename);
extern void module_unload(char * name);
extern void modules_install(void);

View File

@ -143,8 +143,10 @@ int kmain(struct multiboot *mboot, uint32_t mboot_mag, uintptr_t esp) {
for (unsigned int i = 0; i < mboot_ptr->mods_count; ++i ) {
mboot_mod_t * mod = &mboot_mods[i];
uint32_t module_start = mod->mod_start;
uint32_t module_end = mod->mod_end;
size_t module_size = module_end - module_end;
debug_print(NOTICE, "Loading a module: 0x%x:0x%x", module_start);
module_defs * mod_info = (module_defs *)module_load_direct((void *)(module_start));
module_defs * mod_info = (module_defs *)module_load_direct((void *)(module_start), module_size);
debug_print(NOTICE, "Loaded: %s", mod_info->name);
}

View File

@ -341,35 +341,56 @@ page_fault(
int reserved = r->err_code & 0x8 ? 1 : 0;
int id = r->err_code & 0x10 ? 1 : 0;
/* find closest symbol */
typedef struct {
uintptr_t addr;
char name[];
} kernel_symbol_t;
kernel_symbol_t * closest = NULL;
size_t distance = 0xFFFFFFFF;
list_t * hash_keys = hashmap_keys(modules_get_symbols());
foreach(_key, hash_keys) {
char * key = (char *)_key->value;
kernel_symbol_t * k = hashmap_get(modules_get_symbols(), key);
if (!k->addr) continue;
if ((uintptr_t)k->addr <= r->eip) {
size_t d = r->eip - k->addr;
if (d < distance) {
kprintf("%s is closer [d=%d]", key, d);
closest = k;
distance = d;
}
}
}
kprintf("\033[1;37;41mSegmentation fault. (p:%d,rw:%d,user:%d,res:%d,id:%d) at 0x%x eip:0x%x pid=%d,%d [%s]\033[0m\n",
present, rw, user, reserved, id, faulting_address, r->eip, current_process->id, current_process->group, current_process->name);
kprintf("\033[1;31mLast symbol before faulting address: %s [0x%x]\n", &closest->name, closest->addr);
if (r->eip < heap_end) {
/* find closest symbol */
typedef struct {
uintptr_t addr;
char name[];
} kernel_symbol_t;
char * closest = NULL;
size_t distance = 0xFFFFFFFF;
uintptr_t addr = 0;
list_t * hash_keys = hashmap_keys(modules_get_symbols());
foreach(_key, hash_keys) {
char * key = (char *)_key->value;
uintptr_t a = (uintptr_t)hashmap_get(modules_get_symbols(), key);
if (!a) continue;
size_t d;
if (a <= r->eip) {
d = r->eip - a;
} else {
d = a - r->eip;
}
if (d < distance) {
closest = key;
distance = d;
addr = a;
}
}
kprintf("\033[1;31mClosest symbol to faulting address:\033[0m %s [0x%x]\n", closest, addr);
hash_keys = hashmap_keys(modules_get_list());
foreach(_key, hash_keys) {
char * key = (char *)_key->value;
module_data_t * m = (module_data_t *)hashmap_get(modules_get_list(), key);
if ((r->eip >= (uintptr_t)m->bin_data) && (r->eip < m->end)) {
kprintf("\033[1;31mIn module:\033[0m %s (starts at 0x%x)\n", m->mod_info->name, m->bin_data);
break;
}
}
} else {
kprintf("\033[1;31m(In userspace)\033[0m\n");
}
#endif

View File

@ -20,7 +20,7 @@ extern char kernel_symbols_start[];
extern char kernel_symbols_end[];
void * module_load_direct(void * blob) {
void * module_load_direct(void * blob, size_t length) {
Elf32_Header * target = (Elf32_Header *)blob;
if (target->e_ident[0] != ELFMAG0 ||
@ -199,12 +199,21 @@ void * module_load_direct(void * blob) {
debug_print(NOTICE, "Finished loading module %s", mod_info->name);
hashmap_set(modules, mod_info->name, (void *)mod_info);
/* We don't do this anymore
* TODO: Do this in the module unload function
hashmap_free(local_symbols);
free(local_symbols);
*/
return mod_info;
module_data_t * mod_data = malloc(sizeof(module_data_t));
mod_data->mod_info = mod_info;
mod_data->bin_data = target;
mod_data->symbols = local_symbols;
mod_data->end = (uintptr_t)target + length;
hashmap_set(modules, mod_info->name, (void *)mod_data);
return mod_data;
mod_load_error:
return NULL;
@ -226,7 +235,7 @@ void * module_load(char * filename) {
void * blob = (void *)kvmalloc(file->length);
read_fs(file, 0, file->length, (uint8_t *)blob);
void * result = module_load_direct(blob);
void * result = module_load_direct(blob, file->length);
close_fs(file);
return result;

18
modules/crash.c Normal file
View File

@ -0,0 +1,18 @@
#include <module.h>
#include <mod/shell.h>
DEFINE_SHELL_FUNCTION(crash, "Dereference NULL.") {
int x = *((int *)0x20000000 );
return x;
}
static int crash_init(void) {
BIND_SHELL_FUNCTION(crash);
return 0;
}
static int crash_fini(void) {
return 0;
}
MODULE_DEF(crash, crash_init, crash_fini);

View File

@ -611,13 +611,13 @@ static int shell_mod(fs_node_t * tty, int argc, char * argv[]) {
}
fs_printf(tty, "Okay, going to load a module!\n");
module_defs * mod_info = module_load(argv[1]);
module_data_t * mod_info = module_load(argv[1]);
if (!mod_info) {
fs_printf(tty, "Something went wrong, failed to load module: %s\n", argv[1]);
return 1;
}
fs_printf(tty, "Loaded %s!\n", mod_info->name);
fs_printf(tty, "Loaded %s at 0x%x\n", mod_info->mod_info->name, mod_info->bin_data);
return 0;
}
@ -683,9 +683,11 @@ static int shell_modules(fs_node_t * tty, int argc, char * argv[]) {
list_t * hash_keys = hashmap_keys(modules_get_list());
foreach(_key, hash_keys) {
char * key = (char *)_key->value;
module_defs * mod_info = hashmap_get(modules_get_list(), key);
module_data_t * mod_info = hashmap_get(modules_get_list(), key);
fs_printf(tty, "%s {.init=0x%x, .fini=0x%x}\n", mod_info->name, mod_info->initialize, mod_info->finalize);
fs_printf(tty, "%s at 0x%x {.init=0x%x, .fini=0x%x}\n",
mod_info->mod_info->name, mod_info->bin_data,
mod_info->mod_info->initialize, mod_info->mod_info->finalize);
}
return 0;