3
votes

I'm using a modular build system for software than runs on an ARM embedded target as well as on a normal X86 (linux) machine. I'm compiling with a GNU toolchain, thus linking using ld.

One of the modules makes use of a linkerscript trick to assemble an array of 'registered' objects. The objects are created with a macro like this:

#define RegObject(name, arg1, arg2, etc) \
    static TRegObject name \
    __attribute__((section ("regobj_table"), used)) = \
    { arg1, arg2, etc }

The module also adds an implicit linker script to the link step, which looks like this:

SECTIONS
{
    .data : ALIGN(4)
    {
        regobj_table_start = .;
        KEEP(*(regobj_table))
        regobj_table_end = .;
    }
}

The regobj_table_start and regobj_table_end symbols are used by the code to find the registered objects. This solution works just fine for native (Linux) compiled targets.

This doesn't work for the ARM target however. The reason is that I have a custom default linker script for the target (it's a tiny microcontroller, running without an OS), which defines a load memory address for the .data section. This is because the section is stored in Flash memory, but once the microcontroller boots it's copied to RAM. The relevant part of the linker script looks like this:

MEMORY
{
  ROM (rx)  : ORIGIN = 0x00000000, LENGTH = 512k
  RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 32k
}

SECTIONS
{
    /* ... other stuff ... */

    .data :
    {
        _data = .;
        *(.data)
        *(.data.*)
    } >RAM AT>ROM

    /* ... even more stuff ... */
}

This sets the VMA of the .data section to somewhere in the 0x4000000 range, and the LMA in the 0x00000000 range.

The problem is that when the implicit linker script is added to the command-line of ld, it just forgets about the LMA and it becomes equal to the VMA again. I'm desperately looking for a method to tell ld to not touch the LMA when loading the implicit linker script.

1
Just a wild guess: would adding another implicit script (after the one already being used) for the ARM build do the trick: SECTIONS { .data { } AT >ROM }. Alternatively, if the ARM build can use a different implicit script in the first place, just add the AT>ROM in the appropriate place in that script. - Michael Burr
That doesn't work because the ROM memory region isn't available outside the script where it's defined. I already tried that. - Bart
Have you considered embedding your implicit script into the explicit script for ARM (thus you'd have - unfortunately - two scripts - one for ARM, and the implicit short one for x86) - this really is the simpliest solution... Or maybe use a custom section for the objects? - Freddie Chopin
Besides that it isn't possible (to refer to the ROM section in an implicit script) I indeed want to keep the implicit script 'agnostic' of the underlying architecture. Right now I'm working around this problem by using the .rodata section (which has equal LMA and VMA) to keep pointers to the registered objects in the data section. - Bart

1 Answers

0
votes

Try using INSERT AFTER ... as the last line. This will insert your script into the default one.