backtrace: print function name instead of addr

Thx to the ELF header given by the bootloader
This commit is contained in:
Mathieu Maret 2023-11-20 00:11:47 +01:00 committed by Mathieu Maret
parent 60e71f6521
commit f05e017d45
4 changed files with 104 additions and 1 deletions

View File

@ -159,6 +159,9 @@ void kmain(unsigned long magic, unsigned long addr)
}
}
if (CHECK_FLAG(mbi->flags, 5)) {
stackSymbolSetup(mbi);
}
if (CHECK_FLAG(mbi->flags, 6)) {
memMapAvailable = 1;
}

View File

@ -1,7 +1,94 @@
#include "stack.h"
#include "elf.h"
#include "klibc.h"
#include "paging.h"
#include "types.h"
/** Defined in linker.ld script **/
extern char __multiboot_data_start;
extern char __multiboot_data_end;
static size_t multibootDataSize;
static size_t multibootUsage;
/** Initialized at 'StackSymbolSetup'. */
static Elf32_Sym_t *elfSymtab;
static size_t elfSymtabSize;
static const char *elfStrtab;
static size_t elfStrtabSize;
static void *stackSaveSection(const void *addr, size_t size, const char *sectionName)
{
if (size > (multibootDataSize - multibootUsage)) {
printf("No enough room to store %s (%d/%d). Increase multiboot_data section size",
sectionName, size, (multibootDataSize - multibootUsage));
return NULL;
}
void *destAddr = (void *)&__multiboot_data_start + multibootUsage;
memcpy((void *)destAddr, addr, size);
multibootUsage += size;
return destAddr;
}
/**
* Copy the symbols table and string table from a multiboot information.
* We need to copy them as they are loaded by the bootloader and could be override as soon
* as we play with memory around our loaded kernel.
* As special ELF section is allocated for this purpose.
*/
void stackSymbolSetup(multiboot_info_t *mbi)
{
/** Get the section header table as an array of section headers. */
Elf32_Shdr_t *sht = (Elf32_Shdr_t *)mbi->u.elf_sec.addr;
size_t sec_len = (size_t)mbi->u.elf_sec.num;
assert(mbi->u.elf_sec.size == sizeof(Elf32_Shdr_t));
multibootDataSize = &__multiboot_data_end - &__multiboot_data_start;
multibootUsage = 0;
/**
* The section header at index 'shndx' in the table is a meta section
* header. It contains a list of section header names in the table. We
* should look for section header names ".symtab" & ".strtab".
*/
const char *sh_names = (const char *)sht[mbi->u.elf_sec.shndx].sh_addr;
/** Loop through the table and look for ".symtab" & ".strtab". */
for (size_t i = 0; i < sec_len; ++i) {
const char *name = sh_names + sht[i].sh_name;
if (strcmp(name, ".symtab") == 0) {
assert(sht[i].sh_type == SHT_SYMTAB);
elfSymtab = stackSaveSection((void *)sht[i].sh_addr, sht[i].sh_size, name);
if (elfSymtab)
elfSymtabSize = sht[i].sh_size;
} else if (strcmp(name, ".strtab") == 0) {
assert(sht[i].sh_type == SHT_STRTAB);
elfStrtab = stackSaveSection((void *)sht[i].sh_addr, sht[i].sh_size, name);
if (elfStrtab)
elfStrtabSize = sht[i].sh_size;
}
}
}
/** Look up an address in symbols map and return its function name or NULL. */
static const char *lookupSymbolName(uint32_t addr)
{
size_t symtab_len = elfSymtabSize / sizeof(Elf32_Sym_t);
for (size_t i = 0; i < symtab_len; ++i) {
if ((ELF_SYM_TYPE(elfSymtab[i].st_info) == ELF_SYM_TYPE_FUNC) &&
(addr >= elfSymtab[i].st_value) &&
(addr <= elfSymtab[i].st_value + elfSymtab[i].st_size)) {
return elfStrtab + elfSymtab[i].st_name;
}
}
return NULL;
}
void printStackTrace(unsigned int maxFrames)
{
#ifdef DEBUG
@ -21,7 +108,12 @@ void printStackTrace(unsigned int maxFrames)
break;
}
unsigned int *arguments = ebp + 2;
printf("[%d] 0x%x (", frame, eip);
const char *functionName = lookupSymbolName(eip);
if (functionName != NULL) {
printf("[%d] %s (", frame, functionName);
} else {
printf("[%d] 0x%x (", frame, eip);
}
int nbArg = 0;
do {
if ((_stack_bottom <= (vaddr_t)arguments) && ((vaddr_t)arguments <= _stack_top)) {

View File

@ -1,6 +1,8 @@
#pragma once
#include "multiboot.h"
#include "types.h"
extern vaddr_t _stack_bottom;
extern vaddr_t _stack_top;
void printStackTrace(unsigned int maxFrame);
void stackSymbolSetup(multiboot_info_t *mbi);

View File

@ -39,6 +39,12 @@ SECTIONS
*(.bss)
}
.multiboot_data : {
__multiboot_data_size = 48k;
__multiboot_data_start = .;
. = . + __multiboot_data_size;
__multiboot_data_end = .;
}
__ld_kernel_end = .;
/* The compiler may produce other sections, by default it will put them in