GCC entrypoint address - gcc

I am compiling a very basic "hello world" program with gcc, with this command line:
gcc -m32 prog_cible.c -o prog_cible
I am very surprised of the entry point address:
readelf -h prog_cible
...
Entry point: 0x420
I have tunrned off alsr with this command:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
I think this cannot be the real entry point.
I suppose a base address is added to 0x420 ?
In the past, 10 years ago, readelf gave me the good entry point. What has changed since ?
Thanks

I think this cannot be the real entry point.
You are correct. Your gcc is likely configured to build PIE binaries by default. PIE binary is really a special form of a shared library.
If you look at the type of the binary (which readelf -h also printed), you'll see that it's a DYN, not EXEC.
You can disable PIE with gcc -m32 -no-pie ..., and then your entry point will look something like 0x8048420.

Related

How to force GCC to use ld.gold if real-ld executable exists in compiler search path?

I've found out that when GCC (tried on GCC 4.8 and GCC 6.4) finds real-ld executable in its search path, it is silently ignoring -fuse-ld=... option, and use real-ld instead of appropriate linker.
$ echo "int main(){}" > script.c
$ ln -s /usr/bin/ld real-ld
$ gcc -fuse-ld=gold -B$PWD script.c
$ readelf --string-dump=.note.gnu.gold-version a.out
readelf: a.out: Warning: Section '.note.gnu.gold-version' was not dumped because it does not exist!
Normally, without real-ld it will work as expected:
$ echo "int main(){}" > script.c
$ gcc -fuse-ld=gold script.c
$ readelf --string-dump=.note.gnu.gold-version a.out
String dump of section '.note.gnu.gold-version':
[ c] GNU
[ 10] gold 1.12
Documentation of GCC suggests that gold linker will be used.
Documentation of collect2 does not say anything about -fuse-ld feature...
tl;dr It is not possible [2]. This is a feature.
I've dug deep into GCC's collect2.c source code, it's history, and collect2 documentation, and came into conclusion that, based on those documents, it is expected behavior that real-ld takes precedence over all other binaries [1].
However, logic of searching real ld, when -fuse-ld=... is enabled, is vague and does not have reflection in documentation...
Based on source code, as far as I understand C language, -fuse-ld=... feature is effective only when collect2 tries to search for ld.
[1] One exception is when GCC is compiled with --with-ld=..., but only for non-crosscompilers. It gives nothing if one cannot rebuild GCC (or uses crosscompiler).
[2] Not entirely true. Just came into hackish idea to create own real-ld that would exec ld.gold, and modify compiler search path (using -B, instead of using -fuse-ld=...):
$ cat /path/to/real-ld/real-ld
#!/bin/sh
exec ld.gold "$#"
$ gcc -B /path/to/real-ld/ ...
Remove real-ld and in it's place have ld. pointing to the linker you want to use. This way -fuse-ld=gold will work if there is a ld.gold, same for ld.bfd.

How to set library search path for 64 bit libraries for g++ in Ubuntu?

Trying to compile something for 64 bit unix using Ubuntu. As a disclaimer I only started using linux and gcc a few days ago so still learning my way around. Anyway, getting the following error:
/home/myuser/myproject/myfile.cpp:437: undefined reference to `clock_gettime'
A quick google reveals I need the -lrt option to link with librt.a. So I check my command line ( formatted for readability, different file names and I've remove lists of file names ):
/usr/bin/g++
-Wl,
--gc-sections
-fno-exceptions
-m64
-B/usr/bin
-o
"/home/myuser/myproject"
-Wl,
-Map, "/home/myuser/myproject/myproject.map"
-g
"/home/myuser/myproject/myproject.cpp.obj"
..and some more .objs..
-Xlinker
--start-group
"-lpthread"
"-lrt"
"/home/myuser/myproject/lib/mylib.a"
..and some more .as..
-Xlinker
--end-group
Hmm. Looks like -lrt is already there, maybe I don't have librt.a? Nope searching all files reveals I have /usr/lib/x86_64-linux-gnu/librt.a. I guess g++ is looking in the wrong place. So in the above command line I replace -lrt with /usr/lib/x86_64-linux-gnu/librt.a and bingo! it compiles and links fine. Unfortunately, this is an automated tool and I need this to work on many computers and can't make assumptions about the location of librt.a so I really need it to work with -lrt. So how do I set the local libary search path? First attempt is changing LD_LIBRARY_PATH environment variable but apparently ( from what I can tell from more googling ) this is ignored on ubuntu and instead I should be messing with .conf files in /etc/ld.so.conf.d/, however I already it looks like I already have x86_64-linux-gnu.conf in there with the following lines:
# Multiarch support
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
From my reading up this point it looks that should be all I need. Kind of stuck as to where to go from here...
Answering my own question just in case someone else has this problem. Turns out the correct librt.a was being linked but the linker is very sensitive to the link order. Putting -lrt and -lpthread at the end of the group fixes the problem.

rpath=$ORIGIN not having desired effect?

I've got a binary "CeeloPartyServer" that needs to find libFoundation.so at runtime, on a FreeBSD machine. They're both in the same directory. I compile (on another platform, using a cross compiler) CeeloPartyServer using linker flag -rpath=$ORIGIN.
> readelf -d CeeloPartyServer |grep -i rpath
0x0000000f (RPATH) Library rpath: [$ORIGIN]
> ls
CeeloPartyServer Contents Foundation.framework libFoundation.so
> ./CeeloPartyServer
/libexec/ld-elf.so.1: Shared object "libFoundation.so" not found, required by "CeeloPartyServer"
Why isn't it finding the library when I try to run it?
My exact linker line is: -lm -lmysql -rpath=$ORIGIN.
I am pretty sure I don't have to escape $ or anything like that since my readelf analysis does in fact show that library rpath is set to $ORIGIN. What am I missing?
I'm assuming you are using gcc and binutils.
If you do
readelf -d CeeloPartyServer | grep ORIGIN
You should get back the RPATH line you found above, but you should also see some entries about flags. The following is from a library that I built.
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../lib]
0x000000000000001e (FLAGS) ORIGIN
0x000000006ffffffb (FLAGS_1) Flags: ORIGIN
If you aren't seeing some sort of FLAGS entries, you probably haven't told the linker to mark the object as requiring origin processing. With binutils ld, you do this by passing the -z origin flag.
I'm guessing you are using gcc to drive the link though, so in that case you will need to pass flag through the compiler by adding -Wl,-z,origin to your gcc link line.
Depending on how many layers this flag passes through before the linker sees it, you may need to use $$ORIGIN or even \$$ORIGIN. You will know that you have it right when readelf shows an RPATH header that looks like $ORIGIN/../lib or similar. The extra $ and the backslash are just to prevent the $ from being processed by other tools in the chain.
\$\ORIGIN if you are using chrpath and \$\$ORIGIN if you are providing directly in LDFLAGS
using ldd CeeloPartyServer to check the dependency .so is starting with ./ or not. (e.g. libFoundation.so and ./libFoundation.so)
For common situation it should be libFoundation.so and without the prefix ./
if ./ prefix is necessary for some uncommon case, make sure the CWD is the same folder with libFoundation.so, and the $ORIGIN would be invalid.
=======
For example:
g++ --shared -Wl,--rpath="\$ORIGIN" ./libFoundation.so -o lib2.so
would got a library lib2.so with ./libFoundation.so
g++ --shared -Wl,--rpath="\$ORIGIN" libFoundation.so -o lib2.so
would got libFoundation.so instead.

What's the "correct" way to determine target and architecture for GNU binutils?

In my build chain, I need to do this:
objcopy -I binary -O $BFDNAME -B $BFDARCH <this> <that>
in order to get a binary file into library form. Because I want other people to be able to use this, I need to know how to get $BFDNAME and $BFDARCH from their toolchain when they run the build. I can get the values locally by running objdump -f against a file I've already built, but is there a better way which won't leave me compiling throw-away files just to get configuration values?
Thank you for pointing this out, regularfry! Your answer helped me to find another solution which works without specifying the architecture at all:
ld -r -b binary -o data.o data.txt
On my system (Ubuntu Linux, binutils 2.22) both objcopy and ld approaches produce identical object files.
All credit goes to:
http://stupefydeveloper.blogspot.de/2008/08/cc-embed-binary-data-into-elf.html
For future reference, the answer seems to be this: the first entry in the output of objdump -i is the default, native format of the system.

Unrolling gcc compiler optimization

I am interested in seeing the code where gcc has actually optimized the code. Is there a way I could do?
I have gone through few other similar questoins, I have tried following few things,
-Wa,ahl=filename.lst :- this option is really good, you can browse the code and corresponding machine code, but it is not good when I enable O3 option.
Dumping optimized tree :- I am sure gcc is giving me good amount of debug information. But I do not how to decipher it. I will be glad if someone could point to any available information.
Is there any other better way, to find out what part of the code gcc optimized?
Thanks,
Madhur
You can compile the code twice, first with:
$ gcc -O0 -S -o yourfile_o0.s
Then with:
$ gcc -O3 -S -o yourfile_o3.s
Then you can diff the two resulting assembly files:
$ diff -u yourfile_o0.s yourfile_o3.s
$ vim -d yourfile_o0.s yourfile_o3.s
$ emacs --eval '(ediff "yourfile_o0.s" "yourfile_o3.s")'
Look at the assember code or decompile your compiled application. C decompilers produce ugly C code, but for analyzing which code was generated, it have to suffice.

Resources