Up until recently, I've been using the Bochs emulator to test my OS, but I got sick of not having a proper debugger, so I finally decided to switch to QEMU and GDB. I managed to get the debugger working mostly fine, I can set breakpoints and everything seems to run normally, except for when I actually try to debug code. I run into the problem of GDB being unable to "compute CFA for this frame" whenever it tries to compute the values of any local variables (ones which are stored on the stack, right?). I'll admit I have a weak-ish understanding of the internals of the debugger, but from what I can tell, it's telling me that it can't figure out the layout of the stack and whereabouts my local variables should be on the stack. At least, that's what I think it is, but again, not 100% sure, debuggers aren't really second nature for me yet.
In any case, this problem is stopping me from debugging my code easily, and for now I have to resort back to my old hacky method (which was to put values like 0xDEADBEEF into values I wanted to monitor, break before a the local variable gets it's value changed, and find my marker value's location in a dump of the stack memory. Ugly and time consuming, I know). I have a feeling it has something to do with the Stack base pointer register (I think it's usually called the EBP register on 32 bit x86 machines?), which helps maintain a stack "frame" of sorts. I know it's important for debuggers and traceback functions, but no matter where I pause execution, it always seems to be strange values like 0 or garbage values (nowhere near any code or stack memory, I thought it was supposed to be pointing to a value on the stack normally). It seems that for some reason, the C compiler doesn't seem to be properly maintaining the stack frame, which is what the debuggers/tracebacks use to keep track of which function the CPU is currently in and what the local variables are (and also what GDB uses to calculate offsets in the stack for local variables, it seems).
So, is there a way to make sure the C compiler actually uses the EBP register as intended? (That is, pushing the old EBP on the stack and pushing the stack pointer into the EBP register, or something like that, I'm not much of an expert on the internal workings of C function preludes either.) I'm using a normal GCC cross compiler exactly like in the tutorial on the Bare Bones page, and my bootstrap ASM code is very similar to Bare Bones too in terms of how it calls my kernel's main function. So I thought that it would behave fairly normally and actually use the EBP register like it would normally do, but I guess that's something that's turned off in a cross compiler.
For completeness and reference, here's my build options and build lines (I've also been passing the -g option to the makefile through the command line while I've been setting up GDB and QEMU by running [CFLAGS="-std=c99 -Wall -Wextra -O2 -g" make ] ):
Code: Select all
# Tool info
TOOL-PREFIX=i686-elf-
AS=nasm
ASFLAGS?=-f elf32
LD=$(TOOL-PREFIX)ld
LDFLAGS?= -ffreestanding -lgcc
CC=$(TOOL-PREFIX)gcc
CFLAGS?=-std=c99 -Wall -Wextra -O2
CFLAGS:=$(CFLAGS) -ffreestanding
# Pattern recipie to build core kernel files
$(OBJDIR)/%.o: $(CDIR)/%.c $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(ASMDIR)/%.asm $(OBJDIR)
$(AS) $(ASFLAGS) $< -o $@
# Kernel compile and link recipie
$(BINDIR)/kernel.bin: $(KERNEL_DEPENDS) $(SRCDIR)/linker.ld $(BINDIR)
$(CC) $(LDFLAGS) -T $(SRCDIR)/linker.ld -o $(BINDIR)/kernel.bin -nostdlib -lgcc $(KERNEL_DEPENDS)
Code: Select all
# Kernel object file compile
i686-elf-gcc -std=c99 -Wall -Wextra -O2 -ffreestanding -Iinclude/kernel -c src/kernel/c/kernel.c -o obj/kernel.o
# Kernel Linking
i686-elf-gcc -ffreestanding -lgcc -T src/kernel/linker.ld -o bin/kernel.bin -nostdlib -lgcc obj/mem.o obj/input.o ...Loads of object files... obj/keyboard_asm.o obj/io.o obj/bootstrap.o obj/gdt.o
Code: Select all
Breakpoint 1, initialise_kernel_paging (kernel_start=<error reading variable: can't compute CFA for this frame>,
kernel_end=<error reading variable: can't compute CFA for this frame>) at src/kernel/c/paging.c:30
30 {
- Mikumiku747