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);