Nick thats sort of the plan yes, in terms of implementing services as normal shared libraries/executables.
I've started working on a ELF loader, FASM can output straight to ELF executable format without a linker it seems.. which is fantastic
Amethana, I'm not sure how you got that right exactly, for example mov al,[aVariable] is RIP-relative... but mov al,[aVariable+rdi] isn't... which means to make all your code rip relative you'd have to pay really close attention all the time and avoid most of the helpful addressing modes?
On the ELF file side the format does seem to be really simple, i made a small test app with fasm and outputed to elf exe, then manually went through the file to validate it against the spec.. it seems 100% the only thing that i'm not 100% sure of is the following:... there is the file header, 2 program headers for code and data, then the code.. there doesn't seem to be any sections, and no relocation symbol tables or anything.. here is the breakdown:
Code: Select all
format ELF64 executable at 0
USE64 ; Enable 64bit Code Assembly.
include 'c:/fasm/include/macro/struct.inc' ; FASM Structures.
offset equ ; Allow FASM to support OFFSET directive.
segment readable executable
entry $
xor rdi,rdi
inc rdi
;mov al,[aVariable] ;rip relative
mov al,[aVariable+rdi] ;not rip
ret
segment readable writable
aVariable db 23h
bVariable db 24h
the binary elf exe:
7F454C46020101000000000000000000
02003E0001000000B000000000000000
40000000000000000000000000000000
00000000400038000200400000000000
0100000005000000B000000000000000
B000000000000000B000000000000000
0D000000000000000D00000000000000
00100000000000000100000006000000
BD00000000000000BD10000000000000
BD100000000000000200000000000000
02000000000000000010000000000000
4831FF48FFC78A87BD100000C323
which leads to a manual break-down:
;elf_header:
; db 7fh,'ELF'
; db ELFCLASS64 ; EI_CLASS (1 for 32-bit, 2 for 64-bit objects)
; db ELFDATALSB ; EI_DATA encoding (1 little-endian, 2 big-endian)
; db 1 ; EI_VERSION (has the value EV_CURRENT, which is defined with the value 1)
; db ELFOSABI_SYSV ; EI_OSABI
; db 0 ; EI_ABIVERSION
; times 7 db 0
;
; dw ET_EXEC ; e_type Object file type (ET_EXEC 2 Executable file)
; dw 3Eh ; e_machine Machine type
; dd 1 ; e_version Object file version
; dq 0xb0 ; e_entry Entry point address
; dq 0 ; e_phoff Program header offset
; dq 0 ; e_shoff Section header offset
; dd 0 ; e_flags Processor-specific flags
; dw 0 ; e_ehsize ELF header size
; dw 0 ; e_phentsize Size of program header entry
; dw 2 ; e_phnum Number of program header entries
; dw 40h ; e_shentsize Size of section header entry
; dw 0 ; e_shnum Number of section header entries
; dw 0 ; e_shstrndx Section name string table indexehdrsize = $ - $$
;
;prog_headers:
; dd PT_LOAD ; Segment Type
; dd PF_R OR PF_X ; Segment Attrib. Read/Execute
; dq 0xb0 ; p_offset contains the offset, in bytes, of the segment from the beginning of the file.
; dq 0xb0 ; p_vaddr contains the virtual address of the segment in memory.
; dq 0xb0 ; p_paddr is reserved for systems with physical addressing.
; dq 0xa0 ; p_filesz contains the size, in bytes, of the file image of the segment.
; dq 0xa0 ; p_memsz contains the size, in bytes, of the memory image of the segment.
; dq 0x1000 ; p_align specifies the alignment constraint for the segment. Must be a power of two. The values of p_offset and p_vaddr must be congruent modulo the alignment.
; dd PT_LOAD ; Segment Type
; dd PF_R OR PF_W ; Segment Attrib. Read/Write
; dq 0xba ; p_offset contains the offset, in bytes, of the segment from the beginning of the file.
; dq 0x10ba ; p_vaddr contains the virtual address of the segment in memory.
; dq 0x10ba ; p_paddr is reserved for systems with physical addressing.
; dq 0x01 ; p_filesz contains the size, in bytes, of the file image of the segment.
; dq 0x01 ; p_memsz contains the size, in bytes, of the memory image of the segment.
; dq 0x1000 ; p_align specifies the alignment constraint for the segment. Must be a power of two. The values of p_offset and p_vaddr must be congruent modulo the alignment.
ELFCLASS32 = 1 ; 32bit object,executable
ELFCLASS64 = 2 ; 64bit object,executable
ELFDATALSB = 1 ; Little-Endian Data Format
ELFDATAMSB = 2 ; Big-Endian Data Format
ELFOSABI_SYSV = 0 ; System V ABI
ELFOSABI_HPUX = 1 ; HP-UX operating system
ELFOSABI_STANDALONE = 255 ; Standalone, embedded application
; ELF File Types
ET_NONE = 0 ; No file type
ET_REL = 1 ; Relocatable object file
ET_EXEC = 2 ; Executable file
ET_DYN = 3 ; Shared object file
ET_CORE = 4 ; Core file
ET_LOOS = 0xFE00 ; Environment-specific use
ET_HIOS = 0xFEFF
ET_LOPROC = 0xFF00 ; Processor-specific use
ET_HIPROC = 0xFFFF
; ELF Segment Types
PT_NULL = 0 ; Unused entry
PT_LOAD = 1 ; Loadable segment
PT_DYNAMIC = 2 ; Dynamic linking tables
PT_INTERP = 3 ; Program interpreter path name
PT_NOTE = 4 ; Note sections
PT_SHLIB = 5 ; Reserved
PT_PHDR = 6 ; Program header table
PT_LOOS = 0x60000000 ; Environment-specific use
PT_HIOS = 0x6FFFFFFF
PT_LOPROC = 0x70000000 ; Processor-specific use
PT_HIPROC = 0x7FFFFFFF
; ELF Segment Attributes
PF_X = 0x1 ; Execute permission
PF_W = 0x2 ; Write permission
PF_R = 0x4 ; Read permission
PF_MASKOS = 0x00FF0000 ; These flag bits are reserved for environment-specific use
PF_MASKPROC = 0xFF000000 ; These flag bits are reserved for processor-specific use
The confusing part then is:
4831FF(xor), 48FFC7(inc),8A87BD100000(mov),C3 (ret),2324 (data)
now the mov uses address: 0x000010bd .. which is the address of data byte 23 (first byte in the data segment) (in terms of addressing mode it'll add rdi).. but the point is now that value should be absolute, non-rip relative and has been calculated from the base of the segment with alignment 1000h .. now i could remove the header "at 0" part.. but I still don't get a table that would allow me to relocate/patch these address if I load to a different location other than 0?