// // Created by rick on 08-03-21. // #include #include #include #include #define DEBUG_INIT #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; uintptr_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 = calloc(info->u.elf_sec.num, sizeof(struct elf32_section_header)); memcpy(elf_headers, (const void *) info->u.elf_sec.addr, sizeof(struct elf32_section_header) * info->u.elf_sec.num); 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(uintptr_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 (%lx)\n", frame->eip); } else { sprintf(msg, "%s (%lx)\n", debug_get_strtab_entry(entry->st_name), frame->eip); }; printer(msg); frame = frame->ebp; } printer("\n"); }