Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access variable define in linker script in c?

Tags:

c

gcc

ld

In the linker script, I defined PROVIDE(__KERNEL_BEGIN__ = .);.

The address can be accessed from:

extern uint32_t __KERNEL_BEGIN__[];

But, the following does not work (gives an incorrect address):

extern uint32_t * __KERNEL_BEGIN__;

I looked at the assembly. The first method, __KERNEL_BEGIN__, provides the exact address. The second one, __KERNEL_BEGIN__ = [address], looks up a value at the address.

So, must it be this way? I cannot tell the difference.

like image 645
pete lin Avatar asked Oct 12 '16 12:10

pete lin


2 Answers

You need to take the address of the extern variable. It is not completely intuitive but is explained in the manual.

In theory, the extern can be any primitive data type. For reasons which I am unaware, the convention is to use a char:

extern char __KERNEL_BEGIN__;

Then to get the address exported from the linker script, take the address of __KERNEL_BEGIN__:

printf("Address: %08x\n", &__KERNEL_BEGIN__);

You can read about this in the manual for ld.

like image 54
Ryan Avatar answered Oct 12 '22 10:10

Ryan


This is more in reference to your follow-up question beneath Ryan's post, however it may help answer your original question as well.

"Variables" defined in linker scripts aren't treated the same as those defined in C; they're more symbols than anything. When accessing these symbols defined in your linker scripts, you must use the & operator.

For example, if we had the following section in our linker script:

.data :
{
    _sdata = .;
    *(.data*);
    _edata = .;
} > ram AT >rom

We could get a pointer to the start of the .data section like so:

uint8_t *data_ptr = &_sdata;

For further reading, try the binutils docs, or this excellent primer on linker scripts

Cheers

like image 30
Tyrel Kostyk Avatar answered Oct 12 '22 11:10

Tyrel Kostyk