Using stdarg.h in bare metal programming

177 Views Asked by At

I'm writing a small bootloader for a qemu virt using cortex a72. I am able to write some text to the UART contrôler to display some text. I want to write a light version of printf to have some flexibility when writing text but stdarg seems not to work.

The compilation has no errors but when calling a function with variadic arguments, qemu seems to stuck itself in an infinite loop. When debugging with gdb, it wont leave the function and freeze even when using 'step' instead of 'next'.

Any way to use stdarg in bare metal programming or is a kernel needed ?

EDIT: I just tried to debug using assembly layout and it is even more weird. At the beginning of the function, there is a bunch of 'str' to save some registers to the stack, but when executing one of them, the program jumps to a random memory address... Here is what I see:

>0x400808b4 <printf>     stp     x29, x30, [sp, #-272]!
│   0x400808b8 <printf+4>   mov     x29, sp
│   0x400808bc <printf+8>   str     x0, [sp, #24]
│   0x400808c0 <printf+12>  str     x1, [sp, #216]
│   0x400808c4 <printf+16>  str     x2, [sp, #224]
│   0x400808c8 <printf+20>  str     x3, [sp, #232]
│   0x400808cc <printf+24>  str     x4, [sp, #240]
│   0x400808d0 <printf+28>  str     x5, [sp, #248]
│   0x400808d4 <printf+32>  str     x6, [sp, #256]
│   0x400808d8 <printf+36>  str     x7, [sp, #264]
│   0x400808dc <printf+40>  str     q0, [sp, #80]
│   0x400808e0 <printf+44>  str     q1, [sp, #96]
│   0x400808e4 <printf+48>  str     q2, [sp, #112]
│   0x400808e8 <printf+52>  str     q3, [sp, #128]
│   0x400808ec <printf+56>  str     q4, [sp, #144]
│   0x400808f0 <printf+60>  str     q5, [sp, #160]
│   0x400808f4 <printf+64>  str     q6, [sp, #176]
│   0x400808f8 <printf+68>  str     q7, [sp, #192]
│   0x400808fc <printf+72>  add     x0, sp, #0x110
│   0x40080900 <printf+76>  str     x0, [sp, #40]
│   0x40080904 <printf+80>  add     x0, sp, #0x110
│   0x40080908 <printf+84>  str     x0, [sp, #48]
│   0x4008090c <printf+88>  add     x0, sp, #0xd0
│   0x40080910 <printf+92>  str     x0, [sp, #56]
│   0x40080914 <printf+96>  mov     w0, #0xffffffc8
│   0x40080918 <printf+100> str     w0, [sp, #64]
│   0x4008091c <printf+104> mov     w0, #0xffffff80
│   0x40080920 <printf+108> str     w0, [sp, #68]
│   0x40080924 <printf+112> str     wzr, [sp, #76]
│   0x40080928 <printf+116> str     wzr, [sp, #72]

The program jumps at the str q1, [sp, #96] instruction.

EDIT2: As asked in the comments, here is a sample code that causes the bug. This code does nothing special, it just uses variadic arguments and the bug is still present.

int va_test(int arg1, ...) {
    va_list ap;
    int next;

    va_start(ap, arg1);
    while (arg1) {
        next = va_arg(ap, int);
        arg1--;
    }
    va_end(ap);
    return next; 
}

int kmain() {
    va_test(1, 2);
    return 0;
}
0

There are 0 best solutions below