From 72f9d833ed6dabf99adf65be1a0bf17269856ac9 Mon Sep 17 00:00:00 2001 From: Pavel <68122101+red-prig@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:06:48 +0300 Subject: [PATCH] + --- sys/kern/kern_bnet.pas | 72 +++++++++++ sys/kern/kern_dynlib.pas | 2 - sys/kern/subr_dynlib.pas | 12 +- sys/kern/trap.pas | 272 ++++++++++++++++++++++++++++++++++++++- sys/syscalls.pas | 8 ++ sys/sysent.pas | 3 +- sys/test/project1.lpi | 6 +- sys/test/project1.lpr | 3 +- 8 files changed, 365 insertions(+), 13 deletions(-) create mode 100644 sys/kern/kern_bnet.pas diff --git a/sys/kern/kern_bnet.pas b/sys/kern/kern_bnet.pas new file mode 100644 index 00000000..3b6e0093 --- /dev/null +++ b/sys/kern/kern_bnet.pas @@ -0,0 +1,72 @@ +unit kern_bnet; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +function sys_netcontrol(fd,op:Integer;buf:Pointer;nbuf:DWORD):Integer; + +implementation + +uses + errno, + systm, + md_arc4random; + +function bnet_get_secure_seed():Integer; +begin + Result:=0; + arc4rand(@Result,SizeOf(Integer),0); +end; + +function sys_netcontrol(fd,op:Integer;buf:Pointer;nbuf:DWORD):Integer; +var + _kbuf:array[0..159] of Byte; + kaddr:Pointer; +begin + if (buf=nil) then + begin + kaddr:=nil; + end else + begin + if (160 < nbuf) then + begin + Exit(EINVAL); + end else + begin + kaddr:=@_kbuf; + end; + + if ((op and QWORD($30000000))<>0) then + begin + Result:=copyin(buf,kaddr,nbuf); + if (Result<>0) then Exit; + end; + end; + + case op of + $14: //bnet_get_secure_seed + begin + PInteger(kaddr)^:=bnet_get_secure_seed(); + end + + else + begin + Writeln(StdErr,'Unhandled netcontrol:',op); + Assert(False); + Result:=EINVAL; + end; + end; + + if (buf<>nil) and (Result=0) and ((op and QWORD($30000000))<>QWORD($20000000)) then + begin + Result:=copyout(kaddr,buf,nbuf); + end; +end; + + + + +end. + diff --git a/sys/kern/kern_dynlib.pas b/sys/kern/kern_dynlib.pas index 18d0b2c0..b0fe36d4 100644 --- a/sys/kern/kern_dynlib.pas +++ b/sys/kern/kern_dynlib.pas @@ -8,8 +8,6 @@ interface uses sysutils, mqueue, - elf64, - kern_thr, kern_rtld, subr_dynlib, kern_dlsym, diff --git a/sys/kern/subr_dynlib.pas b/sys/kern/subr_dynlib.pas index 8b18c6c7..b57a1dab 100644 --- a/sys/kern/subr_dynlib.pas +++ b/sys/kern/subr_dynlib.pas @@ -155,6 +155,7 @@ type p_sym_hash_entry=^t_sym_hash_entry; t_sym_hash_entry=record + link :TAILQ_ENTRY; nid :QWORD; mod_id:WORD; lib_id:WORD; @@ -168,6 +169,7 @@ type attr :WORD; import:WORD; hamt :THAMT; + syms :TAILQ_HEAD; end; t_DoneList=record @@ -2231,14 +2233,22 @@ begin if (Lib_Entry^.hamt=nil) then begin Lib_Entry^.hamt:=HAMT_create64; + TAILQ_INIT(@Lib_Entry^.syms); end; // data:=HAMT_insert64(Lib_Entry^.hamt,nid,h_entry); Assert(data<>nil,'NOMEM'); - if (data^<>h_entry) then //is another exists + // + if (data^<>h_entry) then begin + //is another exists FreeMem(h_entry); + end else + begin + //new + TAILQ_INSERT_TAIL(@Lib_Entry^.syms,h_entry,@h_entry^.link); end; + // end; end; diff --git a/sys/kern/trap.pas b/sys/kern/trap.pas index 5e1d9ca5..cb6658df 100644 --- a/sys/kern/trap.pas +++ b/sys/kern/trap.pas @@ -7,6 +7,7 @@ interface uses sysutils, + mqueue, ucontext, kern_thr; @@ -116,11 +117,17 @@ implementation uses errno, + systm, vmparam, machdep, md_context, kern_sig, - sysent; + sysent, + subr_dynlib, + elf_nid_utils, + ps4libdoc, + kern_rtld, + hamt; const NOT_PCB_FULL_IRET=not PCB_FULL_IRET; @@ -223,6 +230,253 @@ begin td^.pcb_flags:=f; end; +function fuptr(var base:Pointer):Pointer; +begin + Result:=nil; + copyin(@base,@Result,SizeOf(Pointer)); +end; + +function fuptr(var base:QWORD):QWORD; +begin + Result:=0; + copyin(@base,@Result,SizeOf(QWORD)); +end; + +function CaptureBacktrace(rbp:PPointer;skipframes,count:sizeint;frames:PCodePointer):sizeint; +var + adr:Pointer; +begin + Result:=0; + while (rbp<>nil) and + (rbp<>Pointer(QWORD(-1))) do + begin + adr:=fuptr(rbp[1]); + rbp:=fuptr(rbp[0]); + + if (adr<>nil) then + begin + if (skipframes<>0) then + begin + Dec(skipframes); + end else + if (count<>0) then + begin + frames[0]:=adr; + Dec(count); + Inc(frames); + Inc(Result); + end; + end else + begin + Break; + end; + + end; +end; + +type + TLQRec=record + Base :Pointer; + Addr :Pointer; + LastAdr:Pointer; + LastNid:QWORD; + end; + +Function trav_proc(h_entry:p_sym_hash_entry;var r:TLQRec):Integer; +var + adr:Pointer; +begin + Result:=0; + adr:=r.Base+fuptr(h_entry^.sym.st_value); + if (adr<=r.Addr) then + if (adr>r.LastAdr) then + begin + r.LastAdr:=adr; + r.LastNid:=fuptr(h_entry^.nid); + Result:=1; + end; +end; + +Function find_proc_lib_entry(lib_entry:p_Lib_Entry;var r:TLQRec):Integer; +var + h_entry:p_sym_hash_entry; +begin + Result:=0; + h_entry:=fuptr(lib_entry^.syms.tqh_first); + while (h_entry<>nil) do + begin + Result:=Result+trav_proc(h_entry,r); + h_entry:=fuptr(h_entry^.link.tqe_next); + end; +end; + +Function find_proc_obj(obj:p_lib_info;var r:TLQRec):Integer; +var + lib_entry:p_Lib_Entry; +begin + Result:=0; + lib_entry:=fuptr(obj^.lib_table.tqh_first); + while (lib_entry<>nil) do + begin + Result:=Result+find_proc_lib_entry(lib_entry,r); + lib_entry:=fuptr(lib_entry^.link.tqe_next); + end; +end; + +type + TDynlibLineInfo=record + func :shortstring; + source :shortstring; + base_addr:ptruint; + func_addr:ptruint; + end; + +function GetDynlibLineInfo(addr:ptruint;var info:TDynlibLineInfo):boolean; +var + obj:p_lib_info; + r:TLQRec; + adr:QWORD; +begin + Result:=False; + dynlibs_lock; + + obj:=fuptr(dynlibs_info.obj_list.tqh_first); + while (obj<>nil) do + begin + if (Pointer(addr)>=obj^.map_base) and + (Pointer(addr)<(obj^.map_base+obj^.map_size)) then + begin + r:=Default(TLQRec); + r.Addr:=Pointer(addr); + r.Base:=fuptr(obj^.map_base); + + info.base_addr:=QWORD(r.Base); + info.source:=dynlib_basename(obj^.lib_path); + + if (find_proc_obj(obj,r)<>0) then + begin + info.func:=ps4libdoc.GetFunctName(r.LastNid); + if (info.func='Unknow') then + begin + info.func:=EncodeValue64(r.LastNid); + end; + info.func_addr:=QWORD(r.LastAdr); + Result:=True; + end else + begin + info.func_addr:=0; + + adr:=QWORD(obj^.init_proc_addr); + if (adr<=QWORD(r.Addr)) then + if (adr>info.func_addr) then + begin + info.func:='dtInit'; + info.func_addr:=adr; + Result:=True; + end; + + adr:=QWORD(obj^.fini_proc_addr); + if (adr<=QWORD(r.Addr)) then + if (adr>info.func_addr) then + begin + info.func:='dtFini'; + info.func_addr:=adr; + Result:=True; + end; + + adr:=QWORD(obj^.entry_addr); + if (adr<=QWORD(r.Addr)) then + if (adr>info.func_addr) then + begin + info.func:='Entry'; + info.func_addr:=adr; + Result:=True; + end; + + end; + + dynlibs_unlock; + Exit; + end; + // + obj:=fuptr(obj^.link.tqe_next); + end; + + dynlibs_unlock; +end; + +function find_obj_by_handle(id:Integer):p_lib_info; +var + obj:p_lib_info; +begin + Result:=nil; + + obj:=TAILQ_FIRST(@dynlibs_info.obj_list); + while (obj<>nil) do + begin + if (obj^.id=id) then + begin + Exit(obj); + end; + // + obj:=TAILQ_NEXT(obj,@obj^.link); + end; +end; + +procedure print_frame(var f:text;frame:Pointer); +var + info:TDynlibLineInfo; + offset1:QWORD; + offset2:QWORD; + //line:longint; +begin + if is_guest_addr(ptruint(frame)) then + begin + info:=Default(TDynlibLineInfo); + + if GetDynlibLineInfo(ptruint(frame),info) then + begin + offset1:=QWORD(frame)-QWORD(info.base_addr); + offset2:=QWORD(frame)-QWORD(info.func_addr); + + Writeln(f,' offset $',HexStr(offset1,6),' ',info.source,':',info.func,'+$',HexStr(offset2,6)); + + end else + begin + Writeln(f,' 0x',HexStr(frame),' ',info.source); + end; + end else + begin + Writeln(f,BackTraceStrFunc(frame)); + end; + + //if GetLineInfo(ptruint(frame),func,source,line) then + //begin + // Writeln(f,' 0x',HexStr(frame),':',func,':',source); + //end}; + + //Writeln(f,BackTraceStrFunc(frame)); +end; + +procedure print_backtrace(var f:text;rip,rbp:Pointer;skipframes:sizeint); +var + i,count:sizeint; + frames:array [0..255] of codepointer; +begin + count:=max_frame_dump; + count:=20; + + print_frame(f,rip); + + count:=CaptureBacktrace(rbp,skipframes,count,@frames[0]); + + if (count<>0) then + for i:=0 to count-1 do + begin + print_frame(f,frames[i]); + end; +end; + type tsyscall=function(rdi,rsi,rdx,rcx,r8,r9:QWORD):Integer; @@ -257,6 +511,8 @@ begin Writeln(' [5]:0x',HexStr(td_frame^.tf_r8 ,16)); Writeln(' [6]:0x',HexStr(td_frame^.tf_r9 ,16)); + print_backtrace(StdErr,Pointer(td_frame^.tf_rip),Pointer(td_frame^.tf_rbp),0); + Assert(false,sysent_table[td_frame^.tf_rax].sy_name); end; end else @@ -271,6 +527,8 @@ begin Writeln(' [5]:0x',HexStr(td_frame^.tf_r8 ,16)); Writeln(' [6]:0x',HexStr(td_frame^.tf_r9 ,16)); + print_backtrace(StdErr,Pointer(td_frame^.tf_rip),Pointer(td_frame^.tf_rbp),0); + Assert(false,IntToStr(td_frame^.tf_rax)); end else begin @@ -286,12 +544,12 @@ begin if is_guest_addr(td_frame^.tf_rip) then begin Writeln('Guest syscall:',sysent_table[td_frame^.tf_rax].sy_name); - Writeln(' [1]:0x',HexStr(td_frame^.tf_rdi,16)); - Writeln(' [2]:0x',HexStr(td_frame^.tf_rsi,16)); - Writeln(' [3]:0x',HexStr(td_frame^.tf_rdx,16)); - Writeln(' [4]:0x',HexStr(td_frame^.tf_r10,16)); - Writeln(' [5]:0x',HexStr(td_frame^.tf_r8 ,16)); - Writeln(' [6]:0x',HexStr(td_frame^.tf_r9 ,16)); + //Writeln(' [1]:0x',HexStr(td_frame^.tf_rdi,16)); + //Writeln(' [2]:0x',HexStr(td_frame^.tf_rsi,16)); + //Writeln(' [3]:0x',HexStr(td_frame^.tf_rdx,16)); + //Writeln(' [4]:0x',HexStr(td_frame^.tf_r10,16)); + //Writeln(' [5]:0x',HexStr(td_frame^.tf_r8 ,16)); + //Writeln(' [6]:0x',HexStr(td_frame^.tf_r9 ,16)); end; error:=scall(td_frame^.tf_rdi, diff --git a/sys/syscalls.pas b/sys/syscalls.pas index 24a02998..8af43984 100644 --- a/sys/syscalls.pas +++ b/sys/syscalls.pas @@ -58,6 +58,7 @@ function _fcntl(fd,cmd:Integer;arg:QWORD):Integer; function select(nd:Integer;uin,uou,uex,utv:Pointer):Integer; function fsync(fd:Integer):Integer; function setpriority(which,who,prio:Integer):Integer; +function __sys_netcontrol(fd,op:Integer;buf:Pointer;nbuf:DWORD):Integer; function getpriority(which,who:Integer):Integer; function gettimeofday(tp,tzp:Pointer):Integer; function getrusage(who:Integer;rusage:Pointer):Integer; @@ -605,6 +606,13 @@ asm jmp cerror end; +function __sys_netcontrol(fd,op:Integer;buf:Pointer;nbuf:DWORD):Integer; assembler; nostackframe; +asm + movq $99,%rax + call fast_syscall + jmp cerror +end; + function getpriority(which,who:Integer):Integer; assembler; nostackframe; asm movq $100,%rax diff --git a/sys/sysent.pas b/sys/sysent.pas index 01d1746d..c9b99599 100644 --- a/sys/sysent.pas +++ b/sys/sysent.pas @@ -13,6 +13,7 @@ uses kern_evf, kern_gpo, kern_sig, + kern_bnet, kern_dmem, kern_exec, kern_exit, @@ -552,7 +553,7 @@ const ), (//[99] sy_narg:4; - sy_call:nil; + sy_call:@sys_netcontrol; sy_name:'sys_netcontrol' ), (//[100] diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index 22747383..a3d9e5cf 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -645,6 +645,10 @@ + + + + @@ -655,7 +659,7 @@ - + diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index 44f3199a..a8d5192e 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -96,7 +96,8 @@ uses kern_budget, kern_regmgr, kern_authinfo, - kern_dmem; + kern_dmem, + kern_bnet; const PAGE_MAP_COUNT=(qword(VM_MAXUSER_ADDRESS) shr PAGE_SHIFT);