Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU ld removes section

I'm writing a boot script for an ARM-Cortex M3 based device. If I compile the assembler boot script and the C application code and then combine the object files and transfer them to my device everything works.

However, if I use ar to create an archive (libboot.a) and combine that archive with the C application there is a problem:

I've put the boot code in a section:

    .section    .boot, "ax"
    .global     _start

_start:
    .word       0x10000800  /* Initial stack pointer (FIXME!) */
    .word       start
    .word       nmi_handler
    .word       hard_fault_handler
    ... etc ...

I've found that ld strips this from the final binary (the section "boot" is not available). This is quite natural as there is no dependency on it that ld knows about, but it causes the device to not boot correctly.

So my question is: what is the best way to force this code to be included?

like image 855
Jonatan Avatar asked Apr 21 '10 11:04

Jonatan


4 Answers

Try adding something like:

KEEP(*(.boot))

in the ld linker script to tell the linker to keep the .boot section.

However, I'm not sure if this is enough to cause ld to pull in any objects from the archive that are in the .boot section - it might not consider an object at all unless some symbol in that object is causing it to be pulled in. If this is a problem, specifying _start as the entry point (using -e _start on the ld command line or using ENTRY(_start) in the linker script) may be the solution.

like image 145
Michael Burr Avatar answered Nov 09 '22 09:11

Michael Burr


I think you want to pass the --no-gc-sections option to the linker. From the GNU ld documentation:

--gc-sections
--no-gc-sections

Enable garbage collection of unused input sections.

`--gc-sections' decides which input sections are used
by examining symbols and relocations. The section
containing the entry symbol and all sections containing symbols
undefined on the command-line will be kept, as will sections
containing symbols referenced by dynamic objects.
Note that when building shared libraries, the linker must
assume that any visible symbol is referenced. Once this initial
set of sections has been determined, the linker recursively marks
as used any section referenced by their relocations.
See `--entry' and `--undefined'.
like image 24
Dan Avatar answered Nov 09 '22 09:11

Dan


The linker will only extract from an archive those objects required to resolve explicitly referenced symbols. Your start-up code is not explicitly referenced because it is invoked via the reset vector.

If your boot code comprises multiple modules you should create a partially linked object file using ld and the -r / --relocatable option, this will combine the objects into a single object without the need to resolve all symbols (such as main() for example). This can then be used in a full link with your application code. If it is only a single object file then there is no real advantage in creating an archive in any case (and as you have found it won't work).

Note that traditionally GNU C runtime start-up is provided in a file called crt0.o (not an archive) presumably for the same reason.

like image 2
Clifford Avatar answered Nov 09 '22 08:11

Clifford


You could use --whole-archive when linking but it's a big elephant gun. The man page claims:

For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the link, rather than searching the archive for the required object files.

like image 2
Rick Dean Avatar answered Nov 09 '22 08:11

Rick Dean