ld location counter going backward?

Luke T. Shumaker lukeshu@lukeshu.com
Tue Mar 24 07:15:56 GMT 2026


Hi,

I'm a newb with linker scripts, and needed to edit an existing script;
I've already got it to do what I need it to, but I'd like to
understand why my first approaches didn't work.

The pre-existing linker script says:

    ...
    } > RAM
    __binary_info_end = .;
    . = ALIGN(4);

    .data  : {
        __data_start__ = .;
    ...

That places `.data` at 0x2000'7110, and for ARMv6-M
memory-protection-unit reasons I need to bump it forward a bit to
what turns out to be 0x2000'8000.  So I changed it to:

    ...
    } > RAM
    __binary_info_end = .;

    . = ALIGN((1<<LOG2CEIL(.-__logical_binary_start))/8);
    .data  : {
        __data_start__ = .;
    ...

`ld --print-map` indicates to me that the expression calculates the
correct desired value for `.`, but then it moves backward and places
.data before that address:

    ...
    .rel.dyn        0x20007104        0x0
     .rel.iplt      0x20007104        0x0 CMakeFiles/vpu_objs.dir/vpu.c.o
                    0x20008000                        . = ALIGN (((0x1 << LOG2CEIL ((. - __logical_binary_start))) / 0x8))

    .data           0x20007110      0x5dc
                    0x20007110                        __data_start__ = .
    ...

(I think that `.rel.dyn` is an orphan section, but I don't care too
much because I still observe this behavior with
`--orphan-handling=discard`.)  I see how it gets 0x2000'7110 from
0x2000'7104--an input section in .data has alignment of 16.  But I
don't understand why it ignores the 0x2000'8000?

I'm similarly confused why forcing the output section's alignment
doesn't seem to move .data forward either:

    .data : ALIGN((1<<LOG2CEIL(.-__logical_binary_start))/8) {

I eventually got it to do what I want by setting .data's address to
the ALIGN(...) expression:

    .data ALIGN((1<<LOG2CEIL(.-__logical_binary_start))/8) : {

But I'd like to understand why the other two approaches don't do what
I expect.  In particular, it seems to me that `.` assignments outside
of a section are totally ignored, which doesn't jive with many of the
examples given in the ld info page.

If it makes a difference:

    $ arm-none-eabi-ld --version
    GNU ld (GNU Binutils) 2.43
    ...

-- 
Happy hacking,
~ Luke T. Shumaker


More information about the Binutils mailing list