Executing an ELF executable How to load an executable ELF physical memory

advertisement
Executing an ELF executable
How to load an executable ELF
file for execution in ‘extended’
physical memory
What is ‘Extended Memory’?
extended
memory
4GB
extended
memory
conventional
memory
8086/8088
(20-bit addresses)
1MB
16MB
conventional
memory
conventional
memory
80286
(24-bit addresses)
80386+
(32-bit addresses)
8086/8088 addresses
Logical Address
0x23450
+ 0x09876
--------------0x2CCC6
segment-address
offset-address
0x2345
0x9876
x16
+
Physical Address
(20-bits)
0x2CCC6
Biggest 8086/8088 address
Logical Address
0xFFFF0
+ 0x0FFFF
--------------0x10FFEF
segment-address
offset-address
0xFFFF
0xFFFF
x16
+
Physical Address
(20-bits)
A20
0x0FFEF
Emulating 8086/8088 on 80286
• Special circuitry provided to ‘disable’ the
21st 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)
port 0x92
7
6
5
4
3
2
1
FAST
A20
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 A20 address-line
in
or
out
$0x92, %al
$0x02, %al
%al, $0x92
reset the CPU
(1=yes, 0=no)
enable A20-line
(1=yes, 0=no)
Effect of A20 address-line
Highest real-mode address (= 0x10FFEF)
Extra 64K
Same 64K
Highest 20-bit address (= 0x0FFFFF)
memory
differs
at these
places
same
memory
appears
at two
places
“extended” memory
is above 1MB
“conventional” memory
is below 1 MB
A20 enabled
A20 disabled
Executable versus Linkable
ELF Header
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
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/sda4 seek=13
• We need modifications to our ‘try32bit.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 0x08048000 and
0x08049000, 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 4GB
using Descriptor Privilege Level (DPL) =3
• For our (32-bit) code-segment:
.word 0xFFFF, 0x0000, 0xFA00, 0x00CF
• For our (32-bit) data-segment:
.word 0xFFFF, 0x0000, 0xF200, 0x00CF
• For our (32-bit) stack-segment:
.word 0xFFFF, 0x0000, 0xF200, 0x00CF
Loading the ‘.text’ and ‘.data’
• ELF file-image fits within three disk sectors
(#14-#16), so total size is at most 0x0600
• So we can copy the entire ELF file-image
from address 0x00011800 to 0x08048000
to initialize our ‘.text’ program-segment
• And we can copy the entire ELF file-image
from address 0x00011800 to 0x08049000
to initialize our ‘.data’ program-segment
Copying ‘hello’
# copying .text section
.code32
mov
$sel_FS, %ax
mov
%ax, %ds
mov
%ax, %es
mov
$0x00011800, %esi
mov
$0x08048000, %edi
cld
mov
$0x800, %ecx
rep
movsb
# copying .data section
.code32
mov
$sel_FS, %ax
mov
%ax, %ds
mov
%ax, %es
mov
$0x00011800, %esi
mov
$0x08049000, %edi
cld
mov
$0x800, %ecx
rep
movsb
The ‘hello’ executable ELF file easily fits within 4 hard-disk sectors (= 0x800 bytes)
Initial values for ESP and EIP
• The program’s entry-point is 0x08048074
(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 ring3 stack?
.data
EIP
ESP
.text
0x08049000
0x08048000
ring3 stack
OS630
IVT and BDA
0x00010000
0x00000000
In-Class Exercise
• Make a copy of our ‘try32bit.s’ demo (from our
CS630 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
pushl
pushl
pushl
lret
$userSS
$0x08048000
$userCS
$0x08048074
; image for SS
; image for ESP
; image for CS
; image for EIP
; execute ‘hello’
Download