diff --git a/examples/ini.rs b/examples/ini.rs new file mode 100644 index 0000000..f7df8a2 --- /dev/null +++ b/examples/ini.rs @@ -0,0 +1,49 @@ +#![no_std] +#![no_main] + +use cstr_core::{cstr, CStr}; +use kos::{dll::Libini, system::debug_write, threads::exit}; + +extern crate alloc; +use alloc::format; + +static mut LIB: Option = None; + +#[no_mangle] +pub fn kol_main() { + unsafe { + // FIXME: Find any possible solution to drop that fucking unsafe + LIB = Libini::import(None).ok(); + let filename = cstr!("/sys/File Managers/Kfar.ini"); + LIB.unwrap() + .enum_sections(filename.as_ptr() as *const u8, sec_handler); + } + + exit(); +} + +extern "stdcall" fn sec_handler(filename: *const u8, section: *const u8) { + unsafe { + debug_write(&format!( + "{}\n", + CStr::from_ptr(section as *const i8).to_str().unwrap() + )); + + LIB.unwrap().enum_keys(filename, section, key_handler); + }; +} + +extern "stdcall" fn key_handler( + _filename: *const u8, + _section: *const u8, + key: *const u8, + value: *const u8, +) { + unsafe { + debug_write(&format!( + "- {}\t = {}\n", + CStr::from_ptr(key as *const i8).to_str().unwrap(), + CStr::from_ptr(value as *const i8).to_str().unwrap() + )) + } +} diff --git a/src/allocation.rs b/src/allocation.rs index 68a72e2..6a8111b 100644 --- a/src/allocation.rs +++ b/src/allocation.rs @@ -170,13 +170,15 @@ unsafe impl alloc::alloc::GlobalAlloc for GlobalAlloc { return null_mut(); } - init(); - malloc(layout.size()) + // init(); + // malloc(layout.size()) + sys::alloc(layout.size()) as *mut u8 } unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { // free keeps track of layout presumably???? - free(ptr) + // free(ptr) + sys::free(ptr); } } diff --git a/src/dll.rs b/src/dll.rs index b449d97..fd7eda2 100644 --- a/src/dll.rs +++ b/src/dll.rs @@ -1,9 +1,15 @@ use crate::sys; -use cstr_core::CStr; +use core::mem::transmute; +use cstr_core::{cstr, CStr}; mod console; pub use console::Console; +mod libini; +pub use libini::Libini; + +use crate::system::debug_write; + pub struct DLL { table: *const ImportTableEl, } @@ -22,6 +28,20 @@ impl DLL { } } + pub fn init_dll(name: &CStr) -> Result { + unsafe { + let lib = DLL::load_dll(name); + match lib { + Err(e) => Err(e), + Ok(dll) => { + let init: fn() = transmute(dll.get_func(cstr!("lib_init")).ok().unwrap()); + sys::dllInit(init); + Ok(dll) + } + } + } + } + pub fn get_func(&self, name: &CStr) -> Result<*const (), &str> { unsafe { let mut i = 0; @@ -31,6 +51,11 @@ impl DLL { return Err("Function not found"); } let cur_name = CStr::from_ptr((*el).func_name as *const i8); + debug_write(&format!( + "{}: {:x}\n", + cur_name.to_str().unwrap(), + (*el).func_addr as usize + )); if cur_name == name { return Ok((*el).func_addr as *const ()); } diff --git a/src/dll/libini.rs b/src/dll/libini.rs new file mode 100644 index 0000000..fbb7619 --- /dev/null +++ b/src/dll/libini.rs @@ -0,0 +1,48 @@ +use crate::{dll::DLL, system::debug_write}; +use core::mem::transmute; +use cstr_core::{cstr, CStr}; + +#[derive(Clone, Copy)] +pub struct Libini { + ini_enum_sections: extern "stdcall" fn(*const u8, extern "stdcall" fn(*const u8, *const u8)), + ini_enum_keys: extern "stdcall" fn( + *const u8, + *const u8, + extern "stdcall" fn(*const u8, *const u8, *const u8, *const u8), + ), +} + +impl Libini { + pub fn import(path: Option<&CStr>) -> Result { + let lib = DLL::init_dll(path.unwrap_or(cstr!("/sys/lib/libini.obj"))); + match lib { + Err(e) => return Err(e), + Ok(dll) => unsafe { + Ok(Libini { + ini_enum_sections: transmute( + dll.get_func(cstr!("ini_enum_sections")).ok().unwrap(), + ), + ini_enum_keys: transmute(dll.get_func(cstr!("ini_enum_keys")).ok().unwrap()), + }) + }, + } + } + + pub fn enum_sections( + &self, + filename: *const u8, + callback: extern "stdcall" fn(*const u8, *const u8), + ) { + debug_write("--enum_sections\n"); + (self.ini_enum_sections)(filename, callback); + } + + pub fn enum_keys( + self, + filename: *const u8, + section_name: *const u8, + callback: extern "stdcall" fn(*const u8, *const u8, *const u8, *const u8), + ) { + (self.ini_enum_keys)(filename, section_name, callback); + } +} diff --git a/src/include/dll.inc b/src/include/dll.inc new file mode 100755 index 0000000..b04c4b1 --- /dev/null +++ b/src/include/dll.inc @@ -0,0 +1,166 @@ +;----------------------------------------------------------------------------- +; load one or more DLL file in COFF format and try to import functions by our list +; if first function in import list begins with 'lib_', call it as DLL initialization +; return eax = 1 as fail, if anyone of .obj file not found in /sys/lib +; return 0 if all fine, but 0 not garantees in succesfull import - see dll.Link comment +; dirties all registers! eax, ebx, ecx, edx, esi, edi +proc dll.Load, import_table:dword + mov esi, [import_table] + .next_lib: + mov edx, [esi] + or edx, edx + jz .exit + push esi + mov esi, [esi + 4] + + mov edi, esi + cmp byte[esi], '/' + jz .load_lib + + mov edi, s_libdir.fname + @@: + lodsb + stosb + or al, al + jnz @b + + mov edi, s_libdir + .load_lib: + mcall 68, 19, edi ;s_libdir + or eax, eax + jz .fail + stdcall dll.Link, eax, edx + push eax + mov eax, [eax] + cmp dword[eax], 'lib_' + pop eax + jnz @f + stdcall dll.Init, [eax + 4] + @@: + pop esi + add esi, 8 + jmp .next_lib + .exit: + xor eax, eax + ret + .fail: + add esp, 4 + xor eax, eax + inc eax + ret +endp +;----------------------------------------------------------------------------- +; scans dll export table for a functions we want to import +; break scan on first unresolved import +; no return value +proc dll.Link, exp:dword, imp:dword + push eax + mov esi, [imp] + test esi, esi + jz .done + .next: + lodsd + test eax, eax + jz .done + stdcall dll.GetProcAddress, [exp], eax + or eax, eax + jz @f + mov [esi - 4], eax + jmp .next + @@: + mov dword[esp], 0 + .done: + pop eax + ret +endp +;----------------------------------------------------------------------------- +; calls lib_init with predefined parameters +; no return value +proc dll.Init, dllentry:dword + pushad + mov eax, mem.Alloc + mov ebx, mem.Free + mov ecx, mem.ReAlloc + mov edx, dll.Load + stdcall [dllentry] + popad + ret +endp +;----------------------------------------------------------------------------- +; scans export table for a sz_name function +; returns in eax function address or 0 if not found +proc dll.GetProcAddress, exp:dword, sz_name:dword + mov edx, [exp] + xor eax, eax + .next: + or edx, edx + jz .end + cmp dword[edx], 0 + jz .end + stdcall strcmp, [edx], [sz_name] + test eax, eax + jz .ok + add edx, 8 + jmp .next + .ok: + mov eax, [edx + 4] + .end: + cmp eax, -1 + jnz @f + xor eax, eax + @@: + ret +endp +;----------------------------------------------------------------------------- +; compares strings +; returns eax = 0 if equal, -1 otherwise +proc strcmp, str1:dword, str2:dword + push esi edi + mov esi, [str1] + mov edi, [str2] + xor eax, eax + @@: + lodsb + scasb + jne .fail + or al, al + jnz @b + jmp .ok + .fail: + or eax, -1 + .ok: + pop edi esi + ret +endp +;----------------------------------------------------------------------------- +if defined dll.Load +s_libdir: + db '/sys/lib/' + .fname rb 32 +end if +;----------------------------------------------------------------------------- +proc mem.Alloc, size + push ebx ecx + mov ecx, [size] + mcall 68, 12 + pop ecx ebx + ret +endp +;----------------------------------------------------------------------------- +proc mem.ReAlloc, mptr, size + push ebx ecx edx + mov ecx, [size] + mov edx, [mptr] + mcall 68, 20 + pop edx ecx ebx + ret +endp +;----------------------------------------------------------------------------- +proc mem.Free, mptr + push ebx ecx + mov ecx,[mptr] + mcall 68, 13 + pop ecx ebx + ret +endp +;----------------------------------------------------------------------------- diff --git a/src/func_constants.inc b/src/include/func_constants.inc similarity index 100% rename from src/func_constants.inc rename to src/include/func_constants.inc diff --git a/src/include/macros.inc b/src/include/macros.inc new file mode 100755 index 0000000..39fb53a --- /dev/null +++ b/src/include/macros.inc @@ -0,0 +1,604 @@ +@^ fix macro comment { +^@ fix } + +; -------------------------- +macro library [lname,fname] +{ + forward + dd __#lname#_library_table__,__#lname#_library_name__ + common + dd 0 + forward + align 4 + __#lname#_library_name__ db fname,0 +} + +macro import lname,[name,sname] +{ + common + align 4 + __#lname#_library_table__: + forward + if used name + name dd __#name#_import_name__ + end if + common + dd 0 + forward + if used name + align 4 + __#name#_import_name__ db sname,0 + end if +} + +macro export [name,sname] +{ + forward + dd __#name#_export_name__,name + common + dd 0 + forward + align 4 + __#name#_export_name__ db sname,0 +} +; ------------------------- + +macro m2m dest,src { + push src + pop dest +} + + +macro iglobal { + IGlobals equ IGlobals, + macro __IGlobalBlock { } + +macro uglobal { + UGlobals equ UGlobals, + macro __UGlobalBlock { } + +endg fix } ; Use endg for ending iglobal and uglobal blocks. + + +macro IncludeIGlobals{ + macro IGlobals dummy,[n] \{ __IGlobalBlock + purge __IGlobalBlock \} + match I, IGlobals \{ I \} } + +macro IncludeUGlobals{ + macro UGlobals dummy,[n] \{ + \common + \local begin, size + begin = $ + virtual at $ + \forward + __UGlobalBlock + purge __UGlobalBlock + \common + size = $ - begin + end virtual + rb size + \} + match U, UGlobals \{ U \} } + +uglobal +endg + +iglobal +endg + + +; new application structure +macro meos_app_start + { + use32 + org 0x0 + + db 'MENUET01' + dd 0x01 + dd __start + dd __end + dd __memory + dd __stack + + if used __params & ~defined __params + dd __params + else + dd 0x0 + end if + + dd 0x0 + } +MEOS_APP_START fix meos_app_start +KOS_APP_START fix meos_app_start + +macro code + { + __start: + } +CODE fix code + +macro data + { + __data: + IncludeIGlobals + } +DATA fix data + +macro udata + { + if used __params & ~defined __params + __params: + db 0 + __end: + rb 255 + else + __end: + end if + __udata: + IncludeUGlobals + } +UDATA fix udata + +macro meos_app_end + { + align 32 + rb 2048 + __stack: + __memory: + } +MEOS_APP_END fix meos_app_end +KOS_APP_END fix meos_app_end + + +; macro for defining multiline text data +struc mstr [sstring] + { + forward + local ssize + virtual at 0 + db sstring + ssize = $ + end virtual + dd ssize + db sstring + common + dd -1 + } + +; macro for defining multiline text data +struc mls [sstring] + { + forward + local ssize + virtual at 0 + db sstring ; mod + ssize = $ + end virtual + db ssize + db sstring + common + db -1 ; mod + } + + + +; strings +macro sz name,[data] { ; [mike.dld] + common + if used name + name db data + .size = $-name + end if +} + +macro szZ name,[data] { ; same as sz, but for zero terminated string [dunkaist] + common + if used name + name db data,0 + .size = $-name-1 + end if +} +sz0 fix szZ + +macro lsz name,[lng,data] { ; [mike.dld] + common + if used name + label name + forward + if lang eq lng + db data + end if + common + .size = $-name + end if +} + +macro szc name,elsz,[data] { ; [mike.dld] + common + local s,m + m = 0 + if used name + label name + forward + virtual at 0 + db data + s = $ + end virtual + d#elsz s + if m < s + m = s + end if + db data + common + .size = $-name + .maxl = m + end if +} + +macro lszc name,elsz,[lng,data] { ; [mike.dld] + common + local s,m,c + m = 0 + c = 0 + if used name + label name + forward + if lang eq lng + virtual at 0 + db data + s = $ + end virtual + d#elsz s + if m < s + m = s + end if + db data + c = c+1 + end if + common + .size = $-name + .maxl = m + .count = c + end if +} + + +; easy system call macro +macro mpack dest, hsrc, lsrc +{ + if (hsrc eqtype 0) & (lsrc eqtype 0) + mov dest, (hsrc) shl 16 + lsrc + else + if (hsrc eqtype 0) & (~lsrc eqtype 0) + mov dest, (hsrc) shl 16 + add dest, lsrc + else + mov dest, hsrc + shl dest, 16 + add dest, lsrc + end if + end if +} + +macro __mov reg,a,b { ; mike.dld + if (~a eq)&(~b eq) + mpack reg,a,b + else if (~a eq)&(b eq) + mov reg,a + end if +} + + +;include 'config.inc' +__CPU_type equ p5 +SYSENTER_VAR equ 0 + +macro mcall a,b,c,d,e,f,g { ; [mike.dld], [Ghost] + local ..ret_point + __mov eax,a + __mov ebx,b + __mov ecx,c + __mov edx,d + __mov esi,e + __mov edi,f + __mov ebp,g + + if __CPU_type eq p5 + int 0x40 + else + if __CPU_type eq p6 + push ebp + mov ebp, esp + push ..ret_point ; it may be 2 or 5 byte + sysenter + ..ret_point: + pop edx + pop ecx + + else + if __CPU_type eq k6 + push ecx + syscall + pop ecx + else + display 'ERROR : unknown CPU type (set to p5)', 10, 13 + __CPU_type equ p5 + int 0x40 + end if + end if + end if +} + + +; ------------------------- +macro __header a,[b] { + common + use32 + org 0 + db 'MENUET',a + forward + if b eq + dd 0 + else + dd b + end if +} + +macro __section name { + align 16 + label name +} + +macro __func name { + if ~used name + display 'FUNC NOT USED: ',`name,13,10 + else + align 4 + name: + ;diff16 `name,0,name +} + +macro endf { end if } + +macro diff16 title,l1,l2 + { + local s,d + s = l2-l1 + display title,': 0x' + repeat 8 + d = '0' + s shr ((8-%) shl 2) and $0F + if d > '9' + d = d + 'A'-'9'-1 + end if + display d + end repeat + display 13,10 + } + +macro diff10 title,l1,l2 + { + local s,d,z,m + s = l2-l1 + z = 0 + m = 1000000000 + display title,': ' + repeat 10 + d = '0' + s / m + s = s - (s/m)*m + m = m / 10 + if d <> '0' + z = 1 + end if + if z <> 0 + display d + end if + end repeat + display 13,10 + } + + +macro movi arg1,arg2 +{ +if (arg1 in ) & ((arg2 eqtype 0) | (arg2 eqtype '0')) + if (arg2) = 0 + xor arg1,arg1 + else if (arg2) = 1 + xor arg1,arg1 + inc arg1 + else if (arg2) = -1 + or arg1,-1 + else if (arg2) >= -128 & (arg2) <= 127 + push arg2 + pop arg1 + else + mov arg1,arg2 + end if +else + mov arg1,arg2 +end if +} + + +macro RGB [a] { + common + match (r=,g=,b),a \{ + \dd ((r) shl 16) or ((g) shl 8) or (b) + \} +} + + +struc POINT _t,_dx,_dy { + .x _t _dx + .y _t _dy +} + +; structure definition helper +include 'struct.inc' + +struct RECT + left dd ? + top dd ? + right dd ? + bottom dd ? +ends + +struct BOX + left dd ? + top dd ? + width dd ? + height dd ? +ends + +; structures used in KolibriOS +struct process_information + cpu_usage dd ? ; +0 + window_stack_position dw ? ; +4 + window_stack_value dw ? ; +6 + dw ? ; +8 + process_name rb 12 ; +10 + memory_start dd ? ; +22 + used_memory dd ? ; +26 + PID dd ? ; +30 + box BOX ; +34 + slot_state dw ? ; +50 + dw ? ; +52 + client_box BOX ; +54 + wnd_state db ? ; +70 + event_mask dd ? ; +71 + keyboard_mode db ? ; +75 + rb (1024-76) +ends + +struct system_colors + frame dd ? ;nonset1 + grab dd ? ;nonset2 + work_dark dd ? + work_light dd ? + grab_text dd ? ;window_title + work dd ? + work_button dd ? + work_button_text dd ? + work_text dd ? + work_graph dd ? +ends + +struct FILEDATE + Second db ? + Minute db ? + Hour db ? + db ? + Day db ? + Month db ? + Year dw ? +ends + +struct FILEINFO + Attributes dd ? + IsUnicode db ? + db 3 dup(?) + DateCreate FILEDATE + DateAccess FILEDATE + DateModify FILEDATE + Size dq ? +ends + +cmove fix cmovz + +macro cmovz reg1, reg2 { + + local ..jumpaddr + +if __CPU_type eq p5 ; CMOVcc isnt supported on the P5 + jnz ..jumpaddr + mov reg1, reg2 + ..jumpaddr: +else + cmovz reg1, reg2 +end if + +} + +cmovne fix cmovnz + +macro cmovnz reg1, reg2 { + + local ..jumpaddr + +if __CPU_type eq p5 ; CMOVcc isnt supported on the P5 + jz ..jumpaddr + mov reg1, reg2 + ..jumpaddr: +else + cmovnz reg1, reg2 +end if + +} + +macro cmovg reg1, reg2 { + + local ..jumpaddr + +if __CPU_type eq p5 ; CMOVcc isnt supported on the P5 + jle ..jumpaddr + mov reg1, reg2 + ..jumpaddr: +else + cmovg reg1, reg2 +end if +} + +macro cmovl reg1, reg2 { + + local ..jumpaddr + +if __CPU_type eq p5 ; CMOVcc isnt supported on the P5 + jge ..jumpaddr + mov reg1, reg2 + ..jumpaddr: +else + cmovl reg1, reg2 +end if +} + +; replaces /programs/cmp.inc +irp cond, e, ne, g, ng, l, nl, ge, le { + macro cmp#cond a, b, c\{ + cmp a, b + j#cond c + \} +} + +; constants + +; button flags +BT_DEL = 0x80000000 +BT_HIDE = 0x40000000 +BT_NOFRAME = 0x20000000 + +; events +EV_IDLE = 0 +EV_TIMER = 0 +EV_REDRAW = 1 +EV_KEY = 2 +EV_BUTTON = 3 +EV_EXIT = 4 +EV_BACKGROUND = 5 +EV_MOUSE = 6 +EV_IPC = 7 +EV_STACK = 8 + +; event mask bits for function 40 +EVM_REDRAW = 1b +EVM_KEY = 10b +EVM_BUTTON = 100b +EVM_EXIT = 1000b +EVM_BACKGROUND = 10000b +EVM_MOUSE = 100000b +EVM_IPC = 1000000b +EVM_STACK = 10000000b +EVM_DEBUG = 100000000b +EVM_STACK2 = 1000000000b + +EVM_MOUSE_FILTER = 0x80000000 +EVM_CURSOR_FILTER = 0x40000000 diff --git a/src/include/proc32.inc b/src/include/proc32.inc new file mode 100755 index 0000000..762826c --- /dev/null +++ b/src/include/proc32.inc @@ -0,0 +1,301 @@ + +; 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, \{ 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, \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} + macro finish@proc + \{ localbytes = current + match close:reglist, close@proc: \\{ 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 qqword eq type + dd ?,?,?,?,?,?,?,? + else 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*2 + restore done@local \\} + match =QQWORD, vartype \\{ label varname qqword + rq count*4 + restore done@local \\} + match =XWORD, vartype \\{ label varname xword + rq count*2 + restore done@local \\} + match =YWORD, vartype \\{ label varname yword + rq count*4 + 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 =QQWORD, vartype \\{ label varname qqword + dq ?,?,?,? + restore done@local \\} + match =XWORD, vartype \\{ label varname xword + dq ?,? + restore done@local \\} + match =YWORD, vartype \\{ label varname yword + dq ?,?,?,? + restore done@local \\} + match , done@local \\{ varname vartype + restore done@local \\} \} + match ,done@local + \{ var + restore done@local \} + common + endl } diff --git a/src/include/struct.inc b/src/include/struct.inc new file mode 100755 index 0000000..789dd17 --- /dev/null +++ b/src/include/struct.inc @@ -0,0 +1,240 @@ + +; Macroinstructions for defining data structures + +macro struct name + { virtual at 0 + fields@struct equ name + match child parent, name \{ fields@struct equ child,fields@\#parent \} + sub@struct equ + struc db [val] \{ \common define field@struct .,db, + fields@struct equ fields@struct,field@struct \} + struc dw [val] \{ \common define field@struct .,dw, + fields@struct equ fields@struct,field@struct \} + struc du [val] \{ \common define field@struct .,du, + fields@struct equ fields@struct,field@struct \} + struc dd [val] \{ \common define field@struct .,dd, + fields@struct equ fields@struct,field@struct \} + struc dp [val] \{ \common define field@struct .,dp, + fields@struct equ fields@struct,field@struct \} + struc dq [val] \{ \common define field@struct .,dq, + fields@struct equ fields@struct,field@struct \} + struc dt [val] \{ \common define field@struct .,dt, + fields@struct equ fields@struct,field@struct \} + struc rb count \{ define field@struct .,db,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rw count \{ define field@struct .,dw,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rd count \{ define field@struct .,dd,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rp count \{ define field@struct .,dp,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rq count \{ define field@struct .,dq,count dup (?) + fields@struct equ fields@struct,field@struct \} + struc rt count \{ define field@struct .,dt,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro db [val] \{ \common \local anonymous + define field@struct anonymous,db, + fields@struct equ fields@struct,field@struct \} + macro dw [val] \{ \common \local anonymous + define field@struct anonymous,dw, + fields@struct equ fields@struct,field@struct \} + macro du [val] \{ \common \local anonymous + define field@struct anonymous,du, + fields@struct equ fields@struct,field@struct \} + macro dd [val] \{ \common \local anonymous + define field@struct anonymous,dd, + fields@struct equ fields@struct,field@struct \} + macro dp [val] \{ \common \local anonymous + define field@struct anonymous,dp, + fields@struct equ fields@struct,field@struct \} + macro dq [val] \{ \common \local anonymous + define field@struct anonymous,dq, + fields@struct equ fields@struct,field@struct \} + macro dt [val] \{ \common \local anonymous + define field@struct anonymous,dt, + fields@struct equ fields@struct,field@struct \} + macro rb count \{ \local anonymous + define field@struct anonymous,db,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rw count \{ \local anonymous + define field@struct anonymous,dw,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rd count \{ \local anonymous + define field@struct anonymous,dd,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rp count \{ \local anonymous + define field@struct anonymous,dp,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rq count \{ \local anonymous + define field@struct anonymous,dq,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro rt count \{ \local anonymous + define field@struct anonymous,dt,count dup (?) + fields@struct equ fields@struct,field@struct \} + macro union \{ fields@struct equ fields@struct,,union,< + sub@struct equ union \} + macro struct \{ fields@struct equ fields@struct,,substruct,< + sub@struct equ substruct \} } + +macro ends + { match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt + restruc rb,rw,rd,rp,rq,rt + purge db,dw,du,dd,dp,dq,dt + purge rb,rw,rd,rp,rq,rt + purge union,struct + match name tail,fields@struct, \\{ if $ + display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah + err + end if \\} + match name=,fields,fields@struct \\{ fields@struct equ + make@struct name,fields + define fields@\\#name fields \\} + end virtual \} + match any, sub@struct \{ fields@struct equ fields@struct> \} + restore sub@struct } + +macro make@struct name,[field,type,def] + { common + local define + define equ name + forward + local sub + match , field \{ make@substruct type,name,sub def + define equ define,.,sub, \} + match any, field \{ define equ define,.#field,type, \} + common + match fields, define \{ define@struct fields \} } + +macro define@struct name,[field,type,def] + { common + virtual + db `name + load initial@struct byte from 0 + if initial@struct = '.' + display 'Error: name of structure should not begin with a dot.',0Dh,0Ah + err + end if + end virtual + local list + list equ + forward + if ~ field eq . + name#field type def + sizeof.#name#field = $ - name#field + else + label name#.#type + rb sizeof.#type + end if + local value + match any, list \{ list equ list, \} + list equ list + common + sizeof.#name = $ + restruc name + match values, list \{ + struc name value \\{ \\local \\..base + match any, fields@struct \\\{ fields@struct equ fields@struct,.,name, \\\} + match , fields@struct \\\{ label \\..base + forward + match , value \\\\{ field type def \\\\} + match any, value \\\\{ field type value + if ~ field eq . + rb sizeof.#name#field - ($-field) + end if \\\\} + common label . at \\..base \\\} + \\} + macro name value \\{ + match any, fields@struct \\\{ \\\local anonymous + fields@struct equ fields@struct,anonymous,name, \\\} + match , fields@struct \\\{ + forward + match , value \\\\{ type def \\\\} + match any, value \\\\{ \\\\local ..field + ..field = $ + type value + if ~ field eq . + rb sizeof.#name#field - ($-..field) + end if \\\\} + common \\\} \\} \} } + +macro enable@substruct + { macro make@substruct substruct,parent,name,[field,type,def] + \{ \common + \local define + define equ parent,name + \forward + \local sub + match , field \\{ match any, type \\\{ enable@substruct + make@substruct type,parent,sub def + purge make@substruct + define equ define,.,sub, \\\} \\} + match any, field \\{ define equ define,.\#field,type, \\} + \common + match fields, define \\{ define@\#substruct fields \\} \} } + +enable@substruct + +macro define@union parent,name,[field,type,def] + { common + virtual at parent#.#name + forward + if ~ field eq . + virtual at parent#.#name + parent#field type def + sizeof.#parent#field = $ - parent#field + end virtual + if sizeof.#parent#field > $ - parent#.#name + rb sizeof.#parent#field - ($ - parent#.#name) + end if + else + virtual at parent#.#name + label parent#.#type + type def + end virtual + label name#.#type at parent#.#name + if sizeof.#type > $ - parent#.#name + rb sizeof.#type - ($ - parent#.#name) + end if + end if + common + sizeof.#name = $ - parent#.#name + end virtual + struc name [value] \{ \common + label .\#name + last@union equ + forward + match any, last@union \\{ virtual at .\#name + field type def + end virtual \\} + match , last@union \\{ match , value \\\{ field type def \\\} + match any, value \\\{ field type value \\\} \\} + last@union equ field + common rb sizeof.#name - ($ - .\#name) \} + macro name [value] \{ \common \local ..anonymous + ..anonymous name value \} } + +macro define@substruct parent,name,[field,type,def] + { common + virtual at parent#.#name + forward + if ~ field eq . + parent#field type def + sizeof.#parent#field = $ - parent#field + else + label parent#.#type + rb sizeof.#type + end if + common + sizeof.#name = $ - parent#.#name + end virtual + struc name value \{ + label .\#name + forward + match , value \\{ field type def \\} + match any, value \\{ field type value + if ~ field eq . + rb sizeof.#parent#field - ($-field) + end if \\} + common \} + macro name value \{ \local ..anonymous + ..anonymous name \} } diff --git a/src/sys.rs b/src/sys.rs index c0bd7e1..ef7cf8b 100644 --- a/src/sys.rs +++ b/src/sys.rs @@ -64,3 +64,10 @@ extern "C" { #[link_name = "_load_dll"] pub fn load_dll(name: *const u8) -> *const u32; } + +// dll.inc +#[link(name = "syscalls")] +extern "stdcall" { + #[link_name = "dll.Init"] + pub fn dllInit(init_function: fn()); +} diff --git a/src/syscalls.S b/src/syscalls.S index b314bf1..c82dbac 100644 --- a/src/syscalls.S +++ b/src/syscalls.S @@ -1,6 +1,9 @@ format ELF -include "src/func_constants.inc" +include "src/include/macros.inc" +include "src/include/proc32.inc" +include "src/include/dll.inc" +include "src/include/func_constants.inc" section '.text' public _exit @@ -20,6 +23,8 @@ section '.text' public _load_dll public _set_event_mask + public dll.Init + _exit: mov eax, SF_TERMINATE_PROCESS int 0x40