When I make a shared library, a error occur - c

I made a shared library as the follow:
gcc -c output.c
gcc -shared -fPIC -o liboutput.so output.o
When output.c is the follow, it could work.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
return 1+2;
}
But, when output.c changed as the follow, a error occur.
//#include "output.h"
#include <stdio.h>
int output(const char* st) {
printf("%s\n", st);
return 1+2;
}
This is error message:
/usr/bin/ld: output.o: relocation R_X86_64_PC32 against undefined 符号 `puts##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: 最后的链结失败: 错误的值
collect2: error: ld returned 1 exit status
I want to know why and how to deal it. Thanks in advance.

You need to compile output.c as position independent code.
gcc -c -fPIC output.c
In the first version you have not called any library function. But in second one printf is being called. In general, compile all sources with -fPIC if you intend to build a shared library later.

Related

C library internal function names

How do I prevent namespace collisions in a library? Let's say I have a internal library function called foo(), that is not included in a public header, so the user doesn't know about this function. But foo() is used across multiple files and can't be declared static.
The Problem is, if the user now creates a function called foo(), there is an error. How do I prevent namespace collision (as the library author), without forcing the user to not use specific function names?
example.c
#include <stdio.h>
void foo() {
printf("my foo called");
}
int main() {
foo();
}
lib.c
#include <stdio.h>
void foo() {
printf("library foo() called\n");
}
output:
$ gcc -Wall -Wextra -Werror example.c example-lib.c
/usr/bin/ld: /tmp/cci3Dd3J.o: in function `foo':
example-lib.c:(.text+0x0): multiple definition of `foo'; /tmp/ccneOJjI.o:example.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
Edit
I now tried the following (with the same files):
$ gcc -Wall -Wextra -Werror example-lib.c -fpic -shared -o example-lib.so
$ gcc -Wall -Wextra -Werror example.c example-lib.so
And for some reason it works. Can anyone explain why?

How to use extern symbols in shared library in C

I am trying to compile following test files to create a shared library:
answer.c
#include <stdio.h>
#include "add.h"
extern int myvar();
int answer()
{
printf("\r\n myvar:%d \r\n", myvar());
setSummand(20);
return add(22); // Will return 42 (=20+22)
}
add.c
#include <stdio.h>
int gSummand;
void setSummand(int summand)
{
printf("1Library is initialized\n");
gSummand = summand;
}
int add(int summand)
{
return gSummand + summand;
}
I want to create a shared library from the 2 files "answer.c" "add.c", I am using following commands:
gcc -c answer.c -o answer.o
gcc -c add.c -o add.o
gcc -shared add.o answer.o -o libtest.so
However third command gives following error:
answer.o:answer.c:(.text+0x9): undefined reference to `myvar'
answer.o:answer.c:(.text+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `myvar'
collect2: error: ld returned 1 exit status
Same setup links successfully if I use the following command to create static library instead of dynamic. Therefore, I don't see any error if I try following command:
ar rcs libtest.a add.o answer.o
Want to know if I am missing here something. Also want to know how to use external symbols in shared library.
ELF shared libraries need to be position independent. They will be mapped into the executable's address space at an address that isn't known until run time. This means no absolute address call instructions, such as might be used to call myvar().
You need to specify -fpic when you compile the source into object files, when those object files will be placed into a shared library. This tells the compiler to generate code that does not use absolute addresses, etc. so it can be position independent.
Example main.c file to use this library:
extern int answer(void);
int myvar() { return 1; }
int main(void) { return answer(); }
Example without -fpic:
[test]$ gcc -c add.c
[test]$ gcc -c answer.c
[test]$ gcc -shared add.o answer.o -o libtest.so
/usr/bin/ld: add.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: answer.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
Example with -fpic:
[test]$ gcc -fpic -c add.c
[test]$ gcc -fpic -c answer.c
[test]$ gcc -shared add.o answer.o -o libtest.so
[test]$ gcc main.c libtest.so
[test]$ LD_LIBRARY_PATH=. ./a.out
myvar:1
1Library is initialized

Undefined references in GSL

I'm trying to link gsl in a small c program.
#include "stdlib.h"
#include "stdio.h"
#include "gsl/gsl_block_float.h"
#include "gsl/gsl_matrix_float.h"
int main(void)
{
gsl_matrix_float* m = gsl_matrix_float_alloc(2, 2);
gsl_matrix_float_fprintf(stdout, m, "%f");
}
I'm compiling with gcc -lgsl -lgslcblas -lm program.c. I've tried gcc $(pkg-config --cflags gsl) $(pkg-config --libs gsl) program.c as well, along with gsl-config. In every case, gcc returns
/tmp/cc1wKgXm.o: In function `main':
program.c:(.text+0x13): undefined reference to `gsl_matrix_float_alloc'
program.c:(.text+0x32): undefined reference to `gsl_matrix_float_fprintf'
collect2: error: ld returned 1 exit status
objdump --syms /usr/lib/libgsl.so | grep gsl_matrix_float returns the proper symbols, as does grepping my headers. Everything is in /usr/lib or /usr/include What am I doing wrong?
I got this from the ubuntu forums. The order of the arguments togcc might be the issue
gcc -o program program.c `gsl-config --cflags --libs`

netfilter queue undefined reference to `nfq_open'

I have writting this code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/netfilter.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
int main(int argc, char **argv)
{
struct nfq_handle *h;
printf("opening library handle\n");
h = nfq_open();
nfq_close(h);
exit(0);
}
and when I try to compile it says that:
/tmp/ccEv9MYS.o: In function `main':
test1.c:(.text+0x1a): undefined reference to `nfq_open'
test1.c:(.text+0x2a): undefined reference to `nfq_close'
collect2: ld returned 1 exit status
I tried checking if the library is found by gcc and it is (when I modifiy the incluse of libnetfilter_queue there is an error), I recompiled the library and made sur that the fonctions I'm calling are in in it.
If you have any clue thanks for helping
Icompile using this:
gcc -o test test1.c
I have also tried:
gcc -o test -lnetfilter_queue test1.c
gcc -o test -L/usr/local/lib test1.c
Well, from the gcc manual page, for the -llibrary linking option
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.
That says, the linker works from left to right, so need to put the dependent on left hand side.
You need to change your compilation statement to
gcc -o test test1.c -lnetfilter_queue

Include a source file in a C program

How can I include foo() function of foo.c in this small program (sorry for my noob question):
In my foo.h file:
/* foo.h */
#include <stdio.h>
#include <stdlib.h>
int foo(double largeur);
In foo.c:
/* foo.c */
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
int foo(double largeur)
{
printf("foo");
return 0;
}
And in main.c:
/* main.c */
#include <stdio.h>
#include <stdlib.h>
#include "foo.h"
int main(int argc, char *argv[])
{
printf("Avant...");
foo(2);
printf("Apres...");
return 0;
}
After compiling:
$ gcc -Wall -o main main.c
I get this error:
Undefined symbols: "_foo",
referenced from:
_main in ccerSyBF.o ld: symbol(s) not found collect2: ld
returned 1 exit status
Thanks for any help.
$ gcc -Wall -o main main.c foo.c
GCC doesn't know to look for foo.c if you don't tell it to :)
Creating a program in C requires two steps, compiling and linking. To just run the compiling part, use the -c option to gcc:
gcc -c main.c
This creates an object file, main.o (or main.obj on Windows). Similarly for gcc -c foo.c. You won't get the error message above at this stage. Then you link these two object files together. At this stage, the symbol foo is resolved. The reason you got the error message was because the linker couldn't find the symbol, because it was only looking at main.o and not foo.o. The linker is usually run from gcc, so to link your object files and create the final executable file main, use
gcc -o main main.o foo.o
You have to compile foo.c also because it is another module. Let me see how they do it in gcc:
$ gcc -Wall main.c foo.c -o main
You could also do this in your MakeFiles, like this:
APP_NAME = Foo
Foo_HEADERS = foo.h
Foo_FILES = main.c foo.c
If you're not so much familiar with MakeFiles i suggest you to take a look at Make Docs, but this is a simple example, APP_NAME sets the name of the compiled executable(in this case is Foo), Foo_HEADERS will set the headers used by your application, Foo_FILES you will set the source files of your applications, remember to put the APP_NAME(in this case Foo) at the beginning of _HEADERS and _FILES. I suggest you to use MakeFiles because they will organize you application build process and will be better for the end-user.

Resources