undefined reference on lib.a with symbol in the lib - linker

I'm new in managing lib, so I want to understand why I recieved an
libcrypto.a(e_aesgcmsiv.c.o):e_aesgcmsiv.c:(.text+0x1a4) : undefined reference to « aes128gcmsiv_aes_ks »
when I link my executable with libcrypto.a
For checking what is in my libcrypto.a I try to nm the static lib and I see this things (in this order) :
aes128gcmsiv-x86_64.asm.o:
0000000000000510 T aes128gcmsiv_aes_ks
...
000000000000051d t L$SEH_begin_aes128gcmsiv_aes_ks
...
00000000000005f5 t L$SEH_end_aes128gcmsiv_aes_ks
e_aesgcmsiv.c.o:
...
000000000000159f t aead_aes_gcm_siv_seal_scatter
U aes_ctr_set_key
U aes128gcmsiv_aes_ks
...
So if I understand correctly, my libcrypto.a contains in aes128gcmsiv-x86_64.asm.o the function aes128gcmsiv_aes_ks.
And in e_aesgcmsiv.c.o I would to use the function which is undefined in the scope of this .o file.
But because everything is in my lib I can't understand why I recieved an undefined reference.
If it could help the file e_aesgcmsiv.c contains this :
extern void aes128gcmsiv_aes_ks(
const uint8_t key[16], uint8_t out_expanded_key[16*15]);
And later it use the function.
PS : I don't paste the asm file that contains the real code of the function but I think it's not revelant cause you can see that it's present in the lib.
EDIT : I find a workaround (I link the aes128gcmsiv-x86_64.asm.o file before my libcrypto.a, with that the function is known).
But It's not the answer to my question : why it doesn't work automatically with all informations in the lib.a

Related

How to solve "Undefined reference to function" in Eclipse CDT?

I did setup a C project with Eclipse Photon (4.8.0) for developing a program for the ESP-32. I did configure the IDE according to this official setup instructions.
Flashing the ESP-32 works fine. But as soon as I try to include header files from a sub folder, I run into troubles. I have set up a very simple project to illustrate the issue. The project consists of main.c, base/test.h and base/test.c, whereas the test.h and test.c files only contain one function with the signature void function1(void);.
When I try to call function1() in main.c, I get this error in main.c:
Undefined reference to function1()
Please compare to the attached screenshot, where everything is depicted.
How to solve this issue?
This is not a compiler, but rather a linker error.
Note, with #includeing a header file, you only make the external function known to the compiler. You also need to link to the external function during the linking stage. Make sure you include the compiled object file that contains function1 into the link.
Seems like you need to do proper linking.
If you are linking with a library, you need to specify:
The name of the library: Project\Settings\C C++ General\Paths and Symbols\Libraries
Location where the linker should search for this library:
Project\Settings\C C++ General\Paths and Symbols\Library Paths
Important: see Note.
If you are linking with object files, add those to:
Project\Settings\C C++ Build\Settings\Linker\Miscellaneous\Other objects
Note:
If your library name is, for example, libsomething.a, than you need to specify only something as the name; so omit lib prefix and .a suffix.
If your library is not prefixed with lib, then you need to add its name prefixed with :. For example, something.a should be added as :something.a.

Contiki: undefined reference to a function defined in a separate source file

I am writing a program using the Contiki operating system.
I have the remote_firmware.c file and a folder called parser with the files parser.h and parser.c where I wrote the method void test(). I included parser.h in remote_firmware.c with:
#include "parser/parser.h"
The Makefile looks like this:
CONTIKI_PROJECT = remote_firmware
all: $(CONTIKI_PROJECT)
#UIP_CONF_IPV6=1
CONTIKI_WITH_RIME = 1
CONTIKI = $(HOME)/contiki
include $(CONTIKI)/Makefile.include
When I try to build this the Error occurs:
undefined reference to 'test'
I am aware that the Makefile needs to know about parser.h, but I do not know how. I tried several solutions which were proposed here but I guess I did something wrong. Maybe somebody of you know what to do?
Thank you a lot.
Where is your source file located? Try adding the source file name to the PROJECT_SOURCEFILES preprocessor variable (i.e PROJECT_SOURCEFILES+=parser.c) and adding the location of the source file to the CONTIKIDIRS preprocessor variable (i.e CONTIKIDIRS+={Directory}).
If parser.c depends on a lot other C files you might want create an C library archive first and then adding the library to your project by adding the name of the library to the TARGET_LIBFILES variable.
The error undefined reference to test is an error from the linker not the compiler. It has nothing to do with including a header file. It means when you linked the executable you didn't include parser.o

Why do I get 'multiple definition' errors when linking against an archive?

I'm using CppUTest to test the C code defined in a fornol.c source file. That file defines the main production main() function.
I also have an AllTests.cpp file that also has a main() function, but that main() is supposed to be used only when running the unit tests.
AllTests.cpp gets compiled to a .o file, whereas fornol.c gets compiled to a libfornol.a archive.
Then CppUTest tries to link everything together, but here is what I get instead:
Linking fornol_tests
cc -o fornol_tests objs/tests/AllTests.o objs/tests/FornolTests.o lib/libfornol.a ../../CppUTest/lib/libCppUTest.a ../../CppUTest/lib/libCppUTestExt.a -lstdc++ -lgcov
lib/libfornol.a(fornol.o): In function `main':
/home/dlindelof/Work/endor/nol/fornol/fornol.c:453: multiple definition of `main'
objs/tests/AllTests.o:/home/dlindelof/Work/endor/nol/fornol/tests/AllTests.cpp:4: first defined here
collect2: ld returned 1 exit status
It looks as if the main() function defined in fornol.c and present in the archive libfornol.a conflicts with the main() defined in AllTests.cpp. But my understanding was that archive/library files are searched only if/when a given symbol hasn't been referenced yet. It should therefore not be a problem to have the same symbol defined more than once, provided all definitions are in archive/library files.
What am I doing wrong here?
You need to remove the main() from AllTests.cpp and put it in its own source file.
When a linker links in a library, it can't split object files in the library; it has to either link or omit each object file in the library as a unit. (I know LLVM is different, but that's another topic.) This is why, if you look at the source for a library like glibc, each function gets its own source file.
So what's happening to you is that the linker needs to pull in an object file (fornol.o) from the library (libfornol.a) to satisfy dependencies, but that object file carries a duplicate symbol with it (main).
It's perfectly okay to put test code in a library (we do this routinely where I work), but keep it in its own source files (we traditionally use main.cc). (This is a better test anyway, because test code should not have access to static-declared symbols.)
A library is supposed not to have a main() function as it is a library.
You should remove that main() from fornol.c and compile it again.
main() is the entry point of an executable file's source code, since a library (especially a static ".a" library) is only pre-compiled source code, you cannot use a main in there.
If you want a main production entry point of your library you could rename the main() in fornol.c to something more explicit and less reserved such as "fornolMain()" for example.
A static library is compiled in your binary executable and thus is not searched only if the symbol is loaded. It is exactly the same as compiling fornol.c and linking fornol.o and your other .o

extern linking problems in Microsoft Visual Studio

I have two libs that share a extern variable.
In libA I have the variable declared in the header as such:
extern int Gbl;
then I define it again in the source as:
int Gbl;
next then I set Gbl=1;
in libB, I include libA's header file. And printf Gbl, expecting to get 1 here.
though unfortunately i can't even compile this since I get the error:
undefined symbol '_Gbl' referenced in ....
I was told that this is a linking error, but I'm not sure what to do from here
You need to compile the libB with libA included. This is done by adding -llibA to the compile line. If you don't have library options set correctly, you need to add -lpath_to_library

Weak-linking with static libraries

I have declared an external function with a GCC weak attribute in a .c file:
extern int weakFunction( ) __attribute__ ((weak));
Compiled object file has weakFunction defined as a weak symbol.
Output of nm:
1791: w weakFunction
I am calling the weak defined function as follows:
if (weakFunction != NULL)
{
weakFunction();
}
When I link the program by defining the object files as parameters to GCC (gcc main.o weakf.o -o main.exe) weak symbols work fine. If I leave the weakf.o out of linking, the function address is NULL in main.c and the function won't be called.
Problem is, when weakf.o is inside a static library, for some reason the linker doesn't find the function and the function address always ends up being NULL.
Static library is created with ar: ar rcs weaklibrary weakf.o
Anyone had similar problems?
While I don't know the exact workings of weak symbols it looks like you are getting what you ask for: if no one else is forcing the weakFunction() to be present, main() won't either. To me this makes sense: if you are trying to write code which works with facility X present as well as without it, then you don't want your code to force X to be included in your build at all costs. It looks like "weak" is meant to ask if something is present, not to request that something is present.
Maybe you can force inclusion of weak symbols with "-u weakFunction" as linker option in your case.

Resources