ELFCLASSNONE = 0 ELFCLASS32 = 1 ELFCLASS64 = 2 ELFDATANONE = 0 ELFDATA2LSB = 1 ELFDATA2MSB = 2 ELFOSABI_NONE = 0 ELFOSABI_HPUX = 1 ELFOSABI_NETBSD = 2 ELFOSABI_GNU = 3 ELFOSABI_LINUX = 3 ELFOSABI_SOLARIS = 6 ELFOSABI_AIX = 7 ELFOSABI_IRIX = 8 ELFOSABI_FREEBSD = 9 ELFOSABI_TRU64 = 10 ELFOSABI_MODESTO = 11 ELFOSABI_OPENBSD = 12 ELFOSABI_OPENVMS = 13 ELFOSABI_NSK = 14 ELFOSABI_AROS = 15 ELFOSABI_FENIXOS = 16 ELFOSABI_CLOUDABI = 17 ELFOSABI_OPENVOS = 18 ET_NONE = 0 ET_REL = 1 ET_EXEC = 2 ET_DYN = 3 ET_CORE = 4 ET_LOPROC = 0xff00 ET_HIPROC = 0xffff EM_NONE = 0 EM_M32 = 1 EM_SPARC = 2 EM_386 = 3 EM_68K = 4 EM_88K = 5 EM_860 = 7 EM_MIPS = 8 EM_X86_64 = 62 EV_NONE = 0 EV_CURRENT = 1 PT_NULL = 0 PT_LOAD = 1 PT_DYNAMIC = 2 PT_INTERP = 3 PT_NOTE = 4 PT_SHLIB = 5 PT_PHDR = 6 PT_GNU_EH_FRAME = 0x6474e550 PT_GNU_STACK = 0x6474e551 PT_GNU_RELRO = 0x6474e552 PT_LOPROC = 0x70000000 PT_HIPROC = 0x7fffffff PF_X = 1 PF_W = 2 PF_R = 4 PF_MASKOS = 0x0ff00000 PF_MASKPROC = 0xf0000000 calminstruction align? boundary,value:? compute boundary, (boundary-1)-($-ELF.DYNAMIC+boundary-1) mod boundary arrange value, =db boundary =dup value assemble value end calminstruction ELF:: namespace ELF if defined Settings.Class CLASS := Settings.Class else CLASS := ELFCLASS32 end if if defined Settings.Type TYPE := Settings.Type else TYPE := ET_EXEC end if if defined Settings.Machine MACHINE := Settings.Machine else MACHINE := EM_386 end if if defined Settings.ABI ABI := Settings.ABI else ABI := ELFOSABI_NONE end if if TYPE = ET_DYN element DYNAMIC else DYNAMIC := 0 end if if defined Settings.BaseAddress BASE_ADDRESS := DYNAMIC + Settings.BaseAddress else BASE_ADDRESS := DYNAMIC + 8048000h end if if defined Settings.LoadHeaders LOAD_HEADERS := Settings.LoadHeaders else LOAD_HEADERS := 1 end if Header: e_ident db 0x7F,'ELF',CLASS,ELFDATA2LSB,EV_CURRENT,ABI,(16-$) dup 0 e_type dw TYPE e_machine dw MACHINE e_version dd EV_CURRENT if CLASS <> ELFCLASS64 e_entry dd start - DYNAMIC e_phoff dd ProgramHeader e_shoff dd 0 e_flags dd 0 e_ehsize dw ProgramHeader e_phentsize dw SEGMENT_HEADER_LENGTH e_phnum dw NUMBER_OF_SEGMENTS e_shentsize dw 28h e_shnum dw 0 e_shstrndx dw 0 else e_entry dq start - DYNAMIC e_phoff dq ProgramHeader e_shoff dq 0 e_flags dd 0 e_ehsize dw ProgramHeader e_phentsize dw SEGMENT_HEADER_LENGTH e_phnum dw NUMBER_OF_SEGMENTS e_shentsize dw 40h e_shnum dw 0 e_shstrndx dw 0 end if ProgramHeader: if CLASS <> ELFCLASS64 p_type dd PT_LOAD p_offset dd 0 p_vaddr dd BASE_ADDRESS - DYNAMIC p_paddr dd BASE_ADDRESS - DYNAMIC p_filesz dd 0 p_memsz dd 0 p_flags dd PF_R+PF_W+PF_X p_align dd 1000h else p_type dd PT_LOAD p_flags dd PF_R+PF_W+PF_X p_offset dq 0 p_vaddr dq BASE_ADDRESS - DYNAMIC p_paddr dq BASE_ADDRESS - DYNAMIC p_filesz dq 0 p_memsz dq 0 p_align dq 1000h end if SEGMENT_HEADER_LENGTH = $ - ProgramHeader db (NUMBER_OF_SEGMENTS-1)*SEGMENT_HEADER_LENGTH dup 0 HEADERS_OFFSET = 0 HEADERS_BASE = BASE_ADDRESS OVERLAY_HEADERS = LOAD_HEADERS SEGMENT_INDEX = 0 DEFINED_SEGMENT = 0 SEGMENT_TYPE = PT_LOAD FILE_OFFSET = $% SEGMENT_BASE = BASE_ADDRESS + FILE_OFFSET and 0FFFh org SEGMENT_BASE start: end namespace RVA? equ -ELF.BASE_ADDRESS + macro entry? address* namespace ELF store address-DYNAMIC at ELF:e_entry end namespace end macro macro segment? namespace ELF DEFINED_SEGMENT_SIZE = $ - SEGMENT_BASE if (DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0) & SEGMENT_TYPE = PT_LOAD & OVERLAY_HEADERS FILE_OFFSET = HEADERS_OFFSET SEGMENT_BASE = HEADERS_BASE OVERLAY_HEADERS = 0 end if store SEGMENT_BASE-DYNAMIC at ELF:p_vaddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_BASE-DYNAMIC at ELF:p_paddr+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store FILE_OFFSET at ELF:p_offset+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if SEGMENT_TYPE = PT_LOAD RAW_DATA_SIZE = $%% - FILE_OFFSET SEGMENT_SIZE = $ - SEGMENT_BASE store RAW_DATA_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0 FILE_OFFSET = $%% align 1000h SEGMENT_BASE = $ + FILE_OFFSET and 0FFFh end if section SEGMENT_BASE else if OVERLAY_HEADERS = 0 & ( LOAD_HEADERS | SEGMENT_TYPE = PT_GNU_RELRO ) & ~ SEGMENT_TYPE = PT_GNU_STACK & ~ SEGMENT_TYPE = PT_NOTE OVERLAY_HEADERS = 1 HEADERS_OFFSET = FILE_OFFSET HEADERS_BASE = SEGMENT_BASE end if FILE_OFFSET = $% SEGMENT_SIZE = $ - SEGMENT_BASE store SEGMENT_SIZE at ELF:p_filesz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_SIZE at ELF:p_memsz+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if OVERLAY_HEADERS = 0 SEGMENT_BASE = DYNAMIC + (SEGMENT_BASE-DYNAMIC) and not 0FFFh + FILE_OFFSET and 0FFFh else SEGMENT_BASE = $ end if if $% > $%% store 0:byte at $-1 end if org SEGMENT_BASE end if if DEFINED_SEGMENT | DEFINED_SEGMENT_SIZE > 0 SEGMENT_INDEX = SEGMENT_INDEX + 1 end if end namespace end macro macro segment? attributes* namespace ELF segment SEGMENT_TYPE = PT_LOAD SEGMENT_FLAGS = 0 local seq,list define seq attributes while 1 match car cdr, seq define list car define seq cdr else match any, seq define list any end match break end match end while irpv attribute, list match =readable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_R else match =writeable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_W else match =executable?, attribute SEGMENT_FLAGS = SEGMENT_FLAGS or PF_X else match =interpreter?, attribute SEGMENT_TYPE = PT_INTERP else match =dynamic?, attribute SEGMENT_TYPE = PT_DYNAMIC else match =note?, attribute SEGMENT_TYPE = PT_NOTE else match =gnustack?, attribute SEGMENT_TYPE = PT_GNU_STACK else match =gnuehframe?, attribute SEGMENT_TYPE = PT_GNU_EH_FRAME else match =gnurelro?, attribute SEGMENT_TYPE = PT_GNU_RELRO else err 'unknown attribute "',`attribute,'"' end match end irpv DEFINED_SEGMENT = 1 store SEGMENT_TYPE at ELF:p_type+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH store SEGMENT_FLAGS at ELF:p_flags+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH if SEGMENT_TYPE = PT_LOAD store 1000h at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH else store 1 at ELF:p_align+SEGMENT_INDEX*SEGMENT_HEADER_LENGTH end if end namespace end macro postpone purge segment? segment namespace ELF NUMBER_OF_SEGMENTS := SEGMENT_INDEX end namespace end postpone