Access symbols defined in the linker script by application

That’s a bit old but i will answer it anyways…

From the ld manual:

Accessing a linker script defined variable from source code is
not intuitive. In particular a linker script symbol is not
equivalent to a variable declaration in a high level language,
it is instead a symbol that does not have a value.

Before going further, it is important to note that compilers
often transform names in the source code into different names
when they are stored in the symbol table. For example, Fortran
compilers commonly prepend or append an underscore, and C++
performs extensive name mangling. Therefore there might be a
discrepancy between the name of a variable as it is used in
source code and the name of the same variable as it is defined
in a linker script. For example in C a linker script variable
might be referred to as:

extern int foo;

But in the linker script it might be defined as:

_foo = 1000;

In the remaining examples however it is assumed that no name
transformation has taken place.

When a symbol is declared in a high level language such as C,
two things happen. The first is that the compiler reserves
enough space in the program’s memory to hold the value of
the symbol. The second is that the compiler creates an entry
in the program’s symbol table which holds the symbol’s address.
ie the symbol table contains the address of the block of memory
holding the symbol’s value. So for example the following C
declaration, at file scope:

int foo = 1000;

creates a entry called “foo” in the symbol table. This entry
holds the address of an int sized block of memory where the
number 1000 is initially stored.

When a program references a symbol the compiler generates code
that first accesses the symbol table to find the address of the
symbol’s memory block and then code to read the value from that
memory block. So:

foo = 1;

looks up the symbol foo in the symbol table, gets the address
associated with this symbol and then writes the value 1 into
that address. Whereas:

int * a = & foo;

looks up the symbol foo in the symbol table, gets it address
and then copies this address into the block of memory associated
with the variable “a”.

Linker scripts symbol declarations, by contrast, create an entry
in the symbol table but do not assign any memory to them. Thus
they are an address without a value. So for example the linker
script definition:

foo = 1000;

creates an entry in the symbol table called @samp{foo} which holds
the address of memory location 1000, but nothing special is stored
at address 1000. This means that you cannot access the value of
a linker script defined symbol – it has no value – all you can do
is use the address of a linker script defined symbol.

Hence when you are using a linker script defined symbol in source
code you should always take the address of the symbol, and never
attempt to use its value. For example suppose you want to copy
the contents of a section of memory called .ROM into a section
called .FLASH and the linker script contains these declarations:

start_of_ROM   = .ROM;
end_of_ROM     = .ROM + sizeof (.ROM);
start_of_FLASH = .FLASH;

Then the C source code to perform the copy would be:

extern char start_of_ROM, end_of_ROM, start_of_FLASH;

memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM);

Note the use of the “&” operators. They are correct.

Leave a Comment

tech