Different symbol tables in different versions of gcc causing wrong linkages - c

I am trying to compile a piece of code that links several source files with a shared library. This is to avoid a name conflict with a function named Log in both the source code and shared library.
The signature in my source code is Log(int, char *, char *, ...) and the signature in the shared library is Log(int, int, char *, ...)).
The code needs to be built for different targets. When built using gcc-5.4.0 (Ubuntu 16.04), there is no conflict and the shared library correctly calls the Log function from the shared library. However when building on gcc-4.9.2 for armhf (BeagleBoneBlack), the shared library calls the Log function in my source code which is incorrect.
Specifically, the output of the nm command applied to the executable generated using gcc-4.9.2 shows the first entry in the dynamic symbol table as follows:
$ nm -D <filename>
00017590 T Log
.....
This entry for Log does not appear when compiling with gcc-5.4.0.
I have tried using objcopy for substituting the Log symbol name while the .so file is generated, but that doesn't work.
Is there some setting or flag in the Makefile that needs to be added so that any version of gcc should not add the Log function to the dynamic symbols of my final executable? Or is there something else that I am missing here?
Reproducing the Makefile settings:
CFLAGS=-fPIC -MMD -Wall -std=c99 -D_GNU_SOURCE -g -Werror=implicit
CPPFLAGS=-Iinclude
CFLAGS+=-Os -fdata-sections -ffunction-sections -flto
CPPFLAGS+=-Os -fdata-sections -ffunction-sections -flto
LDFLAGS=-Os -Wl,--gc-sections -flto

Related

Calling functions from an external C file that has its own main()

I have two C files, program.c and tests.c, that each contain a main function.
program.c is a standalone program, that compiles and run normally on its own. But I would like to also be able to use some of its functions in tests.c (without using a common header file). Is there a way of doing this?
If I insert the prototype of the function I want from program.c into tests.c and compile with:
gcc -o program.o -c program.c
gcc -o tests.o -c tests.c
gcc -o tests tests.o program.o
I obtain an error duplicate symbol _main, which I understand since there are indeed two `main' functions.
I basically would like to be able to treat program.c both as a standalone program and as a library, similarly to what could be done in Python with if __name__ == '__main__'.
If you need to have two separate distinct executables for which some of the functionality between them is similar you can share the common functionality by placing relevant functions into a third file, and compiling as a portable executable, DLL in Windows. (or shared library in Linux.) Each of these file types contain sharable, executable code, ithout the main() function, designed to be linked during compile time, and dynamically loaded into your executable at runtime.
Here is a step by step set of instructions for shared library using GCC and Linux.
Here is a step by step example for creating DLL using GCC in windows.
So I managed to achieve what I wanted thanks to the comment from #pmg:
I compile program.c into a standalone binary (gcc -o program program.c), but I also compile it into an object file with "main" renamed (gcc -c -Dmain=mainp -o program.o program.c).
I can then use this object file (that does not contain a "main" symbol anymore) to compile tests.c: gcc -o tests tests.c program.o.
Thanks #pmg, I did not know this use of the -D option.

C pluginsystem: symbol lookup error

I am writing a plugin system which is separated other 3 modules:
plugin_system.c - the core of the system
list.c - contains a linked list implementation for plugins' storage
plugin_interface.h - contains the declaration needed by plugins, has no source file associated with
plugin_interface.h only contains only of types and the function:
extern int plugin_register(PluginManager *plug_manager, const char *name, Plugin *plug);
which is defined in plugin_system.c
When loading a plugin, the plugin system look for a funcion init_plugname() and call it, that function must call plugin_register to register the plugin.
The program is compiled with complex recursive Makefiles (not the best idea), but what I try to achieve is:
I compile the plugin system object in the main program folder, it is then linked with the main program. From make execution:
gcc -Wall -O2 -std=gnu99 -D DEBUG -g -fPIC -c -o /home/kowa/code/reseaux/projet/ringo/c/bin/list.o list.c
gcc -Wall -O2 -std=gnu99 -D DEBUG -g -fPIC -c -o /home/kowa/code/reseaux/projet/ringo/c/bin/plugin_system.o plugin_system.c
A plugin is compiled with gcc -fPIC -c -o plugname.o plugname.c plug_system.o followed by gcc -o plugname.so plugname.o plug_system.o -shared
I try to load the plugin in my main program and get this error:
symbol lookup error: ./plugins/zyva.so: undefined symbol: exists
exists is a function in the list module used by the plugin_system module to store plugins, the plugin_register function mentionned aboved calls it.
I've never done that kind of system before and I'm not an expert in shared library, I guess the problem is from how I compile the whole project, I may miss some linkage...
I just forgot to link the plugin with list.o which is used by the plugin_system.o...

_sbrk function not found when placed in a static library

I'm creating a bare-metal application for the stm32f407 microcontroller, which has an ARM Cortex M4 core. As such, I'm delivering the implementation of functions like _sbrk myself. I now find that when I try to create a static library containing _sbrk, and link it with my main.c into an application, the linker says
"c:/progra~2/gnutoo~1/4947e~1.920/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/softfp\libg_nano.a(lib_a-sbrkr.o): In function _sbrk_r: sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'".
If I take that same function out of the static library, and put it into main.c, everything compiles/links/runs just fine.
I am almost certain that this has something to do with the order in which the linker reads in all libraries, and that when my own static library is read, no definition of _sbrk is required yet, and is therefore thrown out, only to find that it was needed anyway when later one of the standard libraries is linked in. However, I do not specify any standard libraries myself, and can therefore not change the order of linking those libraries. I also tried to declare the _sbrk function as __attribute __ ((__ used__ )), thinking that the linker would not throw away that function, but alas, this has not solved my problem.
So my question is, how can I put _sbrk into a static library, without running into unresolved references?
Update: The command to link the final application is:
C:\PROGRA~2\GNUTOO~1\4947E~1.920\bin\AR10B2~1.EXE -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -fno-rtti -fno-exceptions -std=c++11 -fno-use-cxa-atexit -fno-threadsafe-statics -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -Wl,--gc-sections -nostartfiles -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/mem.ld" -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/sections.ld" "CMakeFiles\http_server.http_server.dir\src\main.cpp.obj" "CMakeFiles\http_server.http_server.dir\src\vectors_stm32f4xx.c.obj" "CMakeFiles\http_server.http_server.dir\http_server.http_server_linker_script_dummy.c.obj" -o "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\http_server.http_server\Generic-stm32f4xx\bin\http_server.http_server.elf" "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
Where AR10B2~.EXE resolves to arm-none-eabi-g++.exe.
Adding the following makes the thing link:
-lc -lg "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
Th libcmsis_stm.cmsis_stm.a library is built with the following command:
C:\PROGRA~2\GNUTOO~1\4947E~1.920\bin\ARM-NO~2.EXE cq "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a" CMakeFiles/cmsis_stm.cmsis_stm.dir/src/cmsis/system_stm32f4xx.c.obj
Where ARM-NO~2.EXE resolves to arm-none-eabi-ar.exe
So one question remains: I would like to place the interrupt vector table, which is a variable, into the static library, but the linker throws that variable away because no source file needs that variable. Is there a mechanism to keep that variable until the linker processes the output sections in the linker file?
When ld links against a library, it will only pick those functions which are required at that time (because of references to functions from translation units which have been linked in before). The linker will forget all other functions (and the library won't be considered later).
Therefore the linking order does matter. Normally you would link in your application object file (which references malloc), then the standard library (which provides malloc and in turn references _sbrk), and then your (application) library which provides _sbrk.
So linking should look like
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -lm -lapp
with the _sbrk function being provided by libapp.
So the order of the objects to be linked does matter.
Update
As stated in one of the comments: If you add debug symbols using -g during compilation, then you have to link against libg as well (-lg).
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -g -lm -lapp

How to link and compile with .so file in Linux

I am having .c and .so file. I tried by using the following compilation: gcc main.c -ldl. In that .c file i linked to .so file through dlsym(). How to compile using .so file with .c.
Probably you can do this:
when linking do:
g++ -o prog prog.o -ldllname
If libdllname.so is not in the system directory then add its directory to the library path:
g++ -o prog prog.o -L/path/to/my/library/folder -ldllname
This is based on your further comments. First guard the declarations of your header file.
#ifndef HEADER_PROTECT
#define HEADER_PROTECT
---------- Here is the content of header
#endif
Next, check in your code, are you defining multiple definitions. Or are you re-defining the standard functions again? Can you please post your code to guide you better?
Looks like you have re-defined Close_Comm(), can you check it? Error says that the definition is there in main.c also.
The following is the general way to compile shared object and link it.
To compile shared objects.
-g : for debug information
fPIC: for position independent code
$gcc -fPIC -g myfile
The following will create the shared object libmyfile.so
$gcc -shared -o libymyfile.so myfile.o
Now,In order to link it with your main.c.
I assume that the libmyfile.so is in your current path, thus -L./
$gcc main.c -o main.out -L./ -lmyfile
Now, you need to export the LD_LIBRARY_PATH on the bash; in order to execute the binary.
$LD_LIBRARAY_PATH=$LD_LIBRARAY_PATH:./
$./main.out
The dlsym is to load the symbol from the shared object at the run-time. If you want to load the shared object at run time, this can be used. The following is one of the example of dlsym Hack the standard function in library and call the native library function afterwards
dlsym() is used to find a symbol in an open library file.
you first need to use dlopen() in order to open the file, and only then use dlsym()

Static library symbols not being found even with -l

I have a static library, liborc-0.4.a with no shared library. I have another library, libschroedinger-1.0.a (no shared) that depends on symbols in liborc-0.4.a. If I run nm on liborc-0.4.a, symbols such as orc_init show up as T (meaning they are defined). I built libschroedinger-1.0.a with the command line flag -lorc-0.4 so it saw the symbols and was ok.
However, now I have a small executable that depends on libschroedinger-1.0.a. It compiles fine, but when I run the linker
gcc -lschroedinger-1.0 -lorc-0.4 -o output input.o
It gives errors such as:
/usr/local/lib/libschroedinger-1.0.a(libschroedinger_1.0_la-schro.o):schro.c:(.text+0x21):
undefined reference to `orc_init'
gcc is sensitive to the order of libraries. When it's compiling liborc-0.4.a in, there is no need for orc_init, so it's not included. The solution is to put the LDFLAGS at the end of the command:
gcc -o output input.o -lschroedinger-1.0 -lorc-0.4
You most probably compiled libschroedinger with shared liborc. Static library is the same as bunch of object files in an archive, so they don't need to see more than headers. Write like the following to be sure (the same apples to liborc).
gcc /path/to/libschroedinger-1.0.a /path/to/liborc-0.4.a -o output input.o

Resources