0

I compiled a hello world C program and this is the file information :

hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=3c4fc3bc82d53281357312935790846333a3c7bc, with debug_info, not stripped

When I check the segment header information, I see that the VirtAddr for the LOAD segment is pointing to the address 0x0000000000000000 which is defined as NULL. The entry address is 0x540 which indicates that it lies in the first LOAD segment of the two. The E (execute) flag and the .text section is also mapped to the first LOAD segment. enter image description here

When I use gdb and set a breakpoint at main, then I see the address getting changed, which means the addresses have been shifted by certain offset. Why did this happen? I tried loading the program multiple times, but the offset remains constant, which means there is no address randomization happnening. I see other questions on SO which are getting load address just opposite of mine. Why? Same thing happen when I compile with -m32. Did something change w.r.t linux during past years that I get different output from the linked question?

enter image description here

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Naveen
  • 7,944
  • 12
  • 78
  • 165
  • Did you compile with `-fPIC` or `-fPIE`? – datenwolf Jan 31 '20 at 15:41
  • 2
    GCC compiles PIE executables by default, but GDB [disables address randomization](https://stackoverflow.com/questions/59772399/why-is-the-address-of-libc-start-main-always-the-same-inside-gdb-even-though-a/59772503#59772503) by default. – Marco Bonelli Jan 31 '20 at 15:42
  • @datenwolf : No, I just used the command `gcc -g -o hello hello.c` – Naveen Jan 31 '20 at 15:47
  • @MarcoBonelli : Thanks but why the offset? And is there a way to know the offset beforehand. In other words, is there a way to know the load address for a segment, in virtual memory, by analyzing the binary? – Naveen Jan 31 '20 at 15:50
  • @InsaneCoder I'd say no, as it ultimately depends on the kernel. – Marco Bonelli Jan 31 '20 at 15:56
  • And does this no longer hold : https://stackoverflow.com/questions/2966426/why-do-virtual-memory-addresses-for-linux-binaries-start-at-0x8048000 good? – Naveen Jan 31 '20 at 16:01
  • @InsaneCoder that question has nothing to do with your ELF, which is 64 bits. – Marco Bonelli Jan 31 '20 at 16:14
  • I recommend you a book: *Linkers & Loaders* by John R. Levine. It will explain how it all works. – 0andriy Jan 31 '20 at 16:50
  • @MarcoBonelli : As I said in my question, even when I compile with `-m32`, I still get the same results, the VirtAddr for first LOAD section is still `0x00000000`, unlike the link that I attached in the comment. My output in case of both 32-bit and 64-bit is same, but different from the question/answer linked. – Naveen Jan 31 '20 at 17:59
  • 1
    @MarcoBonelli @datenwolf: My fault. I should have read yours' comment carefully. This https://stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64-linux also helped and now when i added the options `-fno-pie -no-pie` I get the VirtAddr as `0x0000000000400000` and I could also verify the content is mapped at the same address. – Naveen Jan 31 '20 at 18:39
  • @MarcoBonelli: You should post that as an answer. – R.. GitHub STOP HELPING ICE Jan 31 '20 at 20:36
  • Also because of the reason `--enable-default-pie` configured by host OS for gcc, I was getting `shared object` for my executable, which again hints it to be a PIE (Position Independent Executable). – Naveen Feb 01 '20 at 02:33

1 Answers1

1

You're seeing 0 for LOAD because your ELF is position independent.

Modern versions of GCC generate Position Independent Executables by default (unless configured otherwise). If the executable is PIE, the base virtual address in the ELF headers is set to 0. When you run your program under GDB, it temporarily disables address randomization and loads your program at the default address 0x0000555555554000.

If you want to compile a non-PIE executable you can use the -no-pie -fno-pie compilation flags.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128