Can you add two SECTION sections to ld script

4

I have an executable made by linking several .o files, using a somewhat involved linker script. If a particular environment flag is set, I'd like there to be another section involved. So, something like:

/* withfoo.ld */
SECTIONS {
 .foo 0x80000000 : {
    _start_foo = .;
    . += 0xfff;
    _end_foo = .;
 }
}

and then compile with:

if [ $FOO_DEFINED ]; then
    gcc -Wl,-T normal.ld $(OBJS) foo.o foo.ld
else
    gcc -Wl,-T normal.ld $(OBJS)
fi

where I'd like to not to have to modify normal.ld. normal.ld has a SECTIONS definition within it. So that gives me two SECTIONS... I'm getting the warning:

/usr/bin/ld: warning: foo.ld contains output sections; did you forget -T?

Is there an actual problem or is this just a warning? Also is there a proper way to do this that I'm not aware of?

gcc
linker
linker-errors
ld
linker-scripts
asked on Stack Overflow Nov 27, 2017 by HardcoreHenry • edited Sep 15, 2019 by Michael Petch

1 Answer

3

GNU linker scripts and LD do not support conditional compile. You can't use two linker scripts at once and have it work as expected. You have to pre-process the linker script with some other type of macro language like m4 or even just use the GNU C Preprocessor cpp.


Not sure if this is a type of solution you are looking for. The C preprocessor cpp can process the text of any kind of file (even non-C files) and will blindly parse for pre-processor directives and macros just like a C file. You can also pass C style defines through the cpp command line just like you can with GCC. You create a linker script with all the C pre-processor directives and generate specific linker scripts based on that. For example create a special linker script like this:

linker.ld.pp :

SECTIONS {
#ifdef FOO
 .foo 0x80000000 : {
    _start_foo = .;
    . += 0xfff;
    _end_foo = .;
 }
#endif
}

This uses typical C style #if/#ifdef/#endif for conditional compilation. If you run it through the C pre-processor with a command like:

cpp -P -DFOO linker.ld.pp

You'd get output like this:

SECTIONS {
 .foo 0x80000000 : {
    _start_foo = .;
    . += 0xfff;
    _end_foo = .;
 }
}

Not defining FOO would be done like this:

cpp -P linker.ld.pp

The output would be:

SECTIONS {
}

To redirect the pre-processor you can output to a linker script with:

cpp -P -DFOO linker.ld.pp >withfoo.ld
cpp -P linker.ld.pp >withoutfoo.ld

You can specify multiple -D directives on the CPP command line to define multiple pre-processor symbols if you wish. The idea of this method is that you have a single linker script but you create a shell script to generate the necessary specialized scripts that are required.


Other Observations

Usually you specify linker scripts on the GCC command line with the -T option:

gcc -T withfoo.ld $(OBJS) foo.o
answered on Stack Overflow Nov 27, 2017 by Michael Petch • edited Mar 17, 2019 by Michael Petch

User contributions licensed under CC BY-SA 3.0