gcc -g conflicts with -fPIC? - gcc

Tested under CentOS 5.1 g++ 4.1.2 and 4.6.3 and 4.7.0, they all produce same results. How do I solve this? Basically I can't build llvm with Debug build.
[hidden]$ cat x.cpp
#include <iostream>
int main() {
}
[hidden]$ g++ -c -fPIC -g x.cpp
[hidden]$ objdump -r x.o | grep R_X86_64_32 | head -10
000000000000001c R_X86_64_32 .debug_frame
0000000000000044 R_X86_64_32 .debug_frame
000000000000006c R_X86_64_32 .debug_frame
0000000000000006 R_X86_64_32 .debug_abbrev
000000000000000c R_X86_64_32 .debug_str+0x0000000000000414
0000000000000011 R_X86_64_32 .debug_str+0x00000000000007f2
0000000000000015 R_X86_64_32 .debug_str+0x000000000000017b
0000000000000029 R_X86_64_32 .debug_line
000000000000002e R_X86_64_32 .debug_str+0x0000000000000422
0000000000000034 R_X86_64_32 .debug_str+0x0000000000000607

How do I solve this?
You don't have a problem to solve (you haven't shown any signs of the problem existing).
And no, -g and -fPIC are perfectly compatible and do not conflict with each other.

These are not dynamic relocations. They will be resolved at link time. This does not break -fPIC.
Remember there are two kinds of linking, static and dynamic. Static linking is done by the compiler/linker when you compile the final program binary from the object files, and dynamic linking is done by the OS (ld-linux.so in the case of linux).
To get a list of dynamic relocations, use objdump -R. It will only work on dynamically linked binaries, however (i.e. not .o files).

Related

Statically linking the dependencies of a shared object in linux

I'm trying to create a share object which has its own dependencies statically linked.
Here is an example:
/* File: add.c */
#include <stdio.h>
int add(int a, int b) {
printf("Adding: %d %d\n", a, b);
return a + b;
}
When I try to compile I get the following error:
$ gcc -g -shared -fPIC -o libadd.so add.c -Wl,-Bstatic -lc -Wl,-Bdynamic
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libc.a(malloc.o): relocation R_X86_64_TPOFF32 against `tcache' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libc.a(libc_fatal.o): relocation R_X86_64_PC32 against symbol `_dl_pagesize' 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
Running on Ubuntu 18.04.4 LTS with gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 and GNU ld (GNU Binutils for Ubuntu) 2.30.
My questions:
How can I make the above work?
Would it be an issue if 2 libcs run simultaneously (one statically linked in my shared object and one from a hypothetical executable that will link against my shared object and libc)?
I also found this article here highlighting a similar issue but without a solution.
How can I make the above work?
Normal build of libc.a does not have -fPIC. On i386, you can actually link non-PIC object files into a .so, but the result would be an .so which requires text relocations (.text of such .so can't be shared between processes).
But on x86_64 you can't (relocations only have 4 bytes in the medium memory model, and you would need to relocate .text by more than +/-2GiB).
So to make this work, you must rebuild libc.a with -fPIC.
Would it be an issue if 2 libcs run simultaneously (one statically linked in my shared object and one from a hypothetical executable that will link against my shared object and libc)?
Most things will work, but TLS may cause complications.

undefined reference to `WinMain` while compiling my own kernel

I've started writing my very own kernel and am developing on Windows 10.
I am using the following tools:
gcc 8.1.0 elf x86_64 for compiling my C code, and for linking.
I am using this Windows package.
nasm 2.14.02 for compiling my assembly code.
I am using the following command to build my freestanding kernel code:
gcc -c -m64 common/src/kernel.c -o common/build/kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra`
I am using the following command for compiling the root assembly code:
nasm -f elf64 targets/x86_64/src/main.asm -o targets/x86_64/build/main.o
Finally I link the object files together:
gcc -o dist/x86_64/main.bin -ffreestanding -O2 targets/x86_64/build/main.o common/build/kernel.o -lgcc
I haven't a clue why, but the following error is stopping the linking process from working:
... undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status
This doesn't make sense to me because my compilation and linking is in freestanding mode and I am not attempting to use any windows APIs.
How do I fix this?
If it matters, here is my very simple code:
main.asm:
EXTERN kernel_main
call kernel_main
jmp $
; padding and magic number
times 510-($-$$) db 0
dw 0xaa55
kernel.c:
void kernel_main()
{
// empty
}
Edit: It looks like I might need the x86_64-elf-gcc compiler
Edit 2: I tried the x86_64-w64-mingw32-gcc compiler, same error occurs
I was missing the -nostdlib flag on the linker. This seems to have solved the problem.

gcc -fPIC -fPIE: difference betweenn gcc-4 and gcc-6

Preamble: this question is not about Oracle, instead I'd like to understand the fundamental difference between gcc-4 and gcc-6 in the handling of Position Independent Code.
So I have decided to try an Oracle 12c installation on a Debian stretch.
During the link stage with gcc-6, error messages like the following are issued:
/usr/bin/ld: /opt/oracle/product/12.2.0/lib/libpls12.a(pci.o):
relocation R_X86_64_32S against `.rodata.str1.4' can not be used when making a shared object;
recompile with -fPIC.
However, if I switch the compiler to use gcc-4.9, all the linking is done without any problems.
Thus my 2 questions:
Is there a change in the defaults for -fPIC and -fPIE between gcc version 4 and 6? Most probably yes, version 6 seems to use the 2 options by default.
More important for me: does gcc, version 6 have an option to use the version 4 behavior for the generation of position independent code? (Or will I sooner or later no more be able to link against old libraries because gcc-4 is no more available?)
Most likely the gcc-6 linker creates position independent executables by default. The problem can be reproduced as follows and solved by adding the linker flag -no-pie:
UNIX # gcc-6 -g -Wall -fno-pic -c helloworld.c -o helloworld.o
UNIX # gcc-6 -g -Wall helloworld.o -o helloworld
/usr/bin/ld: helloworld.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
UNIX # gcc-6 -g -Wall -no-pie helloworld.o -o helloworld
Indeed, after adding -no-pie to the gcc options used by Oracle, linking works without any errors.
Solution from broeni works fine. Some additional steps I made to make it work:
During installation, I modified the default linker tool from oracle, editing the file
/opt/oracle/product/12.2.0/db1/bin/orald
In the first lines, I forced to use GCC linker, and add the -no-pie option:
#if [ -z "$BASH_VERSION" -o -n "$ORALD_USE_GCC" ] ; then
exec gcc -no-pie "$#"
exit 1
#fi
tags: oracle 12c debian stretch

Building a shared library created a static library instead

I am trying to build libass into a shared library with static linking under MinGW-w64. When I configure with
./configure --disable-static --enable-shared
it generates the shared library (dynamically-linked) as expected. However, when I attempt to force static linking by setting
LDFLAGS=-static
instead of generating a statically-linked shared library (.dll with no dependency), it generates a static library (.a).
I am almost certain that I have all the dependent static libraries and no error or warning message is shown in the make process.
Can anyone please shed some light on what I'm doing wrong?
libtool says No.
The package's stock autotools ltmain.sh script parses the linkage flags and
if it finds -static it will not build a shared library, just a static
one.
Which is the most it could reasonably do, because you can't statically link a shared
library. A shared library must consist entirely of Position Independent (PIC)
code or the linkage will fail, whereas a static linkage will call for the linkage
of non-PIC object files, contributed by the non-PIC standard and runtime libraries,
if nothing else.
foo.c
#include <stdio.h>
void foo(void)
{
puts("foo");
}
Build a dynamically linked shared library:
$ gcc -c -fPIC foo.c
$ gcc -shared -o libfoo.so foo.o
$ file libfoo.so
libfoo.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), \
dynamically linked, BuildID[sha1]=1adff7204d84d138a80bc4b6f3f38211e4b42812, \
not stripped
Attempt to build a statically linked shared library:
$ gcc -c -fPIC foo.c
$ gcc -shared -static -o libfoo.so foo.o
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/6/crtbeginT.o: \
relocation R_X86_64_32 against hidden symbol `__TMC_END__' cannot be used \
when making a shared object
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
The static lib is just an ar package.
You can use command of ar to make the pack and unpack it.

Non-GOT style relocation for executable in GCC

In GCC, if I compile something into a shared library with GCC with g++ -shared func.cpp -o libfunc.so -fPIC, internal function calls to global symbols go through GOT in this generated shared library file. But if I compile with g++ func.cpp -o libfunc.so -mcmodel=large, it will not generate GOT but instead relocate by patching with R_X86_64_64 style relocation directly.
I want this behavior for executables as well. If I compile an executable with g++ main.cpp libfunc.so -o a.out, GCC will generate GOT for any function call from main.cpp to one defined in libfunc.so. I don't want this behavior. I want R_X86_64_64 style relocation. How can I achieve that?
Executables are compiled with -fPIE by default in modern distros for security reasons. To get old behavior add -no-pie to CFLAGS/CXXFLAGS.

Resources