Why Linux/gnu linker chose address 0x400000?
The start address is usually set by a linker script.
For example, on GNU/Linux, looking at /usr/lib/ldscripts/elf_x86_64.x
we see:
...
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); \
. = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
The value 0x400000
is the default value for the SEGMENT_START()
function on this platform.
You can find out more about linker scripts by browsing the linker manual:
% info ld Scripts
why my x64 process base address not start from 0x400000?
I learned from this link Why is address 0x400000 chosen as a start of text segment in x86_64
That address is used for executables (ELF
type ET_EXEC
).
I only found my bash process starts from a very high base address (0x55971cea6000). Any one knows why?
Because your bash
is (newer) position-independent executable (ELF
type ET_DYN
). It behaves much like a shared library, and is relocated to random address at runtime.
The 0x55971cea6000
address you found will vary from one execution to another. In contrast, ET_EXEC
executables can only run correctly when loaded at their "linked at" address (typically 0x400000
).
how does dynamic linker choose the start address for a 64-bit process?
The dynamic linker doesn't choose the start address of the executable -- the kernel does (by the time the dynamic linker starts running, the executable has already been mmap
ed into memory).
The kernel looks at the .e_type
in the ELF
header and .p_vaddr
field of the first program header and goes from there. IFF .e_type == ET_EXEC
, then the kernel maps executable segments at their .p_vaddr
addresses. For ET_DYN
, if ASLR is in effect, the kernel performs mmap
s at a random address.
Why does not entry point address start at 0x400000
The binary is relocatable, and the segments have been packed against each other. The .text
segment starts at 0x1050 in the file, and the entry point is relative to its location in the file, not the location it will ultimately be loaded.
For a non-relocatable file try readelf -h /usr/lib/klibc/bin/sh
. This file is simpler in a number of ways, including not using an interpreter but actually being loaded as-is by the kernel.
We're not in x86
anymore. Relocatable binaries are the default for everything now, not just shared libraries. It's no longer a great pain to do relocatable stuff, and in a certain way it's cheaper than non-relocatable now because we have to emit the vector table anyway because the processor doesn't have 64 bit displacement.
As Nate Eldredge points out, compiling with -no-pie
yields a non-relocatable binary, and I have verified the expected start address appears.
What is the address of entry point of a file linked by gnu linker?
It depends on the binary format you use. For ELF, the e_entry
member of the main header is what you want.
Why kernels make use of the high logical address
Before PIC (Position-independent code) was popular, there are lots of static linked programs can only be loaded at specified address, likely 0x400000
To be able to compatible with these programs, the kernel must not obtain the address space. So the kernel is located at high 1G address space.
Why does the `--oformat binary' option of the gnu linker place the `.data' segment at 0x0200000
1) The linker probably does this because it felt like it (e.g. possibly for alignment with "2 MiB pages" on 80x86), and because you didn't provide a linker script that says to do anything other than "whatever the linker feels like".
2) I'd assume all output formats do "whatever the linker feels like" (unless the linker is told otherwise).
Note: The actual behaviour may be determined by a default linker script hidden somewhere, and may be "whatever the distribution of the OS felt like" rather than merely "whatever the linker felt like".
In any case, if you want the linker to do something specific, you need to tell the linker specifically what you want by writing a linker script. If you actually have written a "less specific than necessary" linker script then you'd need to make that script more specific.
Why doesn't Linux cache object and/or .so files when using GNU Linker?
It looks like an incorrect setting of vm.vfs_cache_pressure = 1000 was causing this misbehaviour. Setting it to 70 fixed the problem and restored good cache performance.
And the documentation explicitly recommends against increasing the value beyond 100. Unfortunately, the Internet is full of examples with insane values like 1000.
Some questions about ELF file format
xxd
shows the offset of the bytes within the file on disk.objdump -D
shows (tentatively) the address in memory where those bytes will be loaded when the program is run. It is common for them to differ by a round number. In particular,0x400000
may correspond to one higher-level page table entry; see Why Linux/gnu linker chose address 0x400000? which is for x86-64 but I think ARM64 is similar (haven't checked). It doesn't have anything to do with the fact that0x40
is ASCII@
; that's just a coincidence.Note that if ASLR is in use, the actual memory address will be randomly chosen every time the program is run, and will not match what
objdump
shows you, though the difference will still be a multiple of the page size.
Related Topics
How to Have Simple and Double Quotes in a Scripted Ssh Command
Why Does Printf Overwrite the Ecx Register
Count Number of Files Within a Directory in Linux
Docker Command Can't Connect to Docker Daemon
How to Run Crontab Job Every Week on Sunday
Generating a Sha-256 Hash from the Linux Command Line
How to Run Nginx Within a Docker Container Without Halting
Vim Configuration for Linux Kernel Development
How to Edit /Etc/Sudoers from a Script
Get Yesterday's Date in Bash on Linux, Dst-Safe
Linux: Where Are Environment Variables Stored
Should I Use Libc++ or Libstdc++
Bash: Infinite Sleep (Infinite Blocking)
Linux Vi Arrow Keys Broken in Insert Mode
Converting Serial Port Data to Tcp/Ip in a Linux Environment