Commit f77805ff authored by Tomasz Buchert's avatar Tomasz Buchert

Imported Upstream version 1.71.22

parents
macro Elf32_Sym name,value,size,bind,type,other,shndx
{
dd name+0
dd value+0
dd size+0
db (bind+0) shl 4 + (type+0)
db other+0
dw shndx+0
}
virtual at 0
Elf32_Sym
sizeof.Elf32_Sym = $
end virtual
macro Elf32_Rel offset,symbol,type
{
dd offset+0
dd (symbol+0) shl 8 + (type+0)
}
virtual at 0
Elf32_Rel
sizeof.Elf32_Rel = $
end virtual
macro Elf32_Rela offset,symbol,type,addend
{
dd offset+0
dd (symbol+0) shl 8 + (type+0)
dd addend+0
}
virtual at 0
Elf32_Rela
sizeof.Elf32_Rela = $
end virtual
macro Elf64_Sym name,value,size,bind,type,other,shndx
{
dd name+0
db (bind+0) shl 4 + (type+0)
db other+0
dw shndx+0
dq value+0
dq size+0
}
virtual at 0
Elf64_Sym
sizeof.Elf64_Sym = $
end virtual
macro Elf64_Rel offset,symbol,type
{
dq offset+0
dq (symbol+0) shl 32 + (type+0)
}
virtual at 0
Elf64_Rel
sizeof.Elf64_Rel = $
end virtual
macro Elf64_Rela offset,symbol,type,addend
{
dq offset+0
dq (symbol+0) shl 32 + (type+0)
dq addend+0
}
virtual at 0
Elf64_Rela
sizeof.Elf64_Rela = $
end virtual
DT_NULL = 0
DT_NEEDED = 1
DT_HASH = 4
DT_STRTAB = 5
DT_SYMTAB = 6
DT_RELA = 7
DT_RELASZ = 8
DT_RELAENT = 9
DT_STRSZ = 10
DT_SYMENT = 11
DT_REL = 17
DT_RELSZ = 18
DT_RELENT = 19
STB_LOCAL = 0
STB_GLOBAL = 1
STB_WEAK = 2
STT_NOTYPE = 0
STT_OBJECT = 1
STT_FUNC = 2
STT_SECTION = 3
STT_FILE = 4
R_386_NONE = 0
R_386_32 = 1
R_386_PC32 = 2
R_386_GOT32 = 3
R_386_PLT32 = 4
R_386_COPY = 5
R_386_GLOB_DAT = 6
R_386_JMP_SLOT = 7
R_386_RELATIVE = 8
R_386_GOTOFF = 9
R_386_GOTPC = 10
R_X86_64_NONE = 0
R_X86_64_64 = 1
R_X86_64_PC32 = 2
R_X86_64_GOT32 = 3
R_X86_64_PLT32 = 4
R_X86_64_COPY = 5
R_X86_64_GLOB_DAT = 6
R_X86_64_JUMP_SLOT = 7
R_X86_64_RELATIVE = 8
R_X86_64_GOTPCREL = 9
R_X86_64_32 = 10
R_X86_64_32S = 11
R_X86_64_16 = 12
R_X86_64_PC16 = 13
R_X86_64_8 = 14
R_X86_64_PC8 = 15
R_X86_64_DPTMOD64 = 16
R_X86_64_DTPOFF64 = 17
R_X86_64_TPOFF64 = 18
R_X86_64_TLSGD = 19
R_X86_64_TLSLD = 20
R_X86_64_DTPOFF32 = 21
R_X86_64_GOTTPOFF = 22
R_X86_64_TPOFF32 = 23
R_X86_64_PC64 = 24
R_X86_64_GOTOFF64 = 25
R_X86_64_GOTPC32 = 26
format ELF executable 3
entry start
include 'import32.inc'
include 'proc32.inc'
interpreter '/lib/ld-linux.so.2'
needed 'libc.so.6'
import printf,exit
segment readable executable
start:
cinvoke printf,msg
cinvoke exit
segment readable writeable
msg db 'Hello world!',0xA,0
format ELF64 executable 3
entry start
include 'import64.inc'
interpreter '/lib64/ld-linux-x86-64.so.2'
needed 'libc.so.6'
import printf,exit
segment readable executable
start:
lea rdi,[msg]
xor eax,eax
call [printf]
call [exit]
segment readable writeable
msg db 'Hello world!',0xA,0
include 'elf.inc'
macro interpreter [library]
{
segment interpreter readable
db library,0
}
macro needed [library]
{
local str
match needed,needed@dynamic \{ define needed@dynamic needed,str:library \}
match ,needed@dynamic \{ define needed@dynamic str:library \}
}
define needed@dynamic
macro import [name]
{
common
local strtab,strsz,symtab,rel,relsz,hash
segment dynamic readable
match needed,needed@dynamic
\{ irp item,needed \\{ match str:library,item \\\{ dd DT_NEEDED,str-strtab \\\} \\} \}
dd DT_STRTAB,strtab
dd DT_STRSZ,strsz
dd DT_SYMTAB,symtab
dd DT_SYMENT,sizeof.Elf32_Sym
dd DT_REL,rel
dd DT_RELSZ,relsz
dd DT_RELENT,sizeof.Elf32_Rel
dd DT_HASH,hash
dd DT_NULL,0
segment readable writeable
symtab: Elf32_Sym
forward
local fstr
Elf32_Sym fstr-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0
common
rel:
local counter
counter = 1
forward
Elf32_Rel name,counter,R_386_32
counter = counter+1
common
relsz = $-rel
hash:
dd 1,counter
dd 0
repeat counter
if %=counter
dd 0
else
dd %
end if
end repeat
strtab db 0
forward
fstr db `name,0
common
match needed,needed@dynamic
\{ irp item,needed \\{ match str:library,item \\\{ str db library,0 \\\} \\} \}
strsz = $-strtab
forward
name dd 0
}
include 'elf.inc'
macro interpreter [library]
{
segment interpreter readable
db library,0
}
macro needed [library]
{
local str
match needed,needed@dynamic \{ define needed@dynamic needed,str:library \}
match ,needed@dynamic \{ define needed@dynamic str:library \}
}
define needed@dynamic
macro import [name]
{
common
local strtab,strsz,symtab,rel,relsz,hash
segment dynamic readable
match needed,needed@dynamic
\{ irp item,needed \\{ match str:library,item \\\{ dq DT_NEEDED,str-strtab \\\} \\} \}
dq DT_STRTAB,strtab
dq DT_STRSZ,strsz
dq DT_SYMTAB,symtab
dq DT_SYMENT,sizeof.Elf64_Sym
dq DT_RELA,rela
dq DT_RELASZ,relasz
dq DT_RELAENT,sizeof.Elf64_Rela
dq DT_HASH,hash
dq DT_NULL,0
segment readable writeable
symtab: Elf64_Sym
forward
local fstr
Elf64_Sym fstr-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0
common
rela:
local counter
counter = 1
forward
Elf64_Rela name,counter,R_X86_64_64
counter = counter+1
common
relasz = $-rela
hash:
dd 1,counter
dd 0
repeat counter
if %=counter
dd 0
else
dd %
end if
end repeat
strtab db 0
forward
fstr db `name,0
common
match needed,needed@dynamic
\{ irp item,needed \\{ match str:library,item \\\{ str db library,0 \\\} \\} \}
strsz = $-strtab
forward
name dq 0
}
; Macroinstructions for defining and calling procedures
macro stdcall proc,[arg] ; directly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call proc }
macro invoke proc,[arg] ; indirectly call STDCALL procedure
{ common
if ~ arg eq
reverse
pushd arg
common
end if
call [proc] }
macro ccall proc,[arg] ; directly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call proc
if size@ccall
add esp,size@ccall
end if }
macro cinvoke proc,[arg] ; indirectly call CDECL procedure
{ common
size@ccall = 0
if ~ arg eq
reverse
pushd arg
size@ccall = size@ccall+4
common
end if
call [proc]
if size@ccall
add esp,size@ccall
end if }
macro proc [args] ; define procedure
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ local loc
loc = (localbytes+3) and (not 3)
parmbase@proc equ ebp+8
localbase@proc equ ebp-loc
if parmbytes | localbytes
push ebp
mov ebp,esp
if localbytes
sub esp,loc
end if
end if
irps reg, reglist \{ push reg \} }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
if parmbytes | localbytes
leave
end if
if flag and 10000b
retn
else
retn parmbytes
end if }
close@proc equ
macro define@proc name,statement
{ local params,flag,regs,parmbytes,localbytes,current
if used name
name:
match =stdcall args, statement \{ params equ args
flag = 11b \}
match =stdcall, statement \{ params equ
flag = 11b \}
match =c args, statement \{ params equ args
flag = 10001b \}
match =c, statement \{ params equ
flag = 10001b \}
match =params, params \{ params equ statement
flag = 0 \}
match =uses reglist=,args, params \{ regs equ reglist
params equ args \}
match =regs =uses reglist, regs params \{ regs equ reglist
params equ \}
match =regs, regs \{ regs equ \}
match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
virtual at parmbase@proc
match =,args, params \{ defargs@proc args \}
match =args@proc args, args@proc params \{ defargs@proc args \}
parmbytes = $-(parmbase@proc)
end virtual
name # % = parmbytes/4
all@vars equ
current = 0
macro locals
\{ virtual at localbase@proc+current
macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
struc db [val] \\{ \common deflocal@proc .,db,val \\}
struc du [val] \\{ \common deflocal@proc .,du,val \\}
struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
macro endl
\{ purge label
restruc db,du,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq
current = $-(localbase@proc)
end virtual \}
macro ret operand
\{ match any, operand \\{ retn operand \\}
match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
macro finish@proc
\{ localbytes = current
match close:reglist, close@proc:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
end if \} }
macro defargs@proc [arg]
{ common
if ~ arg eq
forward
local ..arg,current@arg
match argname:type, arg
\{ current@arg equ argname
label ..arg type
argname equ ..arg
if dqword eq type
dd ?,?,?,?
else if tbyte eq type
dd ?,?,?
else if qword eq type | pword eq type
dd ?,?
else
dd ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dd ? \}
common
args@proc equ current@arg
forward
restore current@arg
common
end if }
macro deflocal@proc name,def,[val] { name def val }
macro deflocal@proc name,def,[val]
{ common
match vars, all@vars \{ all@vars equ all@vars, \}
all@vars equ all@vars name
forward
local ..var,..tmp
..var def val
match =?, val \{ ..tmp equ \}
match any =?, val \{ ..tmp equ \}
match any (=?), val \{ ..tmp equ \}
match =label, def \{ ..tmp equ \}
match tmp : value, ..tmp : val
\{ tmp: end virtual
initlocal@proc ..var,def value
virtual at tmp\}
common
match first rest, ..var, \{ name equ first \} }
struc label type { label . type }
macro initlocal@proc name,def
{ virtual at name
def
size@initlocal = $ - name
end virtual
position@initlocal = 0
while size@initlocal > position@initlocal
virtual at name
def
if size@initlocal - position@initlocal < 2
current@initlocal = 1
load byte@initlocal byte from name+position@initlocal
else if size@initlocal - position@initlocal < 4
current@initlocal = 2
load word@initlocal word from name+position@initlocal
else
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
end if
end virtual
if current@initlocal = 1
mov byte [name+position@initlocal],byte@initlocal
else if current@initlocal = 2
mov word [name+position@initlocal],word@initlocal
else
mov dword [name+position@initlocal],dword@initlocal
end if
position@initlocal = position@initlocal + current@initlocal
end while }
macro endp
{ purge ret,locals,endl
finish@proc
purge finish@proc
restore regs@proc
match all,args@proc \{ restore all \}
restore args@proc
match all,all@vars \{ restore all \} }
macro local [var]
{ common
locals
forward done@local equ
match varname[count]:vartype, var
\{ match =BYTE, vartype \\{ varname rb count
restore done@local \\}
match =WORD, vartype \\{ varname rw count
restore done@local \\}
match =DWORD, vartype \\{ varname rd count
restore done@local \\}
match =PWORD, vartype \\{ varname rp count
restore done@local \\}
match =QWORD, vartype \\{ varname rq count
restore done@local \\}
match =TBYTE, vartype \\{ varname rt count
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
rq count+count
restore done@local \\}
match , done@local \\{ virtual
varname vartype
end virtual
rb count*sizeof.\#vartype
restore done@local \\} \}
match :varname:vartype, done@local:var
\{ match =BYTE, vartype \\{ varname db ?
restore done@local \\}
match =WORD, vartype \\{ varname dw ?
restore done@local \\}
match =DWORD, vartype \\{ varname dd ?
restore done@local \\}
match =PWORD, vartype \\{ varname dp ?
restore done@local \\}
match =QWORD, vartype \\{ varname dq ?
restore done@local \\}
match =TBYTE, vartype \\{ varname dt ?
restore done@local \\}
match =DQWORD, vartype \\{ label varname dqword
dq ?,?
restore done@local \\}
match , done@local \\{ varname vartype
restore done@local \\} \}
match ,done@local
\{ var
restore done@local \}
common
endl }
; fasm demonstration of writing simple ELF executable
format ELF executable 3
entry start
segment readable executable
start:
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,msg_size
int 0x80
mov eax,1
xor ebx,ebx
int 0x80
segment readable writeable
msg db 'Hello world!',0xA
msg_size = $-msg
; fasm demonstration of writing 64-bit ELF executable
; (thanks to Frantiek Gbri)
; syscall numbers: /usr/src/linux/include/asm-x86_64/unistd.h
; parameters order:
; r9 ; 6th param
; r8 ; 5th param
; r10 ; 4th param
; rdx ; 3rd param
; rsi ; 2nd param
; rdi ; 1st param
; eax ; syscall_number
; syscall
format ELF64 executable 3
segment readable executable
entry $
mov edx,msg_size ; CPU zero extends 32-bit operation to 64-bit
; we can use less bytes than in case mov rdx,...
lea rsi,[msg]
mov edi,1 ; STDOUT
mov eax,1 ; sys_write
syscall
xor edi,edi ; exit code 0
mov eax,60 ; sys_exit
syscall
segment readable writeable
msg db 'Hello 64-bit world!',0xA
msg_size = $-msg
\ No newline at end of file
; fasm demonstration of assembling object files
; compile the program using commands like:
; fasm msgdemo.asm msgdemo.o
; fasm writemsg.asm writemsg.o
; ld msgdemo.o writemsg.o -o msgdemo
format ELF
section '.text' executable
public _start
_start:
extrn writemsg
mov esi,msg
call writemsg
mov eax,1
xor ebx,ebx
int 0x80
section '.data' writeable
msg db "Elves are coming!",0xA,0