gcc: arm-none-eabi-ld linker script doesn't update .bss start and end variables

2.1k views Asked by At

I am trying to build a sample bare-metal ARM project using "arm-none-eabi-" tool chain.

Makefile

CC := arm-none-eabi-gcc
LD := arm-none-eabi-ld
AS := arm-none-eabi-as
AR := arm-none-eabi-ar -cr
OBJCOPY := arm-none-eabi-objcopy

CFLAGS := -mcpu=arm7tdmi-s -g3
AS_FLAGS := -mcpu=arm7tdmi-s -g3

LD_FLAGS := -loslayer
LD_DIR := -Llib
LD_SCRIPT := lpc2138.ld

LIB_DIR := lib

TARGET := image.hex

OBJS := main.o startup.o

$(TARGET) : $(TARGET:%.hex=%)
    $(OBJCOPY) -O ihex $< $@

$(TARGET:%.hex=%) : $(OBJS) liboslayer.a
    $(LD) -o $@ $(LD_DIR) -T $(LD_SCRIPT) $(OBJS) $(LD_FLAGS)

liboslayer.a : oslayer.o
    $(AR) lib/$@ $^

startup.o : startup.s
    $(AS) $(AS_FLAGS) -o $@ $<

%.o : %.c
    $(CC) -c $(CFLAGS) -o $@ $<

clean :
    rm -rf $(TARGET) $(TARGET:%.hex=%) *.o $(LIB_DIR)/*.a

main.c

int a[]= {1,2};
int b[5];
int main()
{
    int i,sum=0;
    for(i = 0; i < 50; i++)
    {
        sum+=i;
        b[0] = a[1];
        a[1]++;
        b[3]--;
    }
    return 0;
}

lpc2138.ld (Linker script)

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
    SRAM  (rw) : ORIGIN = 0x40000000, LENGTH = 32K
}

SECTIONS
{
    .text :
    {
        startup.o (.text)
        *(.text)
        . = ALIGN(4);
    } > FLASH

    .rodata :
    {
        *(.rodata)
        . = ALIGN(4);
    } > FLASH

    .data :
    {
        __data_load__ = LOADADDR (.data);
        __data_start__ = .;
        *(.data)
        . = ALIGN(4);
        __data_end__ = .;
    } > SRAM AT > FLASH

    .bss :
    {
        __bss_start__ = .;
        *(.bss)
        . = ALIGN(4);
        __bss_end__ = .;
    } > SRAM

    .stack :
    {
        __stack_start__ = .;
        . = . + (LENGTH(SRAM) - SIZEOF(.data) - SIZEOF(.bss)) / 2;
        . = ALIGN(4);
        __stack_end__ = .;
    } > SRAM

    .heap :
    {
        __heap_start__ = .;
        . += LENGTH(SRAM) - SIZEOF(.data) - SIZEOF(.bss) - SIZEOF(.stack);
        . = ALIGN(4);
        __heap_end__ = .;
    } > SRAM
}

After a successful build I just ran arm-none-eabi-nm image. The output is shown below.

40000000 D a
40000008 B b
40000008 B __bss_end__
40000008 B __bss_start__
40000008 D __data_end__
000000b8 A __data_load__
40000000 D __data_start__
40008000 B __heap_end__
40004010 B __heap_start__
0000001c T main
40004010 B __stack_end__
4000001c B __stack_start__
00000000 T _start

My question is why __bss_start__ and __bss_end__ refer to the same address even though there is an uninitialised global variable in my c source code?

1

There are 1 answers

1
Sreeyesh Sreedharan On

I observed that the uninitialized global variables belong to a section called COMMON in the object file not in BSS. I modified my linker script as follows(Just added "*(COMMON)" in the .bss section)

/* Stack and heap are equal in size by default.
 *
 * A positive value for STACK_HEAP_BOUNDARY_OFFSET increase the size
 * of the stack(Decrease size of heap).
 *
 * A negetive value for STACK_HEAP_BOUNDARY_OFFSET decrease the size
 * of the stack(increase size of heap).
 */
STACK_HEAP_BOUNDARY_OFFSET = 0;
MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
    SRAM  (rw) : ORIGIN = 0x40000000, LENGTH = 32K
}

SECTIONS
{
    .text :
    {
        startup.o (.text)
        *(.text)
        . = ALIGN(4);
    } > FLASH

    .rodata :
    {
        *(.rodata)
        . = ALIGN(4);
    } > FLASH

    .data :
    {
        __data_load__ = LOADADDR (.data);
        __data_start__ = .;
        *(.data)
        . = ALIGN(4);
        __data_end__ = .;
    } > SRAM AT > FLASH

    .bss :
    {
        __bss_start__ = .;
        *(.bss)
        *(COMMON)
        . = ALIGN(4);
        __bss_end__ = .;
    } > SRAM

    .stack :
    {
        __stack_start__ = .;
        . = . + (LENGTH(SRAM) - SIZEOF(.data) - SIZEOF(.bss)) / 2;
        . += STACK_HEAP_BOUNDARY_OFFSET;
        . = ALIGN(4);
        __stack_end__ = .;
    } > SRAM

    .heap :
    {
        __heap_start__ = .;
        . += LENGTH(SRAM) - SIZEOF(.data) - SIZEOF(.bss) - SIZEOF(.stack);
        . = ALIGN(4);
        __heap_end__ = .;
    } > SRAM
}

Now the result is like the following

40000000 D a
40000008 B b
4000001c B __bss_end__
40000008 B __bss_start__
40000008 D __data_end__
000000b8 A __data_load__
40000000 D __data_start__
40008000 B __heap_end__
40004010 B __heap_start__
0000001c T main
40004010 B __stack_end__
00000000 A STACK_HEAP_BOUNDARY_OFFSET
4000001c B __stack_start__
00000000 T _start