clang appears to use gcc - gcc

When I compile a simple hello world program using clang, in the comments of the elf64 file I still find information related to GCC. Why? I'm using clang not gcc.
I'm using ubuntu 16.04.
username#ubuntu:~$ clang++ -stdlib=libc++ test.cpp
username#ubuntu:~$ objdump --full-contents --section=.comment a.out
a.out: file format elf64-x86-64
Contents of section .comment:
0000 4743433a 20285562 756e7475 20352e34 GCC: (Ubuntu 5.4
0010 2e302d36 7562756e 7475317e 31362e30 .0-6ubuntu1~16.0
0020 342e3429 20352e34 2e302032 30313630 4.4) 5.4.0 20160
0030 36303900 636c616e 67207665 7273696f 609.clang versio
0040 6e20342e 302e3020 28746167 732f5245 n 4.0.0 (tags/RE
0050 4c454153 455f3430 302f6669 6e616c29 LEASE_400/final)
0060 00 .
username#ubuntu:~$
test.cpp is:
#include <iostream>
int main(int argc, char* argv[])
{
std::cout << argc << std::endl;
return 0;
}
I also ran
username#ubuntu:~$ sudo update-alternatives --config c++
[sudo] password for username:
There are 2 choices for the alternative c++ (providing /usr/bin/c++).
Selection Path Priority Status
------------------------------------------------------------
0 /usr/bin/g++ 20 auto mode
* 1 /usr/bin/clang++-libc++ 5 manual mode
2 /usr/bin/g++ 20 manual mode
Press <enter> to keep the current choice[*], or type selection number:
username#ubuntu:~$
Is this ok? why?

It's because you're linking with a C runtime (from Glibc) built with GCC, and the linker is merging the two together.
$ clang++ -c --stdlib=libc++ test.cpp
$ objdump --full-contents --section=.comment test.o
test.o: file format elf64-x86-64
Contents of section .comment:
0000 00636c61 6e672076 65727369 6f6e2034 .clang version 4
0010 2e302e30 20287461 67732f52 454c4541 .0.0 (tags/RELEA
0020 53455f34 30302f66 696e616c 2900 SE_400/final).
$ clang++ --verbose test.o
"/usr/bin/ld" --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crt1.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crti.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/crtbegin.o -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1 -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64 -L/usr/bin/../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../.. -L/usr/bin/../lib -L/lib -L/usr/lib test.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/crtend.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crtn.o
$ objdump --full-contents --section=.comment /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crt1.o
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/6.3.1/../../../../lib64/crt1.o: file format elf64-x86-64
Contents of section .comment:
0000 00474343 3a202847 4e552920 362e332e .GCC: (GNU) 6.3.
0010 31203230 31373033 303600 1 20170306.
$ objdump --full-contents --section=.comment a.out
a.out: file format elf64-x86-64
Contents of section .comment:
0000 4743433a 2028474e 55292036 2e332e31 GCC: (GNU) 6.3.1
0010 20323031 37303330 3600636c 616e6720 20170306.clang
0020 76657273 696f6e20 342e302e 30202874 version 4.0.0 (t
0030 6167732f 52454c45 4153455f 3430302f ags/RELEASE_400/
0040 66696e61 6c2900 final).
My system has slightly different versions from yours, but you can see that the Clang-compiled object only has the Clang identifier in it, the C runtime object has the GCC identifier in it, and the final binary has both.

Related

Size of the file produced by linker is too large

I have those three files that don't have many bytes.
.rw-r--r-- 936 28 Jan 00:53 kernel.o
.rw-r--r-- 512 28 Jan 00:53 kernel_entry.o
.rw-r--r-- 872 28 Jan 00:53 screen.o
I assembled kernel_entry.o using NASM 2.15.05:
nasm src/kernel_entry.asm -f elf32 -o ../build/obj/kernel_entry.o
And i compiled kernel.o and screen.o using gcc 11.1.0:
gcc -ffreestanding -m32 -fno-pie -c -Iinclude -MMD -o ../build/obj/kernel.o src/kernel.c
gcc -ffreestanding -m32 -fno-pie -c -Iinclude -MMD -o ../build/obj/driver/screen.o src/driver/screen.c
My goal is to produce 32 bit executable code.
Then i link those 3 files together using ld 2.36.31:
ld -m elf_i386 -Ttext 0x1000 --oformat binary ../build/obj/kernel_entry.o ../build/obj/kernel.o ../build/obj/driver/screen.o -o ../build/kernel.bin
However, I expected the output file to be the size of the three .o files but it is 135M which is way too much:
.rwxr-xr-x 135M 28 Jan 01:16 build/kernel.bin
Looking at the hexadecimal representation of the file, I see a little room for my instructions and the rest is just zeros.
Do you have any idea what's wrong? By removing the oformat parameter I get a decent size but the code does not execute as expected
Thank you.

gcc assembler - create only the minimal instructions necessary

I have created a very minimal application in assembly. It sets some registers to 0 and does a multiplication. Nothing fancy.
However, the gcc adds a lot of stuff to the machine code I do not want.
A small list of the stuff I find in the objdump:
deregister_tm_clones
register_tm_clones
__do_global_dtors_aux
frame_dummy
__libc_fini_array
memset
and a few more
I know that I do not need them, but I have no idea how I can tell to compiler to stop including them. I tried to use optimization options, but this did not change anything.
I compile it basically like: GCC -o ./main.elf ./main.S
Thank you very much for any help!
GCC automatically links the C / C++ runtime start-up crt0.o and the standard library. You can provide your own startup code to override the default and provide command line options to force it not to link no the standard library.
Options controlling startup and default libraries include:
-nostartfiles
-nostdlib
-nodefaultlubs
-nolibc
Each affects the link in a different way, but in this case -nostdlib will exclude both crt0.o and standard libraries. Of course if your code makes no reference to the standard library then nothing will be linked in any case, but explicitly excluding it will helpfully generate a link error if something does reference it.
See: https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
Be aware that if your code does not establish a valid C runtime environment, providing for example static initialisation and a stack (a minimum), then some C code may not run in the manner intended. You may also need to specify the entry point via --entry=entry if you do not use the same default entry point as crt0 (_start I think).
Alternatively you can invoke gcc with the -c option and separately invoke the linker ld without specifying any library.
so.S:
nop
nop
then build.
as so.S -o so.o
ld -Ttext=0x1000 so.o -o so.elf
objdump -D so.elf
Disassembly of section .text:
0000000000001000 <__bss_start-0x200002>:
1000: 90 nop
1001: 90 nop
objcopy -O binary so.elf so.bin
hexdump -C so.bin
00000000 90 90 |..|
00000002
using gcc
gcc -nostartfiles -nostdlib -nodefaultlibs -ffreestanding so.S -Xlinker "-Ttext=0x1000" -o so.elf
this leaves extra garbage in the file, but
gcc so.S -c -o so.o
ld -Ttext=0x2000 so.o -o so.elf
ld: warning: cannot find entry symbol _start; defaulting to 0000000000002000
objdump -D so.elf
Disassembly of section .text:
0000000000002000 <__bss_start-0x200002>:
2000: 90 nop
2001: 90 nop
But if writing assembly language you might as well use the assembler not the compiler.
_start is not required unless you need an entry point defined in the file then you need to do this:
.globl _start
_start:
plus possibly something in the linker to call that out as the entry point for file formats like elf, exe, etc.
works for cross compiling as well
arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -Ttext=0x3000 so.o -o so.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000000003000
arm-none-eabi-objdump -D so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
00003000 <__bss_end__-0x10008>:
3000: e1a00000 nop ; (mov r0, r0)
3004: e1a00000 nop ; (mov r0, r0)
pdp11-aout-as so.s -o so.elf
pdp11-aout-as so.s -o so.o
pdp11-aout-ld -Ttext=0x400 so.o -o so.elf
pdp11-aout-objdump -D so.elf
so.elf: file format a.out-pdp11
Disassembly of section .text:
00000400 <so.o>:
400: 00a0 nop
402: 00a0 nop
and so on.

How to run manually produce an elf executable using ld?

I'm trying to get my head around how the linking process works when producing an executable. To do that I'm reading Ian Taylor's blog series about it, but a lot of it is beyond me at the moment - so I'd like to see how it works in practice.
At the moment I produce some object files and link them via gcc with:
gcc -m32 -o test.o -c test.c
gcc -m32 -o main.o -c main.c
gcc -m32 -o test main.o test.o
How do I replicate the gcc -m32 -o test main.o test.o stage using ld?
I've tried a very naive: ld -A i386 ./test.o ./main.o
But that returns me these errors:
ld: i386 architecture of input file `./test.o' is incompatible with i386:x86-64 output
ld: i386 architecture of input file `./main.o' is incompatible with i386:x86-64 output
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
./test.o: In function `print_hello':
test.c:(.text+0xd): undefined reference to `_GLOBAL_OFFSET_TABLE_'
test.c:(.text+0x1e): undefined reference to `puts'
./main.o: In function `main':
main.c:(.text+0x15): undefined reference to `_GLOBAL_OFFSET_TABLE_
I'm most confused by _start and _GLOBAL_OFFSET_TABLE_ being missing - what additional info does gcc give to ld to add them?
Here are the files:
main.c
#include "test.h"
void main()
{
print_hello();
}
test.h
void print_hello();
test.c
#include <stdio.h>
void print_hello()
{
puts("Hello, world");
}
#sam : I am not the best people to answer your question because I am a beginner in compilation. I know how to compile programs but I do not really understand all the details (https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)
So, I decided this year to try to understand how compilation works and I tried to do, more or less, the same things as you tried a few days ago. As nobody has answered, I am going to expose what I have done but I hope an expert will supplement my answer.
Short answer : It is recommended to not use ld directly but to use gcc directly instead. Nevertheless, it is, as you write, interesting to know how the linking process works. This command works on my computer :
ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o /usr/lib/crtn.o
Very Long answer :
How did I find the command above ?
As n.m suggested, run gcc with -v option.
gcc -v -m32 -o test main.o test.o
... /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 ... (many
options and parameters)....
If you run ld with these options and parameters (copy and paste), it should work.
Try your command with -m elf_i386 (cf. collect2 parameters)
ld -m elf_i386 test.o main.o
ld: warning: cannot find entry symbol _start; ....
Look for symbol _start in object files used in the full ld command.
readelf -s /usr/lib/crt1.o (or objdump -t)
Symbol table '.symtab' contains 18 entries: Num: Value Size
Type Bind Vis Ndx Name... 11: 00000000 0 FUNC
GLOBAL DEFAULT 2 _start
Add this object to your ld command :ld -m elf_i386 test.o main.o /usr/lib/crt1.o
... undefined reference to `__libc_csu_fini'...
Look for this new reference in object files. It is not so obvious to know which library/object files are used because of -L, -l options and some .so include other libraries. For example, cat /usr/lib/libc.so. But, ld with --trace option helps. Try this commandld --trace ... (collect2 parameters)At the end, you should findld -m elf_i386 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc_nonshared.a /lib/libc.so.6 /usr/lib/crti.oor shorter (cf. cat /usr/lib/libc.so) ld -m elf_i386 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o
It compiles but it does not run (Try to run ./test). It needs the right -dynamic-linker option because it is a dynamically linked ELF executable. (cf collect2 parameters to find it) ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o But, it does not run (Segmentation fault (core dumped)) because you need the epilogue of the _init and _fini functions (https://gcc.gnu.org/onlinedocs/gccint/Initialization.html). Add the ctrn.o object. ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test test.o main.o /usr/lib/crt1.o /usr/lib/libc.so /usr/lib/crti.o /usr/lib/crtn.o./test
Hello, world

Link issue under AIX with G++ 6.3

After some struggle, I must admit I need some external help on this linker issue. AIX will kill me otherwise.
I am striving to migrate our build from GCC 4.8.5 to GCC 6.3.0 under AIX 7.1:
> uname -a
AIX wreckmach 1 7 00F63B074C00
> oslevel
7.1.0.0
Now, all the compilation phase is going well, but at link stage things starts going messy. My compilation line is like the following (I removed includes directories and some internal defines):
g++ -std=c++11 -Wno-deprecated -g -pthread -shared -maix64 -gdwarf -g3 -O3 -fPIC -fPIC -I./some/includes -D_REENTRANT=1 -DAIX53=1 -DAIX=1 -DNDEBUG=1 -DSVR4=1 -D__VACPP_MULTI__=1 -DRS6000=1 myCppFile.cpp -c -o /home/me/migration/build.AIX71_GCC_60300_64/myCppFile.cpp.1.o
And my link line is
g++ -g -ggdb3 -pthread -maix64 -Wl,-brtl -Wl,-bhalt:5 -Wl,-bnodelcsect -Wl,-brtl,-bexpfull -shared /home/me/migration/build.AIX71_GCC_60300_64/myCppFile.cpp.1.o /home/me/migration/build.AIX71_GCC_60300_64/myOtherCppFile.cpp.1.o -o /home/me/migration/build.AIX71_GCC_60300_64/libtest.so -L/BUILD/SOFT/compilers/AIX71/GCC/60300/lib64 -lgcc_s -lstdc++ -lpthread
This gives me the following output:
ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information.
collect2: error: ld returned 8 exit status
By adding the -bnoquiet options, I got :
(ld): save SRE .
SAVE: Section sizes = 69976+5192+280 (0x11158+0x1448+0x118 hex)
SAVE: Size of TOC: 1352 (0x548 hex)
ld: 0711-310 ERROR: Relocation entries from the .text section have been
written to the .loader section. The following csects are in error:
CSECT or (Symbol in CSECT) Inpndx Address TY CL Source-File(Object-File)
Symbols referenced with .loader section RLDs: TY CL Inpndx Name
--------------------------------------------- -- -- ------------------------
<_myCppFile.ro_> [260] 00004080 SD RO ../src/myCppFile.cpp(./build.AIX71_GCC_60300_64/myCppFile.cpp.1.o)
ER PR [140] __gcc_unwind_dbase
SD RW [264] <_myCppFile.rw_>
<_myOtherCppFile.ro_> [107] 00002240 SD RO ../src/myOtherCppFile.cpp(./build.AIX71_GCC_60300_64/myOtherCppFile.cpp.1.o)
SD RW [111] <_myOtherCppFile.rw_>
ER PR [56] __gcc_unwind_dbase
SAVE: The return code is 4.
(ld): rc
RC: Highest return code was 4.
A quick look at libgcc_s/libstdc++ shows that this symbol is defined and exported:
> nm -X64 /BUILD/SOFT/compilers/AIX71/GCC/60300/lib64/libgcc_s.a | grep __gcc_unwind
__gcc_unwind_dbase D 536871816
__gcc_unwind_dbase d 536871816 4
__gcc_unwind_dbase d 536876288 8
> nm -X64 /BUILD/SOFT/compilers/AIX71/GCC/60300/lib64/libstdc++.a | grep __gcc_unwind
__gcc_unwind_dbase D 536871608
__gcc_unwind_dbase d 536871608 4
__gcc_unwind_dbase d 537025144 8
What am I missing and doing wrong?
I precise that the result is the same regardless of which ld I use (system one --prefered-- or gnu binutils one)
EDIT When I create a dummy library and link an executable on it, everything went fine. The whole stuff is using the same options, except the external libraries used in the above quoted project. I am now completely stuck... T_T

Breaking NASM files into multiple with link errors on OS X

My base assembler file foidlrt.asm started getting a bit too large so I broke it up into two. Here is the entirety of the second file folder_stdio.asm:
; foidl_stdio.asm
%include "foidlstnd.inc"
section .text
DEFAULT REL
global foidl_fclose ; Raw file close
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; foidl_close
; Raw file close
; REGISTERS (1):
; RDI file handle
; CALLS:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
foidl_fclose:
mov rax,SYSCALL_FILE_CLOSE ; 0x2000006
syscall
ret
However, now when I build I am now getting this error from make despite the global declaration in the new file:
nasm src/foidlrt.asm -f macho64 --prefix _ -g -O0 -Iincludes/ -o asmobjs/foildrt.o
nasm src/foidlrt.asm -f macho64 --prefix _ -g -O0 -Iincludes/ -o asmobjs/foidl_stdio.o
libtool -static -s -o libs/libfoidlrt.a asmobjs/foildrt.o asmobjs/foidl_stdio.o
gcc src/testlink.c -L libs -l foidlrt -Wall -g -L. -Wl,-pie -I. -o bin/testlink
Undefined symbols for architecture x86_64:
"_foidl_fclose", referenced from:
_main in testlink-4b5ad3.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Version information:
XCode - 7.2.1 (7C1002)
nasm - NASM version 2.12 compiled on Feb 28 2016
gcc - Apple LLVM version 7.0.2 (clang-700.1.81)
RESOLVED
Error was all mine, makefile rule was bad. Working as expected now.

Resources