Executing an ELF executable How to load an
Executing an ELF executable How to load an executable ELF file for execution in ‘extended’ physical memory
What is ‘Extended Memory’? extended memory conventional memory 8086/8088 (20 -bit addresses) 1 MB 16 MB conventional memory 80286 (24 -bit addresses) 80386+ (32 -bit addresses) 4 GB
8086/8088 addresses Logical Address 0 x 23450 + 0 x 09876 -------0 x 2 CCC 6 segment-address offset-address 0 x 2345 0 x 9876 x 16 + Physical Address (20 -bits) 0 x 2 CCC 6
Biggest 8086/8088 address Logical Address 0 x. FFFF 0 + 0 x 0 FFFF -------0 x 10 FFEF segment-address offset-address 0 x. FFFF x 16 + Physical Address (20 -bits) A 20 0 x 0 FFEF
Emulating 8086/8088 on 80286 • Special circuitry provided to ‘disable’ the 21 st address-line (named A 20) causes addresses to ‘wrap’ at the 1 MB boundry • Original IBM-AT used keyboard controller to perform enabling/disabling of A 20 -line • Newer machines have faster ways to enable/disable A 20 -line (e. g. , port 0 x 92)
Effect of A 20 address-line Highest real-mode address (= 0 x 10 FFEF) Extra 64 K Same 64 K Highest 20 -bit address (= 0 x 0 FFFFF) memory differs at these places same memory appears at two places “extended” memory is above 1 MB “conventional” memory is below 1 MB A 20 enabled A 20 disabled
port 0 x 92 7 6 5 4 3 2 1 FAST A 20 0 FAST RESET (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 # how you can turn on the A 20 address-line in or out $0 x 92, %al $0 x 02, %al, $0 x 92 reset the CPU (1=yes, 0=no) enable A 20 -line (1=yes, 0=no)
Comparing A 20 on/off 0 x 00 A 00000 0 x 00900000 0 x 00800000 0 x 00700000 0 x 00600000 0 x 00500000 0 x 00400000 0 x 00300000 0 x 00200000 0 x 00100000 0 x 0000 Memory-addresses in one-megabyte increments 9999999 8888888888888 7777777 6666666666666 5555555 4444444444444 3333333 2222222222222 1111111 0000000000000 Extended Memory seen by the CPU when A 20 is on 0000000 Extended Memory seen by the CPU when A 20 is off
‘Executable’ versus ‘Linkable’ ELF Header Program-Header Table (optional) Program-Header Table Section 1 Data Segment 1 Data Section 2 Data Segment 2 Data Section 3 Data Segment 3 Data … Section n Data … Segment n Data Section-Header Table (optional) Linkable File Executable File
Linker ‘relocates’ addresses ELF Header Section 1 Data Section 2 Data … Section n Data ELF Header Program-Header Table Segment 1 Data Section-Header Table Linkable File Segment 2 Data ELF Header … Segment n Data Section 1 Data Section 2 Data … Section n Data Section-Header Table 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 commandoption: $ ld -verbose
ELF 32 File Header 32 -bit or 64 -bit ΔELF Initial value for EIP register class type program entry-point PHT entry size PHT file-offset PHT entry count PHT = Program-segment Header-Table ‘Executable’ or ‘Linkable’
PHT entries Fields in an ELF 32 Program-segment Header Table entry p_type p_offset p_vaddr p_paddr p_filesz p_memsz p_flags p_align 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_i 386 linuxapp. o –o linuxapp $ dd if=linuxapp of=/dev/sda 4 seek=65 • We’ll need modifications to our ‘tryelf 32. 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 0 x 08048000 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 4 GB using Descriptor Privilege Level (DPL) =3 • For our (32 -bit) data-segment: . quad 00 CFF 2000000 FFFF # 4 GB-data • For our (32 -bit) code-segment: . quad 00 CF 7 A 000000 FFFF # 4 GB-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 ring 3 stack? 0 x 40000000 (at 1 -GB) ESP ring 3 stack . bss. data EIP . text Our OS IVT and BDA 0 x 08049000 0 x 08048000 0 x 00010000 0 x 0000
Demos • Our ‘elfexec. s’ program demonstrates the simulation of ‘on-demand loading’ for two ‘executable’ ELF 32 files on our website: – ‘linuxapp’ (which we’ve used previously) – ‘usingbss’ (which illustrates ‘. bss’ loading) • Our ‘elfinfo. cpp’ utility aids in examining an ELF 32 files’s PHT entries and entry-point
- Slides: 19