Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static variables not initialized

I am developping a small kernel for Raspberry Pi as a school project. We are encountering an issue with static variable initialization: it seems that those are not initialized at all. I've found a few related topics, yet none have brought a solution so far, though this helped me understand the issue (at least, I think).

All the code can be found on this repository, but I will try to sum up the related code here.

Code extracted from the project showing the problem: (kernel/src/kernel.cpp)

static int staticVal = 42;

void doStuff() { // Prevent the compiler from optimizing the value of staticVal
    staticVal++;
}

__attribute__((section(".init")))
int main(void) {
    //...
    gpio::blinkValue(staticVal); // Displays the value through LEDs
    //...
}

The code is then compiled using (eg)

arm-none-eabi-g++ -O2 -std=c++11 -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -nostartfiles -Wall -Wextra -pedantic -I src/ -I uspi/include -DHW_PI_1B -c src/[file].cpp -o _build/[file].o

and built into a binary file using the same options, and finally assembled into a kernel.img using

arm-none-eabi-ld --no-undefined _build/master.bin -Map _build/kernel.map -o _build/output.elf -T kernel.ld
arm-none-eabi-objcopy _build/output.elf -O binary kernel.img

(you can read the Makefile directly for more details: github.com/tobast/sysres-pikern/blob/staticNotWorking/kernel/Makefile).

The linker script used might as well be the problem, as we have tried to figure out how to write a working one without really knowing what we were doing (we use a modified linker script from another project): github.com/tobast/sysres-pikern/blob/staticNotWorking/kernel/kernel.ld

_start = 0x8000;
ENTRY(_start)

SECTIONS {
    .init 0x8000 : {
        *(.init)
    }

    .text : {
        *(.text)
    }

    .data : {
        *(.data)
    }

    .bss : {
        *(.bss)
    }
}

The program generated this way displays an apparently random value (which has, anyway, nothing to do with the expected value -- 42).

What I've understood so far is that the operating system is supposed to be responsible for initializing static variables before actually starting the program, but as we are writing an operating system, no one is doing it for us. Of course, we could manually initialize those variables (by calling a startup function for this purpose), but it would be an ugly and painful solution...

Is there any g++/linker options we are missing, or a problem in our linker script?

Thanks!

like image 947
tobast Avatar asked Oct 18 '22 09:10

tobast


1 Answers

I see a couple of problems:

  • Your sections are not page aligned, i.e with ALIGN(0x1000) in the linker script

  • You have no "start up" ASM script that sets up the stack and zeros the bss section.

I have no idea how such a script would look like on ARM (I'm used to x86), but here's an example:

        .section "vectors"
reset:  b     start
undef:  b     undef
swi:    b     swi
pabt:   b     pabt
dabt:   b     dabt
        nop
irq:    b     irq
fiq:    b     fiq

        .text
start:
        @@ Copy data to RAM.
        ldr   r0, =flash_sdata
        ldr   r1, =ram_sdata
        ldr   r2, =data_size

        @@ Handle data_size == 0
        cmp   r2, #0
        beq   init_bss
copy:
        ldrb   r4, [r0], #1
        strb   r4, [r1], #1
        subs   r2, r2, #1
        bne    copy

init_bss:
        @@ Initialize .bss
        ldr   r0, =sbss
        ldr   r1, =ebss
        ldr   r2, =bss_size

        @@ Handle bss_size == 0
        cmp   r2, #0
        beq   init_stack

        mov   r4, #0
zero:
        strb  r4, [r0], #1
        subs  r2, r2, #1
        bne   zero

init_stack:
        @@ Initialize the stack pointer
        ldr   sp, =0xA4000000

        bl    main

stop:   b     stop

Of course you would need to modify this to match the semantics of your kernel.

like image 173
user6314935 Avatar answered Nov 04 '22 00:11

user6314935