28
Interfacing with ELF files An introduction to the Executable and Linkable Format (ELF) binary file specification standard

Interfacing with ELF files

  • Upload
    aiden

  • View
    47

  • Download
    0

Embed Size (px)

DESCRIPTION

Interfacing with ELF files. An introduction to the Executable and Linkable Format (ELF) binary file specification standard. Overview of source translation. User-created files. C/C++ Source and Header Files. Assembly Source Files. Makefile. C/C++ Source and Header Files. - PowerPoint PPT Presentation

Citation preview

Page 1: Interfacing with ELF files

Interfacing with ELF files

An introduction to the Executable and Linkable Format (ELF) binary

file specification standard

Page 2: Interfacing with ELF files

Library Files

Object Files

Assembly Source

Files

C/C++ Source and Header

Files

Overview of source translation

MakefileC/C++ Source

and HeaderFiles

Assembly Source

Files

Linker Script

File

User-created files

preprocessor

compiler assembler

Make Utility

Object Files

Shared Object

File

Linkable Image File

Executable Image File

Link Map File

Linker and Locator Library Files

Archive Utility

Page 3: Interfacing with ELF files

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 File Executable File

Section-Header Table

Program-Header Table(optional)

Program-Header Table

ELF Header

Section 1 Data

Page 4: Interfacing with ELF files

Role of the Linker

ELF Header

Section-Header Table

Section 1 DataSection 2 Data

…Section n Data

ELF Header

Section-Header Table

Section 1 DataSection 2 Data

…Section n Data

ELF Header

Program-Header Table

Segment 1 Data

Segment 2 Data

…Segment n Data

Linkable File

Linkable File

Executable File

Page 5: Interfacing with ELF files

ELF Header

e_type e_machine e_version e_entry e_phoff

e_shoff e_flags e_ehsize e_phentsize e_phnum e_shentsize

e_shnum e_shstrndx

e_ident [ EI_NIDENT ]

Section-Header Table: e_shoff, e_shentsize, e_shnum, e_shstrndx

Program-Header Table: e_phoff, e_phentsize, e_phnum, e_entry

Page 6: Interfacing with ELF files

Section-Headers

sh_name sh_type sh_flags sh_addr sh_offset

sh_size sh_link sh_info sh_addralign sh_entsize

Page 7: Interfacing with ELF files

Program-Headers

p_type p_offset p_vaddr p_paddr

p_filesz p_memsz p_flags p_align

Page 8: Interfacing with ELF files

Official ELF documentation

• The official document that describes ELF file-formats for both the ‘linkable’ and the ‘executable’ files is available online on our CS630 course website (see ‘Resources’)

• (Recently this document has been revised to accommodate programs that will run on platforms that implement 64-bit addresses and processor registers)

Page 9: Interfacing with ELF files

Memory: Physical vs. Virtual

VirtualAddressSpace(4 GB)

Physicaladdress space

(2 GB)

Portions of physical memory are “mapped” by the CPU into regions of each task’s ‘virtual’ address-space

Page 10: Interfacing with ELF files

Linux ‘Executable’ ELF files

• The Executable ELF files produced by the Linux linker are configured for execution in a private ‘virtual’ address space, whereby every program gets loaded at the identical virtual memory-address (i.e., 0x08048000)

• We will soon study the Pentium’s paging mechanism which makes this possible (i.e., after we have finished Project #1)

Page 11: Interfacing with ELF files

Linux ‘Linkable’ ELF files

• But it is possible that some ‘linkable’ ELF files are self-contained (i.e., they may not need to be linked with other object-files or shared libraries)

• Our ‘manydots.o’ is one such example• So we can write our own system-code that

can execute the instructions contained in a stand-alone ‘linkable’ object-module, using the CPU’s ‘segmented’ physical memory

Page 12: Interfacing with ELF files

Our ‘loadmap.cpp’ utility

• We created a tool that ‘parses’ a linkable ELF file, to identify each section’s length, type, and location within the object-module

• For those sections containing the ‘text’ and ‘data’ for the program, we build segment-descriptors, based on where the linkable image-file will reside in physical memory

Page 13: Interfacing with ELF files

32-bit versus 16-bit code

• The Linux compilers, and the ‘as’ assembler, produce object-files that are intended to reside in ’32-bit’ memory-segments (i.e., the ‘default’ bit in the segment-descriptor is set to 1)

• This affects the CPU’s interpretation of all the machine-instructions that it fetches

• Our ‘as’ assembler can produce either 16-bit or 32-bit code (although its default is 32-bit code)

• We can employ ‘.code32’ or ‘.code16’ directives

Page 14: Interfacing with ELF files

Example: ‘as’ Listing

.code320x0000 01 D8 add %eax, %ebx0x0002 66 01 D8 add %ax, %bx0x0005 90 nop

.code160x0006 66 01 D8 add %eax, %ebx0x0009 01 D8 add %ax, %bx0x000B 90 nop

.end

Page 15: Interfacing with ELF files

Demo-program

• We created a Linux program (‘hello.s’) that invokes two system-calls (‘write’ and ‘exit’)

• We assembled it with the ‘as’ assembler:$ as hello.s –o hello.o

• This linkable ELF object-file ‘hello.o’ should then be written to our hard disk partition (‘/dev/sda4’) at sector address 13, using the Linux ‘dd’ utility:

$ dd if=hello.o of=/dev/sda4 seek=13

• So it will get loaded into memory by ‘quikload’

Page 16: Interfacing with ELF files

Memory-Map

IVT

ROM-BIOS DATA

BOOT-LOADER

‘try32bit.b’image

Loaded into ramfrom sectors 1..16 of disk-partition by our ‘quikload.b’ program-loader

0x00010000

0x00011800

0x00000400

0x00007C00 ‘quikload.b’ reads from CS630 disk partition via ROM-BIOS bootstrap

‘hello.o’ image

Page 17: Interfacing with ELF files

Segment Descriptors

• We created 32-bit segment-descriptors for the ‘text’ and ‘data’ sections of ‘hello.o’ (in a Local Descriptor Table) with DPL=3

• For the ‘.text’ section: offset in ELF file = 0x34 size = 0x23

• So its segment-descriptor is:

.word 0x0023, 0x1834, 0xFA01, 0x0040

(base-address = load-address + file-offset)

Page 18: Interfacing with ELF files

Descriptors (continued)

• For the ‘.data’ section:offset in ELF file = 0x58 size = 0x0D

• So its segment-descriptor is: .word 0x000D, 0x1858, 0xF201, 0x0040

(base-address = load-address + file-offset)

• For the ring3 stack (not part of ELF file): .word 0x0FFF, 0x2100, 0xF201, 0x0040

Page 19: Interfacing with ELF files

Task-State Segment

• Because any system-calls (via int 0x80) will cause privilege-level transitions, we will need to setup a Task-State Segment (to store the ring0 stacktop pointer)

theTSS: .long 0, 0, 0 # 3 longwords

• Its segment-descriptor goes into our GDT:

.word 0x000B, theTSS, 0x8901, 0x0000

Page 20: Interfacing with ELF files

Transition to Ring 3

• Recall that we use ‘lret’ to enter ring 3:pushw $userSSpushw $0x1000pushw $userCSpushw $0x0000lret

(NOTE: This assumes we are coming from a 16-bit code-segment in protected-mode)

Page 21: Interfacing with ELF files

System-Call Dispatcher

• All system-calls are ‘vectored’ through IDT interrupt-gate 0x80

• For ‘hello.o’ we only require implementing two system-calls: ‘exit’ and ‘write’

• But to simplify future enhancements, we used a ‘jump-table’ anyway (for now it has a few ‘dummy’ entries that we can modify later)

Page 22: Interfacing with ELF files

System-Call ID-numbers

• System-call ID #0 (it will never be needed)• System-call ID #1 is for ‘exit’ (required)• System-call ID #2 is for ‘fork’ (deferred)• System-call ID #3 is for ‘read’ (deferred)• System-call ID #4 is for ‘write’ (required)• System-call ID #5 is for ‘open’ (deferred)• System-call ID #6 is for ‘close’ (deferred)(NOTE: over 200 system-calls exist in Linux)

Page 23: Interfacing with ELF files

Defining our jump-table

sys_call_table:

.longdo_nothing # for service 0

.longdo_exit # for service 1

.longdo_nothing # for service 2

.longdo_nothing # for service 3

.longdo_write # for service 4

.equ NR_SYS_CALLS, ( . - sys_call_table)/4

Page 24: Interfacing with ELF files

Setting up IDT Gate 0x80

• The Descriptor Privilege Level must be 3

• The Gate-Type should be ‘386 Trap-Gate’

• The entry-point will be our ‘isrSVC’ label

# Interrupt Descriptor Table’s entry for SuperVisor Call (int $0x80)

mov $0x80, %ebx # table-entry array-indexlea theIDT(, %ebx, 8), %edi # descriptor offset-addressmovw $isrSVC, 0(%edi) # entry-point offset’s lowordmovw $sel_CS, 2(%edi) # selector for code-segmentmovw $0xEF00, 4(%edi)# Gate-Type: 386 Trap-Gatemovw $0x0000, 6(%edi) # entry-point offset’s hiword

Page 25: Interfacing with ELF files

Using our jump-table

isrSVC: # service-number is found in EAX

cmp $NR_SYS_CALLS, %eax

jb idok

xor %eax, %eax

idok: jmp *sys_call_table(, eax, 4)

Page 26: Interfacing with ELF files

Our ‘exit’ service

• When the application invokes the ‘exit’ system-call, our mini ‘operating system’ should leave protected-mode and return back to our boot-loader program

• The ‘exit-code’ parameter (in %ebx) may just as well be discarded (since this isn’t yet a multitasking operating-system)

Page 27: Interfacing with ELF files

Our ‘write’ service

• We only implement writing to the STDOUT device (i.e., the video display terminal)

• For most characters in the user’s buffer, we just write the ascii-code (and standard display-attribute) directly to video memory at the current cursor-location and advance the cursor (scrolling the screen if needed)

• Special ascii control-codes (‘\n’, ‘\r’, ‘\b’) are treated differently, as on a TTY device

Page 28: Interfacing with ELF files

In-Class Exercise

• The ‘manydots.s’ demo (to be used with Project #1) uses the ‘read’ system-call (in addition to the ‘write’ and ‘exit’ services)

• However, you could still ‘execute’ it using the ‘try32bit.s’ mini operating-stem, letting the ‘read’ service simply “do nothing” (or return with “hard-coded” buffer-contents)

• Just modify the LDT descriptors so they conform to the sections in ‘manydots.o’