ELF Base Address

I am trying to find the base address of ELF files. I know that you can use readelf to find the entry point to the program and various section details (base address, size, flags, etc.).

For example, programs for the x86 architecture are based on the 0x8048000 linker. using readelf I can see the entry point to the program, but no specific output field reports the base address.

$ readelf -e test ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2 complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x8048390 Start of program headers: 52 (bytes into file) Start of section headers: 4436 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 9 Size of section headers: 40 (bytes) Number of section headers: 30 Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4 [ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4 [ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000024 04 A 5 0 4 [ 5] .dynsym DYNSYM 080481d0 0001d0 000070 10 A 6 1 4 

In the details of the section, I see that the offset is calculated relative to the ELF base address.

So, the .dynsym section starts with the address, 0x080481d0 and the offset 0x1d0. This means that the base address is 0x08048000. Is it correct?

Similarly, for programs compiled on different architectures, such as PPC, ARM, MIPS, I do not see their base address, but only OEP, Section Headers.

+4
source share
2 answers

You need to check the segment table as the program header ( readelf -l ).

 Elf file type is EXEC (Executable file) Entry point 0x804a7a0 There are 9 program headers, starting at offset 52 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 RE 0x4 INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1 [Requesting program interpreter: /lib/ld-linux.so.2] LOAD 0x000000 0x08048000 0x08048000 0x10fc8 0x10fc8 RE 0x1000 LOAD 0x011000 0x08059000 0x08059000 0x0038c 0x01700 RW 0x1000 DYNAMIC 0x01102c 0x0805902c 0x0805902c 0x000f8 0x000f8 RW 0x4 NOTE 0x000168 0x08048168 0x08048168 0x00020 0x00020 R 0x4 TLS 0x011000 0x08059000 0x08059000 0x00000 0x0005c R 0x4 GNU_EH_FRAME 0x00d3c0 0x080553c0 0x080553c0 0x00c5c 0x00c5c R 0x4 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 

The first (lowest) LOAD segment virtual address is the default load base for the file. You can see this 0x08048000 for this file.

+9
source

Defined in the linker script. You can reset the default linker script using ld --verbose . Output Example:

 GNU ld (GNU Binutils) 2.23.1 Supported emulations: elf_x86_64 elf32_x86_64 elf_i386 i386linux elf_l1om elf_k1om using internal linker script: ================================================== /* Script for -z combreloc: combine and sort reloc sections */ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") OUTPUT_ARCH(i386:x86-64) ENTRY(_start) SEARCH_DIR("/nix/store/kxf1p7l7lgm6j5mjzkiwcwzc98s9f1az-binutils-2.23.1/x86_64-unknown-linux-gnu/lib64"); SEARCH_DIR("/nix/store/kxf1p7l7lgm6j5mjzkiwcwzc98s9f1az-binutils-2.23.1/lib64"); SEARCH_DIR("/nix/store/kxf1p7l7lgm6j5mjzkiwcwzc98s9f1az-binutils-2.23.1/x86_64-unknown-linux-gnu/lib"); SEARCH_DIR("/nix/store/kxf1p7l7lgm6j5mjzkiwcwzc98s9f1az-binutils-2.23.1/lib"); SECTIONS { /* Read-only sections, merged into text segment: */ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS; .interp : { *(.interp) } .note.gnu.build-id : { *(.note.gnu.build-id) } .hash : { *(.hash) } .gnu.hash : { *(.gnu.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } 

(notch)

If you missed it: __executable_start = SEGMENT_START("text-segment", 0x400000)) .

And for me, of course, when I link a simple .o file in binary format, the entry point address is very close to 0x400000.

The entry point address in the ELF metadata is the value plus the offset from the beginning of the .text section to the _start character. Also note that the _start character is customizable. Again from my link builder script: ENTRY(_start) .

0
source

Source: https://habr.com/ru/post/1497641/


All Articles