how to pass -pg to gcc in cygwin - gcc

I just want to test -pg, the source file is very simple, my environment is
cygwin,
$ uname -a
CYGWIN_NT-10.0 SHA-LPLATOW 2.8.2(0.313/5/3) 2017-07-12 10:58 x86_64 Cygwin
$ vi pgtest.c
#include <stdio.h>
void main(void){
printf("hello, world\n");
}
no -pg compiling is OK.
$ gcc -c pgtest.c
$ gcc -o pgtest.exe pgtest.o
but -pg report error
$ gcc -pg -c pgtest.c
$ gcc -o pgtest.exe pgtest.o
pgtest.o:pgtest.c:(.text+0x1): undefined reference to `__fentry__'
pgtest.o:pgtest.c:(.text+0x1): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__fentry__'
pgtest.o:pgtest.c:(.text+0xe): undefined reference to `_monstartup'
pgtest.o:pgtest.c:(.text+0xe): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `_monstartup'
collect2: error: ld returned 1 exit status
I have tried LDFLAGS, it is the same.
export LDFLAGS="-pg" ; gcc -o pgtest.exe pgtest.o

from the gcc info page
'-pg'
Generate extra code to write profile information suitable for the
analysis program 'gprof'. You must use this option when compiling
the source files you want data about, and you must also use it when
linking.
so if you want to do a separate compilation and linking you need to repeate the -pg
$ gcc -c pgtest.c -pg
$ gcc -o pgtest.exe pgtest.o -pg

Related

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

Linking to libusb

I know this is something so simple I'm going to hate myself for having to ask it, but my head is aching from repeated hits on the desktop. I've read dozens of stackoverflow and google results which suggest that the following should work:
$ ls /usr/local/lib/libusb*
/usr/local/lib/libusb-1.0.a /usr/local/lib/libusb-1.0.so /usr/local/lib/libusb-1.0.so.0.1.0
/usr/local/lib/libusb-1.0.la /usr/local/lib/libusb-1.0.so.0
$ gcc -I ~/libusb-1.0.18/libusb -c test.c
$ gcc -L/usr/local/lib -o test test.o -llibusb
/usr/bin/ld: cannot find -llibusb
collect2: error: ld returned 1 exit status
$ gcc -L/usr/local/lib -o test test.o -llibusb-1.0
/usr/bin/ld: cannot find -llibusb-1.0
collect2: error: ld returned 1 exit status
Why is that not correct? One of those should have worked and I've tried many, many more variations.
For completeness I'm running Ubuntu 14.04 (fresh VM installation).
I built libusb from source (~/libusb-1.0.18) with:
./configure --disable-udev
make
sudo make install
The leading lib and trailing .so are automatically filled in by the linker, so you should not specify either on the command line. Your command should be:
gcc -L/usr/local/lib -o test test.o -lusb-1.0

How to make CMake append linker flags instead of prepending them?

CMake seems to prepend linker flags at the front of a GCC compilation command, instead of appending it at the end. How to make CMake append linker flags?
Here is a simple example to reproduce the problem.
Consider this C++ code that uses clock_gettime:
// main.cpp
#include <iostream>
#include <time.h>
int main()
{
timespec t;
clock_gettime(CLOCK_REALTIME, &t);
std::cout << t.tv_sec << std::endl;
return 0;
}
This is a CMakeLists.txt to compile the C++ file above:
cmake_minimum_required(VERSION 2.8)
set(CMAKE_EXE_LINKER_FLAGS "-lrt")
add_executable(helloapp main.cpp)
Note that we have added -lrt since it has the definition of clock_gettime.
Compiling this using:
$ ls
CMakeLists.txt main.cpp
$ mkdir build
$ cd build
$ cmake ..
$ make VERBOSE=1
Which throws up this error, even though you can see -lrt in the command:
/usr/bin/c++ -lrt CMakeFiles/helloapp.dir/main.cpp.o -o helloapp -rdynamic
CMakeFiles/helloapp.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x15): undefined reference to `clock_gettime'
collect2: ld returned 1 exit status
make[2]: *** [helloapp] Error 1
The problem here is the C++ compilation command generated by CMake has -lrt prepended at the front. The compilation works fine if it had been:
/usr/bin/c++ CMakeFiles/helloapp.dir/main.cpp.o -o helloapp -rdynamic -lrt
How to make CMake append the linker flags at the end?
In general you can't (I think), but in the specific case that you want to link against a particular library, you should be using the syntax
target_link_libraries(helloapp rt)
instead. CMake knows that this corresponds to passing -lrt on the linker command line.

Linker problems in Ubuntu 11.10

after upgrading to Ubuntu 11.10, I've found that many of my old and current developments can't be compiled anymore. I've reduced the problem to a simple example:
#include <X11/Xlib.h>
int main() {
Display* display = XOpenDisplay(":0.0");
XCloseDisplay(display);
return 0;
}
Compiling it using:
g++ -lX11 test.cpp
or
g++ -c -o test.o test.cpp
g++ -lX11 -o test test.o
Causes a failure to happen:
/tmp/ccBAOpzy.o: In function `main':
test.cpp:(.text+0x11): undefined reference to `XOpenDisplay'
test.cpp:(.text+0x21): undefined reference to `XCloseDisplay'
Any ideas? I've found that some linker stuff has changed in 11.10:
https://wiki.ubuntu.com/NattyNarwhal/ToolchainTransition
But still doesn't explain these problems.
g++ -lX11 -o test test.o
Above command is incorrect. Try this instead:
g++ test.o -lX11
Explanation of why the order matters here.
Also, you should never call your executables test on UNIX.

GCC 4.5 vs 4.4 linking with dependencies

I am observing a difference when trying to do the same operation on GCC 4.4 and GCC 4.5. Because the code I am doing this with is proprietary, I am unable to provide it, but I am observing a similar failure with this simple test case.
What I am basically trying to do is have one shared library (libb) depend on another shared library (liba). When loading libb, I assume that liba should be loaded as well - even though libb is not necessarily using the symbols in liba.
What I am observing is when I compile with GCC 4.4, I observe that the liba is loaded, but if I compile with GCC 4.5, libb is not loaded.
I have a small test case that consists of two files, a.c and b.c . The contents of the files:
//a.c
int a(){
return 0;
}
//b.c
int b(){
return 0;
}
//c.c
#include <stdio.h>
int a();
int b();
int main()
{
printf("%d\n", a()+b());
return 0;
}
//test.sh
$CC -o liba.so a.c -shared
$CC -o libb.so b.c -shared -L. -la -Wl,-rpath-link .
$CC c.c -L. -lb -Wl,-rpath-link .
LD_LIBRARY_PATH=. ./a.out
This is my output with different versions of GCC
$ CC=gcc-4.4 ./test.sh
1
$ CC=gcc-4.5 ./test.sh
/tmp/cceJhAqy.o: In function `main':
c.c:(.text+0xf): undefined reference to `a'
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory
$ CC=gcc-4.6 ./test.sh
/tmp/ccoovR0x.o: In function `main':
c.c:(.text+0xf): undefined reference to `a'
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory
$
Can anyone explain what is happening? Another extra bit of information is that ldd on libb.so does show liba.so on GCC 4.4 but not on GCC 4.5.
EDIT
I changed test.sh to the following:
$CC -shared -o liba.so a.c
$CC -L. -Wl,--no-as-needed -Wl,--copy-dt-needed-entries -la -shared -o libb.so b.c -Wl,-rpath-link .
$CC -L. c.c -lb -Wl,-rpath-link .
LD_LIBRARY_PATH=. ./a.out
This gave the following output with GCC 4.5:
/usr/bin/ld: /tmp/cc5IJ8Ks.o: undefined reference to symbol 'a'
/usr/bin/ld: note: 'a' is defined in DSO ./liba.so so try adding it to the linker command line
./liba.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
./test.sh: line 4: ./a.out: No such file or directory
There seems to have been changes in how DT_NEEDED libraries are treated during linking by ld. Here's the relevant part of current man ld:
With --copy-dt-needed-entries dynamic libraries mentioned on the command
line will be recursively searched, following their DT_NEEDED tags to other libraries, in order to resolve symbols required by the output binary. With the
default setting however the searching of dynamic libraries that follow it will stop with the dynamic library itself. No DT_NEEDED links will be traversed
to resolve symbols.
(part of the --copy-dt-needed-entries section).
Some time between GCC 4.4 and GCC 4.5 (apparently, see some reference here - can't find anything really authoritative), the default was changed from the recursive search, to no recursive search (as you are seeing with the newer GCCs).
In any case, you can (and should) fix it by specifying liba in your final link step:
$CC c.c -L. -lb -la -Wl,-rpath-link .
You can check that this linker setting is indeed (at least part of) the issue by running with your newer compilers and this command line:
$CC c.c -L. -Wl,--copy-dt-needed-entries -lb -Wl,--no-copy-dt-needed-entries \
-Wl,-rpath-link .

Resources