views:

111

answers:

4

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?

+2  A: 

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'.
Dan
+1  A: 

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.

Clifford
A: 

You could use the ld --whole-archive option to pull in unreferenced symbols. This ld options page has this for whole-archive --whole-archive

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. This is normally used to turn an archive file into a shared library, forcing every object to be included in the resulting shared library. This option may be used more than once.
Two notes when using this option from gcc: First, gcc doesn't know about this option, so you have to use -Wl,-whole-archive. Second, don't forget to use -Wl,-no-whole-archive after your list of archives, because gcc will add its own list of archives to your link and you may not want this flag to affect those as well.

Also see this question on stack overflow, uses of whole-archive option

Jasmeet
A: 

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.

Michael Burr