Dynamically load code on embedded target - gcc

I have an application which runs on bare metal target and has the following structure
main.c
service.c/.h
It's compiled to ELF executable (system.elf) using standard gcc -c, ld sequence. I use linker to generate a map file showing adresses of all symbols.
Now, without re-flashing my system I need to add an extra functionality with a custom run-time loader. Remember, this is a bare-metal with no OS.
I'd like to
compile extra.c which uses APIs defined in service.h (and somehow link against existing service.o/system.elf)
copy the resulting executable to my SDRAM at runtime and jump to it
loaded code should be able to run and accesses the exported symbols from service.c as expected
I thought I'd be able to to reuse map file to link the extra.o against system.elf but this didn't work:
ld -o extraExe extra.o system.map
Does gcc or ld have some mode to make this late linking procedure? If not, how can I achieve dynamic code loading which I outlined above?

You can use the '-R filename' or '--just-symbols=filename' command options in ld. It reads symbol names and their addresses from filename, but does not relocate it or include it in the output. This allows your output file to refer symbolically to absolute locations of memory defined in your system.elf program.
(refer to ftp://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html).
So here filename will be 'system.elf'. You can compile extra.c with GCC normally including services.h but without linking and generate 'extra.o' then call ld as below:
ld -R"system.elf" -o"extra.out" extra.o
The 'extra.out' shall have your symbols linked. You can use objdump to compare contents of both 'extra.out' and 'extra.o'.
Note that you can always pass the start address of your program to the ld (e.g. -defsym _TEXT_START_ADDR=0xAAAA0123) as well as start address of other memory sections like bss,data. (i.e. -Tbss, -Tdata)
Be careful to use a valid address that does not conflict with your 'system.elf' as ld will not generate error for that. You can define new areas for the loaded code+data+bss in your original linker script and re-compile the system.elf then point the start addresses to your defined areas while linking 'extra.o'.

Related

What do link editor (LD) params mean?

I write NASM (netwide assembler) program and for some reasons I needed to use some functions written in C. So, I tried to link compiled C object files with compiled Assembly objects using ld link editor. I did it by this way :
ld -m elf_x86_64 -lc --dynamic-linker=/lib64/ld-linux-x86-64.so.2 object_files -o program.
And it didn't want to link and work long enough until I picked up the necessary parameters. Now this works as expected with this parameter set. But I don't understand the meaning of -lc and --dynamic-linker=/lib64/ld-linux-x86-64.so.2. What do they do ?
-lc - link c standard library
--dynamic-linker=/lib64/ld-linux-x86-64.so.2. - set the program loader. Linux ELF binaries have a field for this.
Afaik the latter is needed even for static binaries, anything other will confuse the loader, and it won't execute.
man ld lists its parameters.

How to generate symbol table with arm gcc

I would like to create a symbol definition table to be used in a separate application during linking. ARM's armlink linker has the following flag but I'm using arm-eabi:
--symdefs=filename
The GNU objcopy utility has an option --extract-symbol that may do what you want. It generates an object file with only symbol data - no actual code or data.
It is specifically intended to generate a .sym file for use in the VxWorks RTOS which has a command shell and dynamic linker/loader that uses this information. It is also used by the VxWorks host shell and source-level debugger.
The binutils nm utility on the other hand generates output very similar to armlink's --symdefs which you might easily post-process into exactly the form you need.
-Wl,-Map -Wl,mapfile -Wl,--cref
added to the final gcc (link) command line should do the trick.
This the correct answer from arm gnu launchpad:
Do you intend to load the symdef file with the GNU toolchain or with armcc one? If the former I think using nm on the object file and then linking with -R <filename> would work. So you would do arm-none-eabi-nm -D ./prog > ./prog.defsym after linking prog and then arm-none-eabi-gcc -Wl,-R,./prog.defsym when you want to use this.

Two ways of linking to static libraries

Here are a couple of ways to use functions from a static library, built with ar (i.e. libSOMTEHING.a):
ld -o result myapp.o -Lpath/to/library -lname
ld -o result myapp.o path/to/library/libname.a
Since we omit any dynamic libraries from the command line, this should build a static executable.
What are the differences? For example, are the whole libraries linked in the executable, or just the needed functions? In the second example, does switching the places of the lib and the object file matter?
(PS: some non-GNU ld linkers require all options like -o to be before the first non-option filename, in which case they'd only accept -L... -lname before myapp.o)
In the first line, a search for a dynamic library (libname.so) occurs before the static library (libname.a) within a directory. Also, the standard lib path is also searched for libname.*, not just /path/to/library.
From "man ld"
On systems which support shared libraries, ld may also search for
files other than libnamespec.a. Specifically, on ELF and SunOS
systems, ld will search a directory for a library called
libnamespec.so before searching for one called libnamespec.a. (By
convention, a ".so" extension indicates a shared library.)
The second line forces the linker to use the static library at path/to/lib.
If there is no dynamic library built (libname.so), and the only library available is path/to/library/libname.a, then the two lines will produce the same "result" binary.

How to force gcc to link like g++?

In this episode of "let's be stupid", we have the following problem: a C++ library has been wrapped with a layer of code that exports its functionality in a way that allows it to be called from C. This results in a separate library that must be linked (along with the original C++ library and some object files specific to the program) into a C program to produce the desired result.
The tricky part is that this is being done in the context of a rigid build system that was built in-house and consists of literally dozens of include makefiles. This system has a separate step for the linking of libraries and object files into the final executable but it insists on using gcc for this step instead of g++ because the program source files all have a .c extension, so the result is a profusion of undefined symbols. If the command line is manually pasted at a prompt and g++ is substituted for gcc, then everything works fine.
There is a well-known (to this build system) make variable that allows flags to be passed to the linking step, and it would be nice if there were some incantation that could be added to this variable that would force gcc to act like g++ (since both are just driver programs).
I have spent quality time with the gcc documentation searching for something that would do this but haven't found anything that looks right, does anybody have suggestions?
Considering such a terrible build system write a wrapper around gcc that exec's gcc or g++ dependent upon the arguments. Replace /usr/bin/gcc with this script, or modify your PATH to use this script in preference to the real binary.
#!/bin/sh
if [ "$1" == "wibble wobble" ]
then
exec /usr/bin/gcc-4.5 $*
else
exec /usr/bin/g++-4.5 $*
fi
The problem is that C linkage produces object files with C name mangling, and that C++ linkage produces object files with C++ name mangling.
Your best bet is to use
extern "C"
before declarations in your C++ builds, and no prefix on your C builds.
You can detect C++ using
#if __cplusplus
Many thanks to bmargulies for his comment on the original question. By comparing the output of running the link line with both gcc and g++ using the -v option and doing a bit of experimenting, I was able to determine that "-lstdc++" was the magic ingredient to add to my linking flags (in the appropriate order relative to other libraries) in order to avoid the problem of undefined symbols.
For those of you who wish to play "let's be stupid" at home, I should note that I have avoided any use of static initialization in the C++ code (as is generally wise), so I wasn't forced to compile the translation unit containing the main() function with g++ as indicated in item 32.1 of FAQ-Lite (http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html).

Different ways to specify libraries to gcc/g++

I'd be curious to understand if there's any substantial difference in specifying libraries (both shared and static) to gcc/g++ in the two following ways (CC can be g++ or gcc)
CC -o output_executable /path/to/my/libstatic.a /path/to/my/libshared.so source1.cpp source2.cpp ... sourceN.cpp
vs
CC -o output_executable -L/path/to/my/libs -lstatic -lshared source1.cpp source2.cpp ... sourceN.cpp
I can only see a major difference being that passing directly the fully-specified library name would make for a greater control in choosing static or dynamic versions, but I suspect there's something else going on that can have side effects on how the executable is built or will behave at runtime, am I right?
Andrea.
Ok, I can answer myself basing on some experiments and a deeper reading of gcc documentation:
From gcc documentation: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
[...] The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with lib' and.a' and searches several directories
This actually answers also to the related doubt about the 3rd option of directly specifying object files on the gcc command line (i.e. in that case all the code in the object files will become part of the final executable, while using archives, only the object files that are really needed will be pulled in).

Resources