Calculate the entry point of an ELF file as a physical address (offset from 0)
My question is: what is the actual "formula" of how exactly you get the entry point address of the _start procedure as an offset from byte 0?
First, forget about sections. Only segments matter at runtime.
Second, use readelf -Wl
to look at segments. They tell you exactly which chunk of file ([.p_offset, .p_offset + .p_filesz)
) goes into which in-memory region ([.p_vaddr, .p_vaddr + .p_memsz)
).
The exact calculation of "at which offset in the file does _start
reside" is:
- Find
Elf32_Phdr
which "covers" the address contained inElf32_Ehdr.e_entry
. - Using that
phdr
, file offset of_start
is:ehdr->e_entry - phdr->p_vaddr + phdr->p_offset
.
Update:
So, am I always looking for the 1st program header?
No.
Also by "covers" you mean that the 1st phdr->p_vaddr is always equal to e_entry?
No.
You are looking for a the program header (describing relationship between in-memory and on-file data) which overlaps the ehdr->e_entry
in memory. That is, you are looking for the segment for which phdr->p_vaddr <= ehdr->e_entry && ehdr->e_entry < phdr->p_vaddr + phdr->p_memsz
. This segment is often the first, but that is in no way guaranteed. See also this answer.
Why can I get the elf entry without the help of a base address?
The linker, as a rule, doesn't really care where in memory it places anything. It's primary job is to make sure that all memory references are consistent, no matter how memory is laid out. The purpose of a linker script is to tell the linker how to lay out the memory. If you don't provide a linker script, it will use its own defaults. In other words, the linker doesn't know or care whether you have something already loaded at 0x4000. It's your job to know how your memory is laid out, and to provide a linker script if you want it laid out in a specific way.
As for the -no-pie
bit of the question, that comes down to how position-independent and non-position-independent executables are loaded. Your UEFI bootloader is, among other things, a loader. There is a flag in the executable telling the loader whether or not it's a PIE. If it's not, then the loader just has to use the exact addresses encoded in the file. In this case, the elf->entry
pointer will be exactly correct. If it is a PIE, then the loader can place it at whatever memory address it likes, in which case the elf->entry
pointer will be relative to the address at which the executable is loaded. That's why you need to use base + elf->entry
when you don't provide the -no-pie
flag.
Is changing default virtual address in elf header to 0 possible?
Can I change the default virtual address(ph_vaddr) in the elf to 0x0.
Yes, that is in fact how PIE
(position independent) executables are usually linked.
echo "int main() { return 0; }" | gcc -xc - -fPIE -pie -o a.out
readelf -l a.out | grep LOAD | head -1
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
Note: above makes an executable that is of type ET_DYN
.
will this allow access to null pointer?
No. When the kernel discovers that the .e_type == ET_DYN
for the executable, it will relocate all of its segments elsewhere.
You can also make an executable of type ET_EXEC
with .p_vaddr == 0
, like so:
echo "int main() { return 0; }" | gcc -xc - -o a.out -Wl,-Ttext=0
readelf -l a.out | grep LOAD | head -1
LOAD 0x0000000000200000 0x0000000000000000 0x0000000000000000
The kernel will refuse to run it:
./a.out
Killed
Related Topics
Split and Rename The Splitted Files in Shell Script
Windows <Sys/File.H> Equivalent
How to Change The Desktop Wallpaper on Linux from Within a Shell/Bash Script
Autostart Javafx Application on Raspberrypi
How to Determine The Ip of The Computer That Connects to Me
How Does Sort Work Out How Much Ram There Is
Run a .Net Mvc5 Application on Mono
How to Get The Interrupt Vector Number on Linux
How Does Linux Handles The I/O Permission Bitmap in The Tss Structure
Grunt Karma Testing on Vagrant When Host Changes Sources Grunt/Karma Doesn't Detect It
Install Gulp Browserify Gives Error Always
Visual Studio 2017 Could Not Create Directories, Mkdir Exit Code: 1
Use Stdin from Within R Studio
Pass File Input and Stdin to Gdb
Question About Epoll and Splice
How to Link a Linux's Thread Tid and a Pthread_T "Thread Id"
Shared Library Mysteriously Doesn't Get Linked to Application