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

Download Report

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

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)
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
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)
Comparing A20 on/off
0x00A00000
0x00900000
0x00800000
0x00700000
0x00600000
0x00500000
0x00400000
0x00300000
0x00200000
0x00100000
0x00000000
Memory-addresses
in one-megabyte
increments
9999999999999
8888888888888
8888888888888
8888888888888
7777777777777
6666666666666
6666666666666
6666666666666
5555555555555
4444444444444
4444444444444
4444444444444
3333333333333
2222222222222
2222222222222
2222222222222
1111111111111
0000000000000
0000000000000
Extended Memory
seen by the CPU
when A20 is on
0000000000000
Extended Memory
seen by the CPU
when A20 is off
‘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
ELF32 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 ELF32 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_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 0x08048000 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
00CFF2000000FFFF
# 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?
0x40000000
(at 1-GB)
ESP
ring3 stack
.bss
.data
EIP
.text
Our OS
IVT and BDA
0x08049000
0x08048000
0x00010000
0x00000000
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