I am looking for a proper way to create firmware components for a following architecture without inventing the wheel.
Consider that the system has multiple firmware executables that can be either loaded dynamically, or execute in order by passing the control to each other. And there is a common functionality that is statically loaded into a known memory address and is callable by each of the executable firmware components:
|-------------------|
| Executable 1 |
|-------------------|
| ... |
|-------------------|
| Executable 2 |
|-------------------|
| ... |
|-------------------| <--- fixed address
| Shared "library" |
|-------------------|
I’d like to be able to create the executables by linking their code with some artifact produced by the build process of the “library”, that is something like:
ld <some options and input objects> --just-symbols=library.syms executable.elf
(both the library artifact and the executable will be flattened into a raw binary later, but this step is implied and isn’t important for the question sake).
Now, the question is how to actually build this library knowing the final location it would be stored at? Traditional static libraries are usually linked with the executable and are placed according to it’s linker script. One way I saw, is to actually produce another (elf) executable with a dummy main
function and a specific linker script and use it as the “library” in the question, but it looks somewhat hack-ish way to me. In addition I am not sure it is safe and no functions that are expected to be exported are optimized out.
** Assuming GNU cross toolchain and whatever binutils in the disposal
8
This is done by “linker script”. https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html
As a very primitive example, you can do something like this:
SECTIONS {
SecA 0x10000 : {
foo.o (.text)
bar.o (.text)
}
SecB : { * (.text) }
.data : { *(.data) }
}
This would put all functions from object file foo.o
at the specified absolute address. Once object foo.o
is done, functions from the bar.o
will be the second one.
Functions, from all other objects, with no regard to sorting object files would be after.
Finally you would have a separate section for global variables.
Please note, you cannot specify locations of functions. If you have two or more functions in an object – they would be put into final output as one batch. But you can go with a one file = one function approach. At least for functions which would require absolute placement.