// // Created by rick on 08-03-21. // #include "debug.h" #include #include #include #include #include #include static struct elf32_section_header* elf_headers = NULL; static struct elf32_section_header* elf_shstrtab = NULL; static struct elf32_section_header* elf_symtab = NULL; static struct elf32_section_header* elf_strtab = NULL; static uint32_t elf_header_cnt; static const char* elf_name_symtab = ".symtab"; static const char* elf_name_strtab = ".strtab"; struct stackframe { struct stackframe* ebp; uint32_t eip; }; char *debug_get_shstrtab_entry(uint32_t ndx) { if (elf_shstrtab == NULL) { return NULL; } if (ndx > elf_shstrtab->sh_size) { return NULL; } return ((char*)elf_shstrtab->sh_addr + ndx); } char *debug_get_strtab_entry(uint32_t ndx) { if (elf_strtab == NULL) { return NULL; } if (ndx > elf_strtab->sh_size) { return NULL; } return ((char*)elf_strtab->sh_addr + ndx); } void debug_find_sections(uint32_t shndx) { elf_shstrtab = &elf_headers[shndx]; for (uint32_t i = 0; i < elf_header_cnt; ++i) { struct elf32_section_header *current = &elf_headers[i]; char *name = debug_get_shstrtab_entry(current->sh_name); if (name == NULL) { printf("Name was NULL\n"); continue; } if (strcmp(name, elf_name_symtab) == 0) { elf_symtab = current; continue; } if (strcmp(name, elf_name_strtab) == 0) { elf_strtab = current; continue; } } } void debug_store_info(struct multiboot_info *info) { if (!(info->flags & MULTIBOOT_INFO_ELF_SHDR)) { return; } if (sizeof(struct elf32_section_header) != info->u.elf_sec.size) { k_panics("ELF size not correct"); } elf_headers = (struct elf32_section_header *) info->u.elf_sec.addr; elf_header_cnt = info->u.elf_sec.num; debug_find_sections(info->u.elf_sec.shndx); } struct elf32_symtab_entry* debug_get_entry_for_addr(uint32_t addr) { if (elf_symtab == NULL) { return NULL; } struct elf32_symtab_entry* first = (struct elf32_symtab_entry *) elf_symtab->sh_addr; uint32_t num = elf_symtab->sh_size / sizeof(struct elf32_symtab_entry); for (uint32_t i = 0; i < num; ++i) { // only functions for now if (ELF32_ST_TYPE(first[i].st_info) != STT_FUNC) { continue; } if (addr >= first[i].st_value && addr < (first[i].st_value + first[i].st_size)) { return &first[i]; } } return NULL; } void debug_backtrace(bool do_sync) { struct stackframe *frame = __builtin_frame_address(0); void (*printer)(const char*) = do_sync ? kprint_sync : kprint; printer("\n\n## Stack Trace ##\n"); char msg[1024] = {0}; while (frame->ebp != NULL) { struct elf32_symtab_entry *entry = debug_get_entry_for_addr(frame->eip); if (entry == NULL) { sprintf(msg, "#unknown (%x)\n", frame->eip); } else { sprintf(msg, "%s (%x)\n", debug_get_strtab_entry(entry->st_name), frame->eip); }; printer(msg); frame = frame->ebp; } printer("\n"); }