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?
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.
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'.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With