Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Utilizing same header file for linker script and C program, is it possible?

For example I want to place a special data in 0x100000000, 0x100100000, 0x100200000, ... and for this I want to do in a header file,

#define DATA_START 0x100000000
#define DATA_GAP 0x100000
#define DATA0_START DATA_START + 0*DATA_GAP
#define DATA1_START DATA_START + 1*DATA_GAP
#define DATA2_START DATA_START + 2*DATA_GAP

Now I want to have a linker script and define sections there and want to do something like this. (so that the C program and linker script match).

. = DATA_START;
.mydata : {
  *(.data0)
   . = ALIGN(DATA_GAP);
  *(.data1)
   . = ALIGN(DATA_GAP);
...
}

of course with enough value for DATA_GAP so that data don't overlap.
But in linker script, the define statement is not "#define DATA_START 0x100000000" but "DATA_START = 0x100000000;". So if I want to use a single file to be used in C and linker script, how can I do it?? (I read somewhere that in programs there should be single point of truth, without having to fix data in multiple places..)
I know how to declare a variable in linker script and use it C program (using "var = ." in linker sciprt and using &var in C program..), but this time I want to statically allocate some data.

like image 396
Chan Kim Avatar asked Feb 06 '26 11:02

Chan Kim


1 Answers

Only working solution I can think of:

  1. Create a separate header file for those constants.
  2. Use #ifdef to split definitions for C programs and for the linker script.
  3. Include the header file in both your program (other .c files) and the linker script.
  4. Preprocess the linker script with the C preprocessor too. You will have to use a different name/extension for the original linker script (with the #include) and the final one.

The header file would look something like this:

#ifndef SECTIONS_H
#define SECTIONS_H

#define _DATA_START  0x100000000
#define _DATA_GAP    0x100000
#define _DATA0_START _DATA_START + 0*_DATA_GAP
#define _DATA1_START _DATA_START + 1*_DATA_GAP
#define _DATA2_START _DATA_START + 2*_DATA_GAP

#ifdef LINKER_SCRIPT

DATA_START  = _DATA_START
DATA_GAP    = _DATA_GAP
DATA0_START = _DATA0_START
DATA1_START = _DATA1_START
DATA2_START = _DATA2_START

#else // !LINKER_SCRIPT

#define DATA_START  _DATA_START
#define DATA_GAP    _DATA_GAP
#define DATA0_START _DATA0_START
#define DATA1_START _DATA1_START
#define DATA2_START _DATA2_START

#endif // LINKER_SCRIPT

#endif // SECTIONS_H

Then in your linker file you can do:

#include "sections.h"

. = DATA_START;
.mydata : {
  *(.data0)
   . = ALIGN(DATA_GAP);
  *(.data1)
   . = ALIGN(DATA_GAP);
...
}

And then you could do:

gcc -E -P -xc -DLINKER_SCRIPT script.ldX > script.ld
gcc -T script.ld -o program foo.o bar.o baz.o
like image 111
Marco Bonelli Avatar answered Feb 09 '26 04:02

Marco Bonelli



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!