misc: Implement stacktrace

This commit is contained in:
mintsuki 2020-11-15 17:56:10 +01:00
parent 36b5be1380
commit 8460cee5ca
12 changed files with 149 additions and 18 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
/**/*.gen
/**/*.map
/**/*.o
/**/*.d
/**/*.a

View File

@ -8,6 +8,7 @@ all: stage2 decompressor
gzip -n -9 < stage2/stage2.bin > stage2/stage2.bin.gz
cd bootsect && nasm bootsect.asm -fbin -o ../limine.bin
cd pxeboot && nasm bootsect.asm -fbin -o ../limine-pxe.bin
cp stage2/stage2.map ./
clean: stage2-clean decompressor-clean test-clean
rm -f stage2/stage2.bin.gz
@ -55,6 +56,7 @@ echfs-test: limine-install test.img
ext2-test: limine-install test.img
$(MAKE) -C test
cp stage2.map test/
rm -rf test_image/
mkdir test_image
sudo losetup -Pf --show test.img > loopback_dev
@ -62,8 +64,7 @@ ext2-test: limine-install test.img
sudo mkfs.ext2 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp test/test.elf test_image/boot/
sudo cp test/limine.cfg test_image/
sudo cp -rv test/* test_image/boot/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`
@ -80,8 +81,7 @@ fat32-test: limine-install test.img
sudo mkfs.fat -F 32 `cat loopback_dev`p1
sudo mount `cat loopback_dev`p1 test_image
sudo mkdir test_image/boot
sudo cp test/test.elf test_image/boot/
sudo cp test/limine.cfg test_image/
sudo cp -rv test/* test_image/boot/
sync
sudo umount test_image/
sudo losetup -d `cat loopback_dev`

View File

@ -9,8 +9,17 @@ void entry(uint8_t *compressed_stage2, size_t stage2_size, uint8_t boot_drive, i
tinf_gzip_uncompress(dest, compressed_stage2, stage2_size);
__attribute__((noreturn))
void (*stage2)(uint8_t boot_drive, int pxe) = (void *)dest;
asm volatile (
"mov esp, 0x7c00\n\t"
"xor ebp, ebp\n\t"
"push %1\n\t"
"push %0\n\t"
"push 0\n\t"
"jmp 0x8000\n\t"
:
: "r" ((uint32_t)boot_drive), "r" (pxe)
: "memory"
);
stage2(boot_drive, pxe);
for (;;);
}

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +1,10 @@
CC = i386-elf-gcc
LD = i386-elf-gcc
OBJCOPY = i386-elf-objcopy
OBJDUMP = i386-elf-objdump
WERROR = -Werror
CFLAGS = -flto -Os -pipe -Wall -Wextra $(WERROR)
CFLAGS = -Os -pipe -Wall -Wextra $(WERROR)
INTERNAL_CFLAGS = \
-std=gnu11 \
@ -11,7 +12,7 @@ INTERNAL_CFLAGS = \
-ffreestanding \
-fno-stack-protector \
-fno-pic \
-fomit-frame-pointer \
-fno-omit-frame-pointer \
-Wno-address-of-packed-member \
-masm=intel \
-mno-80387 \
@ -23,7 +24,7 @@ INTERNAL_CFLAGS = \
-I. \
-I..
LDFLAGS = -flto -Os
LDFLAGS = -Os
INTERNAL_LDFLAGS = \
-lgcc \
@ -41,11 +42,17 @@ ASM_FILES := $(shell find ./ -type f -name '*.asm' | sort)
OBJ := $(ASM_FILES:.asm=.o) $(C_FILES:.c=.o)
HEADER_DEPS := $(C_FILES:.c=.d)
all: stage2.bin
all: stage2.map stage2.bin
stage2.bin: $(OBJ)
$(LD) $(OBJ) $(LDFLAGS) $(INTERNAL_LDFLAGS) -o stage2.elf
$(OBJCOPY) -O binary stage2.elf stage2.bin
stage2.map: stage2.elf
./gensyms.sh $(OBJDUMP)
nasm symlist.gen -f bin -o $@
stage2.bin: stage2.elf
$(OBJCOPY) -O binary $< $@
stage2.elf: $(OBJ)
$(LD) $(OBJ) $(LDFLAGS) $(INTERNAL_LDFLAGS) -o $@
-include $(HEADER_DEPS)
@ -56,4 +63,4 @@ stage2.bin: $(OBJ)
nasm $< -f elf32 -o $@
clean:
rm -f stage2.bin stage2.elf $(OBJ) $(HEADER_DEPS)
rm -f symlist.gen stage2.map stage2.bin stage2.elf $(OBJ) $(HEADER_DEPS)

17
stage2/gensyms.sh Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
set -e
TMP1=$(mktemp)
TMP2=$(mktemp)
TMP3=$(mktemp)
$1 -t stage2.elf | sed '/\bd\b/d' | sort > "$TMP1"
grep "\.text" < "$TMP1" | cut -d' ' -f1 > "$TMP2"
grep "\.text" < "$TMP1" | awk 'NF{ print $NF }' > "$TMP3"
paste -d'$' "$TMP2" "$TMP3" | sed 's/^/dd 0x/g' | sed 's/$/", 0/g' | sed 's/\$/\ndb "/g' > symlist.gen
echo "dd 0xffffffff" >> symlist.gen
rm "$TMP1" "$TMP2" "$TMP3"

View File

@ -4,6 +4,7 @@
#include <lib/libc.h>
#include <lib/blib.h>
#include <lib/print.h>
#include <lib/trace.h>
uint8_t boot_drive;
@ -73,6 +74,9 @@ __attribute__((noreturn)) void panic(const char *fmt, ...) {
va_end(args);
print("\n");
print_stacktrace(NULL);
for (;;) {
asm volatile ("hlt" ::: "memory");
}

75
stage2/lib/trace.c Normal file
View File

@ -0,0 +1,75 @@
#include <stddef.h>
#include <stdint.h>
#include <lib/trace.h>
#include <lib/blib.h>
#include <lib/config.h>
#include <lib/print.h>
#include <lib/uri.h>
#include <fs/file.h>
#include <mm/pmm.h>
static char *stage2_map = NULL;
void trace_init(void) {
char map_filename[80];
if (!config_get_value(map_filename, 0, 80, "STAGE2_MAP"))
return;
struct file_handle stage2_map_file;
if (!uri_open(&stage2_map_file, map_filename))
panic("Could not open stage2 map file `%s`", map_filename);
stage2_map = ext_mem_alloc(stage2_map_file.size);
fread(&stage2_map_file, stage2_map, 0, stage2_map_file.size);
print("trace: Stage 2 map file `%s` loaded.\n", map_filename);
}
char *trace_address(size_t *off, size_t addr) {
if (!stage2_map)
return NULL;
uint32_t prev_addr = 0;
char *prev_sym = NULL;
for (size_t i = 0;;) {
if (*((uint32_t *)&stage2_map[i]) >= addr) {
*off = addr - prev_addr;
return prev_sym;
}
prev_addr = *((uint32_t *)&stage2_map[i]);
i += sizeof(uint32_t);
prev_sym = &stage2_map[i];
while (stage2_map[i++] != 0);
}
}
void print_stacktrace(size_t *base_ptr) {
if (!stage2_map)
print("trace: Symbol names won't be resolved due to missing map file.\n");
if (base_ptr == NULL) {
asm volatile (
"mov %0, ebp"
: "=g"(base_ptr)
:: "memory"
);
}
print("Stacktrace:\n");
for (;;) {
size_t old_bp = base_ptr[0];
size_t ret_addr = base_ptr[1];
if (!ret_addr)
break;
size_t off;
char *name = trace_address(&off, ret_addr);
if (name)
print(" [%x] <%s+%x>\n", ret_addr, name, off);
else
print(" [%x]\n", ret_addr);
if (!old_bp)
break;
base_ptr = (void*)old_bp;
}
print("End of trace.\n");
}

10
stage2/lib/trace.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __LIB__TRACE_H__
#define __LIB__TRACE_H__
#include <stdint.h>
void trace_init(void);
char *trace_address(size_t *off, size_t addr);
void print_stacktrace(size_t *base_ptr);
#endif

View File

@ -5,6 +5,7 @@
#include <lib/libc.h>
#include <lib/part.h>
#include <lib/config.h>
#include <lib/trace.h>
#include <sys/e820.h>
#include <sys/a20.h>
#include <lib/print.h>
@ -67,6 +68,8 @@ void entry(uint8_t _boot_drive, int pxe_boot) {
}
}
trace_init();
char *cmdline = menu();
char proto[32];

View File

@ -3,21 +3,25 @@ TIMEOUT=3
GRAPHICS=yes
MENU_RESOLUTION=1024x768
E9_OUTPUT=yes
STAGE2_MAP=bios://:1/boot/stage2.map
THEME_COLOURS=60000000;aa0000;00aaff;aa5500;0000aa;aa00aa;9076de;aaaaaa
THEME_MARGIN=64
BACKGROUND_PATH=guid://@GUID@/bg.bmp
BACKGROUND_PATH=bios://:1/boot/bg.bmp
:Stivale Test
PROTOCOL=stivale
KERNEL_PATH=guid://@GUID@/boot/test.elf
KERNEL_PATH=bios://:1/boot/test.elf
KERNEL_CMDLINE=Hi! This is an example!
MODULE_PATH=bios://:1/boot/test.elf
MODULE_STRING=yooooo
MODULE_PATH=bios://:1/boot/bg.bmp
MODULE_STRING=yooooo
:Stivale2 Test
PROTOCOL=stivale2
@ -25,5 +29,5 @@ RESOLUTION=640x480x16
KERNEL_PATH=bios://:1/boot/test.elf
KERNEL_CMDLINE=Woah! Another example!
MODULE_PATH=guid://@GUID@/boot/test.elf
MODULE_PATH=bios://:1/boot/bg.bmp
MODULE_STRING=yooooo