Executing an ELF executable How to load an executable ELF file for execution in ‘extended’ physical memory
What is ‘Extended Memory’? conventional memory conventional memory conventional memory 8086/8088 (20-bit addresses) extended memory extended memory 4GB (32-bit addresses) 16MB (24-bit addresses) 1MB
8086/8088 addresses 0x23450x9876 0x2CCC6 segment-addressoffset-address + x16 Logical Address Physical Address (20-bits) 0x x x2CCC6
Biggest 8086/8088 address 0xFFFF 0x0FFEF segment-addressoffset-address + x16 Logical Address Physical Address (20-bits) 0xFFFF0 + 0x0FFFF x10FFEF A20
Emulating 8086/8088 on Special circuitry provided to ‘disable’ the 21 st address-line (named A20) causes addresses to ‘wrap’ at the 1MB boundry Original IBM-AT used keyboard controller to perform enabling/disabling of A20-line Newer machines have faster ways to enable/disable A20-line (e.g., port 0x92)
Effect of A20 address-line Extra 64KSame 64K A20 enabled A20 disabled Highest 20-bit address (= 0x0FFFFF) Highest real-mode address (= 0x10FFEF) “extended” memory is above 1MB “conventional” memory is below 1 MB same memory appears at two places memory differs at these places
port 0x92 FAST A20 FAST RESET reset the CPU (1=yes, 0=no) enable A20-line (1=yes, 0=no) # how you can turn on the A20 address-line in$0x92, %al or$0x02, %al out%al, $0x92 (These bits may implement some other system functions, depending on the vendor’s design (not standardized), so beware of modifying them in ‘portable’ system software
Comparing A20 on/off Extended Memory seen by the CPU when A20 is on Extended Memory seen by the CPU when A20 is off 0x x x x x x x x x x x00A00000 Memory-addresses in one-megabyte increments
Section-Header Table (optional) ‘Executable’ versus ‘Linkable’ ELF Header Section 2 Data Section 3 Data … Section n Data Segment 1 Data Segment 2 Data Segment 3 Data … Segment n Data Linkable FileExecutable File Section-Header Table Program-Header Table (optional) Program-Header Table ELF Header Section 1 Data
Linker ‘relocates’ addresses ELF Header Section-Header Table Section 1 Data Section 2 Data … Section n Data ELF Header Section-Header Table Section 1 Data Section 2 Data … Section n Data ELF Header Program-Header Table Segment 1 Data Segment 2 Data … Segment n Data Linkable File Executable File
The ‘built-in’ linker script Two main ideas that the linker implements: –It combines identically-named sections of the linkable ELF files into a single segment –It assigns runtime addresses to the resulting program data and program code which are non-conflicting and are suitably aligned It may optionally perform other manipulations, depending on directions in its linker script It uses a built-in linker script if you don’t specify otherwise; you can view it using the command- option:$ ld -verbose
ELF32 File Header ΔELF class type program entry-point PHT file-offset PHT entry size PHT entry count ‘Executable’ or ‘Linkable’ 32-bit or 64-bit PHT = Program-segment Header-Table Initial value for EIP register
PHT entries p_type p_offset p_vaddr p_paddr p_filesz p_memsz p_flags p_align Fields in an ELF32 Program-segment Header Table entry Our ‘elfexec.s’ program-loader uses these highlighted fields to simulate program-loading (i.e., to initialize the regions in Extended memory which are needed for program execution
In-Class demo Suppose we want to execute ‘linuxapp’ using our own custom OS environment Boot-disk preparation steps: $ as –32 linuxapp.s –o linuxapp.o $ ld –melf_i386 linuxapp.o –o linuxapp $ dd if=linuxapp of=/dev/sda4 seek=65 We’ll need modifications to our ‘tryelf32.s’
The two program-segments When used without any linker script, our GNU linker-utility (‘ld’) relocates the ‘.text’ and ‘.data’ and ‘.bss’ program-segments, for residence at specific memory-addreses far above the 1-MB conventional ‘real-mode’ memory-area The memory-address 0x is standard for the relocation of an Elf_32 code-segment So we will need to ‘copy’ some portions of the executable ELF-file’s contents to the specified addresses in ‘Extended’ physical memory
New segment-descriptors We can setup segment-limits of size 4GB using Descriptor Privilege Level (DPL) =3 For our (32-bit) data-segment:.quad 00CFF FFFF# 4GB-data For our (32-bit) code-segment:.quad 00CF7A000000FFFF# 4GB-code Both these segments include all memory It’s useful to mark code as ‘Not Present’
Initial values for ESP and EIP The program’s entry-point is obtained from the.e_entry; field in the ELF-file’s Header) The decision about an initial value for ESP is largely up to us, taking into account the amount of physical memory installed and the regions of memory already being used for other system purposes
Where’s our ring3 stack?.data.text 0x x Our OS 0x IVT and BDA 0x ESP ring3 stack EIP 0x (at 1-GB).bss
Demos Our ‘elfexec.s’ program demonstrates the simulation of ‘on-demand loading’ for two ‘executable’ ELF32 files on our website: –‘linuxapp’ (which we’ve used previously) –‘usingbss’ (which illustrates ‘.bss’ loading) Our ‘elfinfo.cpp’ utility aids in examining an ELF32 files’s PHT entries and entry-point