cgcclinkerarm64bare-metal

Array placed in weird address different from linker script (arm64 baremetal)


In aarch64 baremetal program build, some array in the C program is given section attirubtes so that they are placed at .axpudata_args0, .axpudata_args1, ... sections and This is the linkadd.h file that is included at the start of the linker script.

AXPUDATA_START = 0xa0000000;
AXPUDATA_SPACE = 0x100000;
ARGBUF0 = AXPUDATA_START;
ARGBUF1 = AXPUDATA_START + AXPUDATA_SPACE;
ARGBUF2 = AXPUDATA_START + 2*AXPUDATA_SPACE;
ARGBUF3 = AXPUDATA_START + 3*AXPUDATA_SPACE;

And this is the linker script (showing parts).

INCLUDE linkadd.h
...
  . = AXPUDATA_START;
    _axpudata_start = .;
  .axpudata : {
        . = ARGBUF0;
        *(.axpudata_args0)
        . = ARGBUF1;
        *(.axpudata_args1)
        . = ARGBUF2;
        *(.axpudata_args2)
        . = ARGBUF3;
        *(.axpudata_args3)
        . = ARGBUF4;

I thought the arrays would be placed at 0xa0000000, 0xa0100000, 0xa0200000, ... But the resulting map files shows they were allocated at 0xa0000000, 0x14000000, 0x14010000, like below.

.axpudata       0x00000000a0000000 0xa0d00800
                0x00000000a0000000                . = ARGBUF0
 *fill*         0x00000000a0000000 0xa0000000
 *(.axpudata_args0)
 .axpudata_args0
                0x0000000140000000     0x2000 aarch64/cvp_earth/comp1_baremetal/baremetal_bm.o
                0x0000000140000000                args_buffer_0
                0x00000000a0100000                . = ARGBUF1
 *fill*         0x0000000140002000    0xfe000
 *(.axpudata_args1)
 .axpudata_args1
                0x0000000140100000     0x2000 aarch64/cvp_earth/comp1_baremetal/baremetal_bm.o
                0x0000000140100000                args_buffer_1
                0x00000000a0200000                . = ARGBUF2
 *fill*         0x0000000140102000    0xfe000
 *(.axpudata_args2)
 .axpudata_args2
                0x0000000140200000    0x40000 aarch64/cvp_earth/comp1_baremetal/baremetal_bm.o
                0x0000000140200000                args_buffer_2
                0x00000000a0300000                . = ARGBUF3
 *fill*         0x0000000140240000    0xc0000

Why does the args_buffer0 start from 0x14000000 not 0xa0000000? The actual buffer size is 0x2000, 0x2000, 0x40000, .. I don't know why after the program count is set to 0xa0000000, another 0xa0000000 is filled so that the args_buffer_0 starts at 0x14000000 not 0xa0000000. I have worked with linker script many times in the past but I can't figure out what is wrong in this case. I would apprecated it if any could shed some light to me here.


Solution

  • This is from Michael Petch's comment which is the correct answer I wanted.

    When you set . (current location counter) within an output section it is an offset relative to the virtual memory address at the beginning of the current output section (in your case 0xa0000000 since you set . to 0xa0000000 outside the section). When you do . = ARGBUF0;` you are setting the location counter to 0xa0000000 + 0xa0000000 which is 0x140000000. . = ARGBUF1; inside the section sets the location counter to 0xa0000000 + 0xa0000000 + 0x100000 which is 0x140100000 and so on

    So I changed linkadd.h like this :

    AXPUDATA_START = 0xa0000000;
    AXPUDATA_SPACE = 0x100000;
    ARGBUF0 = 0;
    ARGBUF1 = 1*AXPUDATA_SPACE;
    ARGBUF2 = 2*AXPUDATA_SPACE;
    ARGBUF3 = 3*AXPUDATA_SPACE;
    

    and the output becomes what I wanted.

    .axpudata       0x00000000a0000000   0xd00800
                    0x0000000000000000                . = ARGBUF0
     *(.axpudata_args0)
     .axpudata_args0
                    0x00000000a0000000     0x2000 aarch64/cvp_earth/comp1_baremetal/baremetal_bm.o
                    0x00000000a0000000                args_buffer_0
                    0x0000000000100000                . = ARGBUF1
     *fill*         0x00000000a0002000    0xfe000
     *(.axpudata_args1)
     .axpudata_args1
                    0x00000000a0100000     0x2000 aarch64/cvp_earth/comp1_baremetal/baremetal_bm.o
                    0x00000000a0100000                args_buffer_1
                    0x0000000000200000                . = ARGBUF2
     *fill*         0x00000000a0102000    0xfe000
     *(.axpudata_args2)
     .axpudata_args2
                    0x00000000a0200000    0x40000 aarch64/cvp_earth/comp1_baremetal/baremetal_bm.o
                    0x00000000a0200000                args_buffer_2
                    0x0000000000300000                . = ARGBUF3
     *fill*         0x00000000a0240000    0xc0000