How to match linker symbols for minimal Win32 linking with MinGW? - linker

I would like to make some Win32 API calls from within a Cygwin program, but I'm unable to import windows.h without problems with redefinitions. I don't need the entire header, but only a few select functions. So I thought I could just import those manually with identical declarations. But this doesn't seem to work.
Here is an example program where I try to import Sleep():
#define DECLSPEC_IMPORT __declspec(dllimport)
#define WINAPI __stdcall
#define WINBASEAPI DECLSPEC_IMPORT
typedef unsigned long DWORD;
WINBASEAPI void WINAPI Sleep(DWORD);
int main() {
Sleep(1);
return 0;
}
However, I am still unable to properly match the linker symbol:
$ nm -gC libkernel32.a | grep -i sleep
00000000 T SleepEx#8
00000000 I _imp__SleepEx#8
00000000 T Sleep#4
00000000 I _imp__Sleep#4
Linker error:
$ g++ main.cpp -o a.out -mwindows
/cygdrive/c/WINDOWS/TEMP/ccY6MURi.o:main.cpp:(.text+0x32): undefined reference to `__imp___Z5Sleepm#4'
collect2: ld returned 1 exit status
I don't have this problem if I #include <windows.h>. Even though I have matched the declarations exactly, why is the symbol different?

Why don't you just use #include <windows.h>? That's the proper way to do it.
You're linker error indicates the issue is related to the C++ calling convention. Have you tried with gcc instead of g++?
All those complexities should be covered if you just use #include <windows.h>.

Related

Error "undefined reference to symbol 'sqrt##GLIBC_2.17'" [duplicate]

I have this simple code:
max = (int) sqrt (number);
and in the header I have:
#include <math.h>
But application still says undefined reference to sqrt. Do you see any problem here? It looks like everything should be okay.
You may find that you have to link with the math libraries on whatever system you're using, something like:
gcc -o myprog myprog.c -L/path/to/libs -lm
^^^ - this bit here.
Including headers lets a compiler know about function declarations but it does not necessarily automatically link to the code required to perform that function.
Failing that, you'll need to show us your code, your compile command and the platform you're running on (operating system, compiler, etc).
The following code compiles and links fine:
#include <math.h>
int main (void) {
int max = sqrt (9);
return 0;
}
Just be aware that some compilation systems depend on the order in which libraries are given on the command line. By that, I mean they may process the libraries in sequence and only use them to satisfy unresolved symbols at that point in the sequence.
So, for example, given the commands:
gcc -o plugh plugh.o -lxyzzy
gcc -o plugh -lxyzzy plugh.o
and plugh.o requires something from the xyzzy library, the second may not work as you expect. At the point where you list the library, there are no unresolved symbols to satisfy.
And when the unresolved symbols from plugh.o do appear, it's too late.
I suppose you have imported math.h with #include <math.h>
So the only other reason I can see is a missing linking information. You must link your code with the -lm option.
If you're simply trying to compile one file with gcc, just add -lm to your command line, otherwise, give some informations about your building process.
Just adding the #include <math.h> in c source file and -lm in Makefile at the end will work for me.
gcc -pthread -o p3 p3.c -lm
Here are my observation, firstly you need to include the header math.h as sqrt() function declared in math.h header file. For e.g
#include <math.h>
secondly, if you read manual page of sqrt you will notice this line Link with -lm.
#include <math.h> /* header file you need to include */
double sqrt(double x); /* prototype of sqrt() function */
Link with -lm. /* Library linking instruction */
But application still says undefined reference to sqrt. Do you see any
problem here?
Compiler error is correct as you haven't linked your program with library lm & linker is unable to find reference of sqrt(), you need to link it explicitly. For e.g
gcc -Wall -Wextra -Werror -pedantic test.c -lm
I had the same issue, but I simply solved it by adding -lm after the command that runs my code.
Example.
gcc code.c -lm

undefined reference to `CreateRGBABitmapImageReference' [duplicate]

I would like to compile this.
program.c
#include <libavcodec/avcodec.h>
int main(){
int i = avpicture_get_size(AV_PIX_FMT_RGB24,300,300);
}
Running this
gcc -I$HOME/ffmpeg/include program.c
gives error
/tmp/ccxMLBme.o: In function `main':
program.c:(.text+0x18): undefined reference to `avpicture_get_size'
collect2: ld returned 1 exit status
However, avpicture_get_size is defined. Why is this happening?
However, avpicture_get_size is defined.
No, as the header (<libavcodec/avcodec.h>) just declares it.
The definition is in the library itself.
So you might like to add the linker option to link libavcodec when invoking gcc:
-lavcodec
Please also note that libraries need to be specified on the command line after the files needing them:
gcc -I$HOME/ffmpeg/include program.c -lavcodec
Not like this:
gcc -lavcodec -I$HOME/ffmpeg/include program.c
Referring to Wyzard's comment, the complete command might look like this:
gcc -I$HOME/ffmpeg/include program.c -L$HOME/ffmpeg/lib -lavcodec
For libraries not stored in the linkers standard location the option -L specifies an additional search path to lookup libraries specified using the -l option, that is libavcodec.x.y.z in this case.
For a detailed reference on GCC's linker option, please read here.
Are you mixing C and C++? One issue that can occur is that the declarations in the .h file for a .c file need to be surrounded by:
#if defined(__cplusplus)
extern "C" { // Make sure we have C-declarations in C++ programs
#endif
and:
#if defined(__cplusplus)
}
#endif
Note: if unable / unwilling to modify the .h file(s) in question, you can surround their inclusion with extern "C":
extern "C" {
#include <abc.h>
} //extern

Bash script error "undefined reference to sin" [duplicate]

I have this simple code:
max = (int) sqrt (number);
and in the header I have:
#include <math.h>
But application still says undefined reference to sqrt. Do you see any problem here? It looks like everything should be okay.
You may find that you have to link with the math libraries on whatever system you're using, something like:
gcc -o myprog myprog.c -L/path/to/libs -lm
^^^ - this bit here.
Including headers lets a compiler know about function declarations but it does not necessarily automatically link to the code required to perform that function.
Failing that, you'll need to show us your code, your compile command and the platform you're running on (operating system, compiler, etc).
The following code compiles and links fine:
#include <math.h>
int main (void) {
int max = sqrt (9);
return 0;
}
Just be aware that some compilation systems depend on the order in which libraries are given on the command line. By that, I mean they may process the libraries in sequence and only use them to satisfy unresolved symbols at that point in the sequence.
So, for example, given the commands:
gcc -o plugh plugh.o -lxyzzy
gcc -o plugh -lxyzzy plugh.o
and plugh.o requires something from the xyzzy library, the second may not work as you expect. At the point where you list the library, there are no unresolved symbols to satisfy.
And when the unresolved symbols from plugh.o do appear, it's too late.
I suppose you have imported math.h with #include <math.h>
So the only other reason I can see is a missing linking information. You must link your code with the -lm option.
If you're simply trying to compile one file with gcc, just add -lm to your command line, otherwise, give some informations about your building process.
Just adding the #include <math.h> in c source file and -lm in Makefile at the end will work for me.
gcc -pthread -o p3 p3.c -lm
Here are my observation, firstly you need to include the header math.h as sqrt() function declared in math.h header file. For e.g
#include <math.h>
secondly, if you read manual page of sqrt you will notice this line Link with -lm.
#include <math.h> /* header file you need to include */
double sqrt(double x); /* prototype of sqrt() function */
Link with -lm. /* Library linking instruction */
But application still says undefined reference to sqrt. Do you see any
problem here?
Compiler error is correct as you haven't linked your program with library lm & linker is unable to find reference of sqrt(), you need to link it explicitly. For e.g
gcc -Wall -Wextra -Werror -pedantic test.c -lm
I had the same issue, but I simply solved it by adding -lm after the command that runs my code.
Example.
gcc code.c -lm

Unable to access own custom global function of shared library in linux from other module in C

I have downloaded libgcrypt library source code and
added my own customize function inside one particular file.
Although compilation/build process of customized shared library is successful, and both nm and objdump show
the customized function is global, it nonetheless shows an error (undefined reference) at linking time.
Here is what I have done:
inside /src/visibility.c file, I have added my custom function,
void __attribute__((visibility("default"))) MyFunction(void)
{
printf("This is added just for testing purpose");
}
build process
./configure --prefix=/usr/local --disable-ld-version-script
sudo make install
nm and objdump command find this custom function as global inside shared library.
nm /usr/local/lib/libgcrypt.so | grep MyFunction
000000000000fbf0 T MyFunction
objdump -t /usr/local/lib/libgcrypt.so | grep MyFunction
000000000000fbf0 g F .text 0000000000000013 MyFunction
Here is my sample code to access my custom function.
//gcrypt_example_test.c
#include <stdio.h>
#include <gcrypt.h>
#include <assert.h>
int main()
{
MyFunction();
return 0;
}
export LD_RUN_PATH=/usr/local/lib
gcc gcrypt_example_test.c -o test -lgcrypt
/tmp/ccA0qgAB.o: In function `main':
gcrypt_example_test.c:(.text+0x3a2): undefined reference to `MyFunction'
collect2: error: ld returned 1 exit status
Edit 1:
I tried all possible way to include function prototype declaration inside header file (/src/gcrypt.h) as follows:
void __attribute__((visibility("default"))) MyFunction(void);
... or:
extern void __attribute__((visibility("default"))) MyFunction(void);
... or:
extern void MyFunction(void);
... or:
void MyFunction(void);
I am still getting the same error (undefined reference) although no build error results in all above cases.
Why is this happening, and what mistake am I making?
Although other global functions which are part of standard shared library and defined inside visibility.c (nm also shows T for those functions) are accessible, why is my customized global function (MyFunction) of the shared library still inaccessible? Thanks!
Any link or explanation to resolve this error will be highly appreciable.
From the GCC documentation (emphasis mine):
Some linkers allow you to specify the path to the library by setting LD_RUN_PATH in your environment when linking.
But, from the GNU ld man page:
-rpath=dir
Add a directory to the runtime library search path. This is used
when linking an ELF executable with shared objects. All -rpath
arguments are concatenated and passed to the runtime linker,
which uses them to locate shared objects at runtime. The -rpath
option is also used when locating shared objects which are needed
by shared objects explicitly included in the link; see the
description of the -rpath-link option. If -rpath is not used
when linking an ELF executable, the contents of the environment
variable "LD_RUN_PATH" will be used if it is defined.
Note that there is no mention at all of the link time library search path.
You need to compile/link with /usr/local/lib in the link time library search path:
gcc gcrypt_example_test.c -o test -L/usr/local/lib -lgcrypt
most likely cause of the problem:
The header file for the library has not been updated to include the prototype for the new function
I don't understand the reason behind why it is working now, but not before. Anyway, I found the way to make the code working after adding customized function inside standard library. This post may help others in future.
I first locate libgcrypt.so and then remove all versions of libgcrypt.so
locate libgcrypt.so
sudo rm /usr/local/lib/libgcrypt.so
sudo rm /usr/local/lib/libgcrypt.so.20
sudo rm /usr/local/lib/libgcrypt.so.20.2.2
then I delete the libgcrypt folder (which I had extracted for building library) to start fresh.
Again, I follow these steps
Step 0 : extract libgcrypt source code
Step 1 : add my custom function, inside /src/visibility.c file
void __attribute__((visibility("default"))) MyFunction(void)
{
printf("This is added just for testing purpose");
}
Step 2 : build library
export LD_RUN_PATH=/usr/local/lib
./configure --prefix=/usr/local --disable-ld-version-script
sudo make install
Step 3: Open another terminal to compile
export LD_RUN_PATH=/usr/local/lib
gcc gcrypt_example_test.c -o test -lgcrypt
Step 4 : run
./test
This is added just for testing purpose
This is working fine now as expected.
What I noticed that __attribute__((visibility("default"))) in function definition and --disable-ld-version-script during build process is very important to make the customized function global, elimination of any makes the customized function local inside shared library(.so) file.
Below changes are working at my end
visibility.h
#include <cstdio>
void __attribute__((visibility("default"))) MyFunction(void);
visibility.cpp
#include "visibility.h"
void MyFunction(void)
{
printf("This is added just for testing purpose");
}
library build command
gcc -shared -o libtest.so -Wall -Werror -fpic -I. visibility.cpp
test.cpp
#include <stdio.h>
#include <gcrypt.h>
#include <assert.h>
#include "visibility.h"
extern void MyFunction();
int main()
{
MyFunction();
return 0;
}
exe build command
gcc test.cpp -o test -I. -L. -ltest -lstdc++
My gcc version is 4.4.7
And of-course I did not try and install the lib under /usr/local/lib but kept it local for quick testing.

-rdynamic for select symbols only?

Scenario:
Executable loads shared object at run time via dlopen.
The shared object references some symbol (a function) that is actually compiled into the main executable.
This works fine if I add -rdynamic to gcc when linking the executable.
-rdynamic exports all non-static symbols of the executable. My shared object only needs a select few.
Question: Is there a way to achieve the effect of -rdynamic, but restricted the the few select symbols that I know are needed by my shared object?
Edit:
At least two people misunderstood the question, so I try to clarify:
This question is about exporting a symbol from the main executable.
This question is not about exporting a symbol from a dynamic library.
Here is a minimal example:
func.h, the common header file
#include <stdio.h>
void func(void);
main.c, the main executable code:
#include <dlfcn.h>
#include "func.h"
// this function is later called by plugin
void func(void) {
printf("func\n");
}
int main() {
void * plugin_lib = dlopen("./plugin.so", RTLD_NOW);
printf("dlopen -> %p, error: %s\n", plugin_lib, dlerror());
// find and call function "plugin" in plugin.so
void (*p)(void); // declares p as pointer to function
p = dlsym(plugin_lib, "plugin");
p();
return 0;
}
plugin.c, code for the plugin that is loaded at runtime:
#include "func.h"
void plugin()
{
printf("plugin\n");
func();
}
If I compile with
$ gcc -o main main.c -ldl
$ gcc -shared -fPIC -o plugin.so plugin.c
Then plugin.so cannot be loaded, because it references the symbol func, which cannot be resolved:
$ ./main
dlopen -> (nil), error: ./plugin.so: undefined symbol: func
Segmentation fault (core dumped)
I can convince the main executable to export all its global symbols by compiling with -rdynamic:
$ gcc -rdynamic -o main main.c -ldl
$ ./main
dlopen -> 0x75e030, error: (null)
plugin
func
But this fills the dynamic symbol table unnecessarily with all symbols.
(This dynamic symbol table can be inspected with nm -D main.)
The question is, how can I add only "func" to the dynamic symbol table of the main executable, and not everything.
Unfortunately it's harder to achieve this for executables. You need to generate a list of symbols that you want to export and then add -Wl,--dynamic-list=symfile.txt to LDFLAGS.
Here's example of how it's done in Clang (and here's the script they use to generate the symbols file).
You could do it with the visibility attribute of GCC.
Declare the function you need to export with __attribute__ ((visibility ("default"))) flag. Then compile your whole library passing -fvisibility=hidden argument to GCC.
For full explanation on this, refer to the following GCC documentation page.

Resources