Why my shared object does not compile without -fPIC - c

I wrote a simple shared lib which contains the usage of stdout in stdio.h.
#include <stdio.h>
...
fflush(stdout);
...
There was no compilation issue before I added the fflush(stdout) with the command below
$gcc -shared -o a.so a.c
But after adding the fflush(stdout), compiler complains:
/usr/bin/ld: /tmp/ccK4npwc.o: relocation R_X86_64_PC32 against symbol `stdout##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
Can someone explain the rationale behind this with as much detail as possible? why does it have to be -fPIC here?
EDIT:
Some comments suggest I read on PIC, but that is missing my question. My question is why do I need PIC for this program. In my program, I also uses puts which is from libc. I can compile it fine without -fPIC. But why is -fPIC required with the stdout variable?

Related

/usr/bin/ld: cannot find -lRTU_Module Linux / Shared library C code

I have a problem compiling the following line of code :
gcc -o main.c -ldl -lpthread -lRTU_Module main.o
I have the following error message :
/usr/bin/ld: cannot find -lRTU_Module
collect2: error: ld returned 1 exit status
When i try to find the location of my .so it returns this :
locate libRTU_Module.so
/home/owasys/workspace/AccelTest/libRTU_Module.so
/home/owasys/workspace/Compiler_gcc-linaro-5.3_patch/files/lib/libRTU_Module.so
/home/owasys/workspace/Compiler_gcc-linaro-5.3_patch/files/lib/libRTU_Module.so.1.0.11
/opt/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/libRTU_Module.so
/opt/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/libRTU_Module.so.0
/opt/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/libRTU_Module.so.0.0.0
/opt/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/libRTU_Module.so.1.0.11
I have red multiple of answer to a similar question but i have not solve my problem.
Thank you.
ld normally scans a default/configured set of dirs, generally wouldn't know about custom stuff like /home/a/b/c
Should be easy enough to fix; does this work?
dir=/home/owasys/workspace/Compiler_gcc-linaro-5.3_patch/files/lib
gcc -o main.c -ldl -lpthread -lRTU_Module.so main.o -L $dir
May need to tell the runtime link editor to search there as well, eg adding this to gcc cmd-line:
-Wl,-rpath=$dir

C compiler gcc gives linker command failed error [duplicate]

I'm getting the following error and can't for the life of me figure out what I'm doing wrong.
$ gcc main.c -o main
Undefined symbols:
"_wtf", referenced from:
_main in ccu2Qr2V.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
main.c:
#include <stdio.h>
#include "wtf.h"
main(){
wtf();
}
wtf.h:
void wtf();
wtf.c:
void wtf(){
printf("I never see the light of day.");
}
Now, if I include the entire function in the header file instead of just the signature, it complies fine so I know wtf.h is being included. Why doesn't the compiler see wtf.c? Or am I missing something?
Regards.
You need to link wtf with your main. Easiest way to compile it together - gcc will link 'em for you, like this:
gcc main.c wtf.c -o main
Longer way (separate compilation of wtf):
gcc -c wtf.c
gcc main.c wtf.o -o main
Even longer (separate compilation and linking)
gcc -c wtf.c
gcc -c main.c
gcc main.o wtf.o -o main
Instead of last gcc call you can run ld directly with the same effect.
You are missing the fact that merely including a header doesn't tell the compiler anything about where the actual implementation (the definitions) of the things declared in the header are.
They could be in a C file next to the one doing the include, they could come from a pre-compiled static link library, or a dynamic library loaded by the system linker when reading your executable, or they could come at run-time user programmer-controlled explicit dynamic loading (the dlopen() family of function in Linux, for instance).
C is not like Java, there is no implicit rule that just because a C file includes a certain header, the compiler should also do something to "magically" find the implementation of the things declared in the header. You need to tell it.

Relocation R_X86_64_PC32 against symbol when calling function from inline assembly

I am trying to build shared libraries that has some functions in assembly that call other functions. When I build liba.so with code
void aFunc1()
{
}
asm(
".globl aFunc2\n\t"
".type aFunc2, #function\n\t"
"aFunc2:\n\t"
".cfi_startproc\n\t"
"call aFunc1\n\t" /* note here*/
"ret\n\t"
".cfi_endproc\n\t"
);
and command
gcc -o liba.so a.c -shared -fPIC
I got error
/usr/bin/ld: /tmp/ccdGBiQv.o: relocation R_X86_64_PC32 against symbol `aFunc1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
It tells me to use option -fPIC but I just already use that option! However I find out that with option -Wl,-Bsymbolic it compiles fine.
gcc -o liba.so a.c -shared -fPIC -Wl,-Bsymbolic
Unfortunately problem comes back when I try build second library libb.so also with assembly functions that try call functions from first library. Compiling code
#include <a.h>
asm(
".globl bFunc2\n\t"
".type bFunc2, #function\n\t"
"bFunc2:\n\t"
".cfi_startproc\n\t"
"call aFunc1\n\t" /* note here*/
"ret\n\t"
".cfi_endproc\n\t"
);
with command
gcc -o libb.so b.c liba.so -shared -fPIC -Wl,-Bsymbolic
gives error
/usr/bin/ld: /tmp/ccaGvn5d.o: relocation R_X86_64_PC32 against symbol `aFunc1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
and as you can see option -Wl,Bsymbolic doesn't help.
I want to know how to build second library and why first library needs -Wl,Bsymbolic option. I am not assembly master so I don't know if it is correct — I'm trying to build someone else library. Maybe I should use other options?
You need to call either the PLT stub because the function could have been interposed (making the call no longer direct, with a fixed offset):
call aFunc1#plt
With -Bsymbolic, the linker will turn this into a call to aFunc1 (without the double indirection).
You can also call the function via the GOT, similar to what the PLT stub does:
jmp *aFunc1#GOTPCREL(%rip)
Or you can make the function hidden:
.hidden aFunc1
jmp aFunc1
Note that his will make the definition hidden as well, so the function is no longer exported. To emulate the behavior of -Bsymbolic for a single symbol, you can use a hidden alias:
.set aFunc1Alias, aFunc1
.hidden aFunc1Alias
jmp aFunc1Alias
With the hidden function and the hidden alias, the call will always go to the same function, i.e., it is no longer possible to interpose the symbol for this particular call site.

Recompile with -fPIC issue

I have following c program
#include <stdio.h>
int main()
{
printf("hello');
return 0;
}
When I compile this file
gcc -c rr2.c
and then use linker with shared option like
/ld-new -shared -o tmpdir/dump rr2.o
It gives the following error
rr2.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
I don't understand why this error occurs. Can anyone help me to understand actually why this error is appearing?
Dynamic shared "objects" do not have fixed addresses they are loaded into memory. That means all references to function and variables have to be position independent. You have to create Position Independent Code (or PIC for short).
This is done, as suggested by the linker, by adding the -fPIC flag when compiling:
> gcc -fPIC -c rr2.c

Undefined symbols error when using a header file

I'm getting the following error and can't for the life of me figure out what I'm doing wrong.
$ gcc main.c -o main
Undefined symbols:
"_wtf", referenced from:
_main in ccu2Qr2V.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
main.c:
#include <stdio.h>
#include "wtf.h"
main(){
wtf();
}
wtf.h:
void wtf();
wtf.c:
void wtf(){
printf("I never see the light of day.");
}
Now, if I include the entire function in the header file instead of just the signature, it complies fine so I know wtf.h is being included. Why doesn't the compiler see wtf.c? Or am I missing something?
Regards.
You need to link wtf with your main. Easiest way to compile it together - gcc will link 'em for you, like this:
gcc main.c wtf.c -o main
Longer way (separate compilation of wtf):
gcc -c wtf.c
gcc main.c wtf.o -o main
Even longer (separate compilation and linking)
gcc -c wtf.c
gcc -c main.c
gcc main.o wtf.o -o main
Instead of last gcc call you can run ld directly with the same effect.
You are missing the fact that merely including a header doesn't tell the compiler anything about where the actual implementation (the definitions) of the things declared in the header are.
They could be in a C file next to the one doing the include, they could come from a pre-compiled static link library, or a dynamic library loaded by the system linker when reading your executable, or they could come at run-time user programmer-controlled explicit dynamic loading (the dlopen() family of function in Linux, for instance).
C is not like Java, there is no implicit rule that just because a C file includes a certain header, the compiler should also do something to "magically" find the implementation of the things declared in the header. You need to tell it.

Resources