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)
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)
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
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
In-Class Exercise • We want to execute the ‘hello’ application in our own operating system environment • Boot-disk preparation steps: $ as hello. s –o hello. o $ ld hello. o –o hello $ dd if=hello of=/dev/sda 4 seek=13 • We need modifications to our ‘try 32 bit. s’
The two program-segments • When used without any linker script, our linker-utility (‘ld’) relocates the ‘. text’ and ‘. data’ program-segments for loading at the memory-addresses 0 x 08048000 and 0 x 08049000, respectively • So we will need to copy the contents of these two portions of our ELF executable image-file to those 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) code-segment: . word 0 x. FFFF, 0 x 0000, 0 x. FA 00, 0 x 00 CF • For our (32 -bit) data-segment: . word 0 x. FFFF, 0 x 0000, 0 x. F 200, 0 x 00 CF • For our (32 -bit) stack-segment: . word 0 x. FFFF, 0 x 0000, 0 x. F 200, 0 x 00 CF
Loading the ‘. text’ and ‘. data’ • ELF file-image fits within three disk sectors (#14 -#16), so total size is at most 0 x 0600 • So we can copy the entire ELF file-image from address 0 x 00011800 to 0 x 08048000 to initialize our ‘. text’ program-segment • And we can copy the entire ELF file-image from address 0 x 00011800 to 0 x 08049000 to initialize our ‘. data’ program-segment
Copying ‘hello’ # copying. text section. code 32 mov $sel_FS, %ax mov %ax, %ds mov %ax, %es mov $0 x 00011800, %esi mov $0 x 08048000, %edi cld mov $0 x 800, %ecx rep movsb # copying. data section. code 32 mov $sel_FS, %ax mov %ax, %ds mov %ax, %es mov $0 x 00011800, %esi mov $0 x 08049000, %edi cld mov $0 x 800, %ecx rep movsb The ‘hello’ executable ELF file easily fits within 4 hard-disk sectors (= 0 x 800 bytes)
Initial values for ESP and EIP • The program’s entry-point is 0 x 08048074 (as obtained from the file’s ELF 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? . data EIP ESP . text 0 x 08049000 0 x 08048000 ring 3 stack OS 630 IVT and BDA 0 x 00010000 0 x 0000
In-Class Exercise • Make a copy of our ‘try 32 bit. s’ demo (from our CS 630 course website), and modify it so it will execute the ‘hello’ ELF file-image • You’ll need to setup registers TR, DS, and ES • Then a code-fragment that will transfer control to ‘hello’ could look like this -- assuming it occurs in a 32 -bit code segment: pushl lret $user. SS $0 x 08048000 $user. CS $0 x 08048074 ; image for SS ; image for ESP ; image for CS ; image for EIP ; execute ‘hello’
- Slides: 18