mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
8e2d1dafa8
commit
52733dddac
|
@ -423,13 +423,11 @@ begin
|
|||
if (mp^.mnt_optnew=nil) then Exit(EINVAL);
|
||||
if (vfs_getopt(mp^.mnt_optnew, 'from', @path, @plen)<>0) then Exit(EINVAL);
|
||||
if (path=nil) then Exit(EINVAL);
|
||||
if (plen=2) then
|
||||
|
||||
while (plen>0) and ((path[0]='/') or (path[0]='\')) do
|
||||
begin
|
||||
if (path[0]='/') or (path[0]='\') then
|
||||
begin
|
||||
path[0]:=#0;
|
||||
plen:=1;
|
||||
end;
|
||||
Inc(path);
|
||||
Dec(plen);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
|
@ -6,12 +6,14 @@ unit kern_exec;
|
|||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
mqueue,
|
||||
kern_thr,
|
||||
vnode,
|
||||
vuio,
|
||||
vcapability,
|
||||
elf64,
|
||||
kern_rtld,
|
||||
subr_dynlib;
|
||||
|
||||
function exec_alloc_args(args:p_image_args):Integer;
|
||||
|
@ -613,6 +615,7 @@ function self_load_section(imgp:p_image_params;
|
|||
use_mode_2mb:Boolean;
|
||||
name:pchar):Integer;
|
||||
var
|
||||
map:vm_map_t;
|
||||
vaddr_lo:QWORD;
|
||||
vaddr_hi:QWORD;
|
||||
base :Pointer;
|
||||
|
@ -648,23 +651,28 @@ begin
|
|||
|
||||
base:=Pointer(imgp^.image_header)+offset;
|
||||
|
||||
vm_map_lock(@g_vmspace.vm_map);
|
||||
map:=@g_vmspace.vm_map;
|
||||
|
||||
Result:=vm_map_insert(@g_vmspace.vm_map,nil,0,vaddr_lo,vaddr_hi,VM_PROT_RW,prot or VM_PROT_RW,0);
|
||||
vm_map_lock(map);
|
||||
|
||||
//remove prev if exist
|
||||
vm_map_delete(map,vaddr_lo,vaddr_hi);
|
||||
|
||||
Result:=vm_map_insert(map,nil,0,vaddr_lo,vaddr_hi,VM_PROT_RW,prot or VM_PROT_RW,0);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
vm_map_unlock(@g_vmspace.vm_map);
|
||||
vm_map_unlock(map);
|
||||
//
|
||||
Writeln(StdErr,'[KERNEL] self_load_section: vm_map_insert failed ',id,', ',HexStr(vaddr,8));
|
||||
Exit(vm_mmap_to_errno(Result));
|
||||
end;
|
||||
|
||||
vm_map_set_name_locked(@g_vmspace.vm_map,vaddr_lo,vaddr_hi,name);
|
||||
vm_map_set_name_locked(map,vaddr_lo,vaddr_hi,name);
|
||||
|
||||
Result:=copyout(base,Pointer(vaddr),filesz);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
vm_map_unlock(@g_vmspace.vm_map);
|
||||
vm_map_unlock(map);
|
||||
//
|
||||
Writeln(StdErr,'[KERNEL] self_load_section: copyout failed ',
|
||||
id,', ',HexStr(base),'->',HexStr(vaddr,8),':',HexStr(filesz,8));
|
||||
|
@ -672,16 +680,16 @@ begin
|
|||
Exit;
|
||||
end;
|
||||
|
||||
Result:=vm_map_protect(@g_vmspace.vm_map,vaddr_lo,vaddr_hi,prot,False);
|
||||
Result:=vm_map_protect(map,vaddr_lo,vaddr_hi,prot,False);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
vm_map_unlock(@g_vmspace.vm_map);
|
||||
vm_map_unlock(map);
|
||||
//
|
||||
Writeln(StdErr,'[KERNEL] self_load_section: vm_map_protect failed ',id,', ',HexStr(vaddr,8));
|
||||
Exit(vm_mmap_to_errno(Result));
|
||||
end;
|
||||
|
||||
vm_map_unlock(@g_vmspace.vm_map);
|
||||
vm_map_unlock(map);
|
||||
end;
|
||||
|
||||
|
||||
|
@ -1012,8 +1020,6 @@ var
|
|||
|
||||
init_proc_addr:Pointer;
|
||||
fini_proc_addr:Pointer;
|
||||
|
||||
count:Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
|
@ -1024,8 +1030,7 @@ begin
|
|||
|
||||
if (imgp^.dyn_exist=0) then
|
||||
begin
|
||||
TAILQ_INSERT_TAIL(@dynlibs_info.lib_list,lib,@lib^.entry);
|
||||
Inc(dynlibs_info.obj_count);
|
||||
dynlibs_add_obj(lib);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
|
@ -1036,18 +1041,9 @@ begin
|
|||
Exit;
|
||||
end;
|
||||
|
||||
if (lib^.rel_data=nil) then
|
||||
begin
|
||||
count:=0;
|
||||
end else
|
||||
begin
|
||||
count:=(lib^.rel_data^.pltrela_size div sizeof(elf64_rela))+(lib^.rel_data^.rela_size div sizeof(elf64_rela));
|
||||
end;
|
||||
init_relo_bits_process(lib);
|
||||
|
||||
lib^.relo_bits_process:=AllocMem((count+7) div 8);
|
||||
|
||||
TAILQ_INSERT_TAIL(@dynlibs_info.lib_list,lib,@lib^.entry);
|
||||
Inc(dynlibs_info.obj_count);
|
||||
dynlibs_add_obj(lib);
|
||||
|
||||
init_proc_addr:=lib^.init_proc_addr;
|
||||
fini_proc_addr:=lib^.fini_proc_addr;
|
||||
|
@ -1088,6 +1084,41 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function dynlib_proc_initialize_step3(imgp:p_image_params):Integer;
|
||||
var
|
||||
lib:p_lib_info;
|
||||
str:RawByteString;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
lib:=nil;
|
||||
|
||||
//if (td_proc->sdk_version < 0x5000000) {
|
||||
// *(byte *)&dynlibs_info->bits = *(byte *)&dynlibs_info->bits | 0x20;
|
||||
//}
|
||||
//if (imgp->dyn_exist == 0) goto _dyn_not_exist;
|
||||
|
||||
str:='/libkernel.sprx';
|
||||
lib:=preload_prx_modules(str);
|
||||
dynlibs_info.libkernel:=lib;
|
||||
|
||||
if (lib=nil) then
|
||||
begin
|
||||
Writeln(StdErr,'preload_prx_modules:',str,' not loaded');
|
||||
end;
|
||||
|
||||
str:='/libSceLibcInternal.sprx';
|
||||
lib:=preload_prx_modules(str);
|
||||
|
||||
if (lib=nil) then
|
||||
begin
|
||||
Writeln(StdErr,'preload_prx_modules:',str,' not loaded');
|
||||
end;
|
||||
|
||||
|
||||
writeln;
|
||||
end;
|
||||
|
||||
|
||||
function exec_self_imgact(imgp:p_image_params):Integer;
|
||||
var
|
||||
|
@ -1497,6 +1528,8 @@ begin
|
|||
|
||||
PROC_UNLOCK();
|
||||
|
||||
dynlib_proc_initialize_step3(imgp);
|
||||
|
||||
{ Set values passed into the program in registers. }
|
||||
exec_setregs(td, QWORD(imgp^.entry_addr), QWORD(stack_base));
|
||||
|
||||
|
|
|
@ -0,0 +1,538 @@
|
|||
unit kern_rtld;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
kern_thr,
|
||||
vfile,
|
||||
vnode,
|
||||
vm_object,
|
||||
vuio,
|
||||
elf64;
|
||||
|
||||
const
|
||||
AT_NULL = 0; // Terminates the vector.
|
||||
AT_IGNORE = 1; // Ignored entry.
|
||||
AT_EXECFD = 2; // File descriptor of program to load.
|
||||
AT_PHDR = 3; // Program header of program already loaded.
|
||||
AT_PHENT = 4; // Size of each program header entry.
|
||||
AT_PHNUM = 5; // Number of program header entries.
|
||||
AT_PAGESZ = 6; // Page size in bytes.
|
||||
AT_BASE = 7; // Interpreter's base address.
|
||||
AT_FLAGS = 8; // Flags (unused for i386).
|
||||
AT_ENTRY = 9; // Where interpreter should transfer control.
|
||||
AT_NOTELF =10; // Program is not ELF ??
|
||||
AT_UID =11; // Real uid.
|
||||
AT_EUID =12; // Effective uid.
|
||||
AT_GID =13; // Real gid.
|
||||
AT_EGID =14; // Effective gid.
|
||||
AT_EXECPATH =15; // Path to the executable.
|
||||
AT_CANARY =16; // Canary for SSP
|
||||
AT_CANARYLEN =17; // Length of the canary.
|
||||
AT_OSRELDATE =18; // OSRELDATE.
|
||||
AT_NCPUS =19; // Number of CPUs.
|
||||
AT_PAGESIZES =20; // Pagesizes.
|
||||
AT_PAGESIZESLEN=21; // Number of pagesizes.
|
||||
AT_TIMEKEEP =22; // Pointer to timehands.
|
||||
AT_STACKPROT =23; // Initial stack protection.
|
||||
|
||||
AT_COUNT =24; // Count of defined aux entry types.
|
||||
|
||||
ARG_MAX=262144; // max bytes for an exec function
|
||||
|
||||
ps_arg_cache_limit=$400;
|
||||
|
||||
type
|
||||
p_ps_strings=^t_ps_strings;
|
||||
t_ps_strings=packed record
|
||||
ps_argvstr :ppchar; //first of 0 or more argument string
|
||||
ps_nargvstr:Integer; //the number of argument strings
|
||||
_align1 :Integer; //
|
||||
ps_envstr :ppchar; //first of 0 or more environment strings
|
||||
ps_nenvstr :Integer; //the number of environment strings
|
||||
_align2 :Integer; //
|
||||
end;
|
||||
{$IF sizeof(t_ps_strings)<>32}{$STOP sizeof(t_ps_strings)<>32}{$ENDIF}
|
||||
|
||||
p_image_args=^t_image_args;
|
||||
t_image_args=packed record
|
||||
buf :PChar; //pointer to string buffer
|
||||
begin_argv :PChar; //beginning of argv in buf
|
||||
begin_envv :PChar; //beginning of envv in buf
|
||||
endp :PChar; //current `end' pointer of arg & env strings
|
||||
fname :PChar; //pointer to filename of executable (system space)
|
||||
fname_buf :PChar; //pointer to optional malloc(M_TEMP) buffer
|
||||
stringspace:Integer; //space left in arg & env buffer
|
||||
argc :Integer; //count of argument strings
|
||||
envc :Integer; //count of environment strings
|
||||
fd :Integer; //file descriptor of the executable
|
||||
end;
|
||||
|
||||
p_elf64_auxargs=^t_elf64_auxargs;
|
||||
t_elf64_auxargs=packed record
|
||||
execfd:Int64;
|
||||
phdr :QWORD;
|
||||
phent :QWORD;
|
||||
phnum :QWORD;
|
||||
pagesz:QWORD;
|
||||
base :QWORD;
|
||||
flags :QWORD;
|
||||
entry :QWORD;
|
||||
end;
|
||||
|
||||
p_authinfo=^t_authinfo;
|
||||
t_authinfo=packed record
|
||||
app_type_id:QWORD;
|
||||
app_flags :QWORD;
|
||||
app_cap :QWORD;
|
||||
unknow1 :array[0..1] of QWORD;
|
||||
s_prog_attr:QWORD;
|
||||
unknow2 :array[0..10] of QWORD;
|
||||
end;
|
||||
{$IF sizeof(t_authinfo)<>136}{$STOP sizeof(t_authinfo)<>136}{$ENDIF}
|
||||
|
||||
p_image_params=^t_image_params;
|
||||
t_image_params=packed record
|
||||
vp :p_vnode;
|
||||
obj :vm_object_t;
|
||||
attr :p_vattr;
|
||||
image_self :p_self_header;
|
||||
image_header:p_elf64_hdr;
|
||||
entry_addr :Pointer;
|
||||
reloc_base :Pointer;
|
||||
opened :Integer;
|
||||
elf_size :Integer;
|
||||
auxargs :p_elf64_auxargs;
|
||||
auxarg_size :QWORD;
|
||||
args :p_image_args;
|
||||
execpath :PChar;
|
||||
execpathp :Pointer;
|
||||
freepath :PChar;
|
||||
canary :Pointer;
|
||||
pagesizes :Pointer;
|
||||
canarylen :Integer;
|
||||
pagesizeslen:Integer;
|
||||
|
||||
dyn_vaddr:p_elf64_dyn;
|
||||
|
||||
tls_size :QWORD;
|
||||
tls_align :QWORD;
|
||||
tls_init_size:QWORD;
|
||||
tls_init_addr:Pointer;
|
||||
|
||||
eh_frame_hdr_addr:Pointer;
|
||||
eh_frame_hdr_size:QWORD;
|
||||
|
||||
authinfo:t_authinfo;
|
||||
|
||||
proc_param_addr:pSceProcParam;
|
||||
proc_param_size:QWORD;
|
||||
|
||||
module_param_addr:psceModuleParam;
|
||||
module_param_size:QWORD;
|
||||
|
||||
dyn_id :Integer;
|
||||
sce_dynlib_data_id:Integer;
|
||||
sce_comment_id :Integer;
|
||||
dyn_exist :Integer;
|
||||
|
||||
dyn_offset :QWORD;
|
||||
dyn_filesz :QWORD;
|
||||
|
||||
sce_dynlib_data_addr:QWORD;
|
||||
sce_dynlib_data_size:QWORD;
|
||||
|
||||
sce_comment_offset :QWORD;
|
||||
sce_comment_filesz :QWORD;
|
||||
|
||||
min_addr:QWORD;
|
||||
max_addr:QWORD;
|
||||
|
||||
relro_addr:Pointer;
|
||||
relro_size:QWORD;
|
||||
|
||||
hdr_e_type:Integer;
|
||||
end;
|
||||
|
||||
const
|
||||
M2MB_NOTDYN_FIXED=0; //Default =0 (ATTRIBUTE2:0x00000)
|
||||
M2MB_DISABLE =1; //NotUsed =32768 (ATTRIBUTE2:0x08000)
|
||||
M2MB_READONLY =2; //Text_rodata=65536 (ATTRIBUTE2:0x10000)
|
||||
M2MB_ENABLE =3; //All_section=98304 (ATTRIBUTE2:0x18000)
|
||||
|
||||
g_self_fixed:Integer=0;
|
||||
g_mode_2mb :Integer=M2MB_NOTDYN_FIXED;
|
||||
budget_ptype_caller:Integer=0;
|
||||
|
||||
function maxInt64(a,b:Int64):Int64; inline;
|
||||
function minInt64(a,b:Int64):Int64; inline;
|
||||
|
||||
function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr; inline;
|
||||
procedure exec_load_free(imgp:p_image_params);
|
||||
function exec_load_self(imgp:p_image_params):Integer;
|
||||
procedure exec_load_authinfo(imgp:p_image_params);
|
||||
|
||||
function is_used_mode_2mb(phdr:p_elf64_phdr;is_dynlib,budget_ptype_caller:Integer):Boolean;
|
||||
|
||||
function rtld_dirname(path,bname:pchar):Integer;
|
||||
function rtld_file_exists(path:pchar):Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
errno,
|
||||
vnamei,
|
||||
vfs_lookup,
|
||||
vfs_subr,
|
||||
vnode_if;
|
||||
|
||||
function maxInt64(a,b:Int64):Int64; inline;
|
||||
begin
|
||||
if (a>b) then Result:=a else Result:=b;
|
||||
end;
|
||||
|
||||
function minInt64(a,b:Int64):Int64; inline;
|
||||
begin
|
||||
if (a<b) then Result:=a else Result:=b;
|
||||
end;
|
||||
|
||||
function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr; inline;
|
||||
begin
|
||||
Result:=Pointer(elf_hdr+1);
|
||||
end;
|
||||
|
||||
function get_elf_phdr_offset(elf_hdr:p_elf64_hdr):Int64; inline;
|
||||
begin
|
||||
Result:=SizeOf(elf64_hdr);
|
||||
end;
|
||||
|
||||
procedure fixup_offset_size(var offset,size:Int64;max:Int64);
|
||||
var
|
||||
s,e:Int64;
|
||||
begin
|
||||
s:=offset;
|
||||
e:=s+size;
|
||||
|
||||
s:=MinInt64(s,max);
|
||||
e:=MinInt64(e,max);
|
||||
|
||||
offset:=s;
|
||||
size :=(e-s);
|
||||
end;
|
||||
|
||||
function kread(vp:p_vnode;buf:Pointer;nbyte,offset:Integer):Integer;
|
||||
var
|
||||
uio:t_uio;
|
||||
aio:iovec;
|
||||
begin
|
||||
uio:=Default(t_uio);
|
||||
aio:=Default(iovec);
|
||||
//
|
||||
aio.iov_base :=buf;
|
||||
aio.iov_len :=nbyte;
|
||||
//
|
||||
uio.uio_iov :=@aio;
|
||||
uio.uio_iovcnt:=1;
|
||||
uio.uio_offset:=offset;
|
||||
uio.uio_segflg:=UIO_SYSSPACE;
|
||||
uio.uio_rw :=UIO_READ;
|
||||
uio.uio_resid :=nbyte;
|
||||
uio.uio_td :=curkthread;
|
||||
//
|
||||
Result:=VOP_READ(vp,@uio,0);
|
||||
|
||||
if (Result=0) then
|
||||
begin
|
||||
if (uio.uio_resid<>0) then
|
||||
begin
|
||||
Result:=ENOEXEC;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure exec_load_free(imgp:p_image_params);
|
||||
begin
|
||||
FreeMem(imgp^.image_header);
|
||||
FreeMem(imgp^.image_self);
|
||||
imgp^.image_header:=nil;
|
||||
imgp^.image_self:=nil;
|
||||
imgp^.elf_size:=0;
|
||||
end;
|
||||
|
||||
function exec_load_self(imgp:p_image_params):Integer;
|
||||
Var
|
||||
vp:p_vnode;
|
||||
obj_size:Int64;
|
||||
n,s:Int64;
|
||||
Magic:DWORD;
|
||||
i,count:Integer;
|
||||
self_hdr :p_self_header;
|
||||
self_segs:p_self_segment;
|
||||
elf_hdr :p_elf64_hdr;
|
||||
elf_phdr :p_elf64_phdr;
|
||||
MinSeg :Int64;
|
||||
MaxSeg :Int64;
|
||||
src_ofs :Int64;
|
||||
dst_ofs :Int64;
|
||||
mem_size :Int64;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
if (imgp=nil) then Exit(EINVAL);
|
||||
|
||||
vp:=imgp^.vp;
|
||||
obj_size:=imgp^.attr^.va_size;
|
||||
|
||||
if (obj_size=0) then Exit(ENOEXEC);
|
||||
|
||||
Result:=kread(vp,@Magic,SizeOf(DWORD),0);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
case Magic of
|
||||
ELFMAG: //elf64
|
||||
begin
|
||||
elf_hdr:=AllocMem(obj_size);
|
||||
|
||||
Result:=kread(vp,elf_hdr,obj_size,0);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
FreeMem(elf_hdr);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
imgp^.image_header:=elf_hdr;
|
||||
imgp^.image_self :=nil;
|
||||
imgp^.elf_size :=obj_size;
|
||||
end;
|
||||
SELF_MAGIC: //self
|
||||
begin
|
||||
self_hdr:=AllocMem(obj_size);
|
||||
|
||||
Result:=kread(vp,self_hdr,obj_size,0);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
FreeMem(self_hdr);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if (self_hdr^.File_size>obj_size) then
|
||||
begin
|
||||
FreeMem(self_hdr);
|
||||
Exit(EFAULT);
|
||||
end;
|
||||
|
||||
count:=self_hdr^.Num_Segments;
|
||||
|
||||
if (count=0) then
|
||||
begin
|
||||
FreeMem(self_hdr);
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
self_segs:=Pointer(self_hdr+1);
|
||||
|
||||
For i:=0 to count-1 do
|
||||
if ((self_segs[i].flags and (SELF_PROPS_ENCRYPTED or SELF_PROPS_COMPRESSED))<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'exec_load_self:',imgp^.execpath,'is encrypted!');
|
||||
FreeMem(self_hdr);
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
elf_hdr:=Pointer(self_segs)+(count*SizeOf(t_self_segment));
|
||||
|
||||
elf_phdr:=get_elf_phdr(elf_hdr);
|
||||
|
||||
MinSeg:=High(Int64);
|
||||
MaxSeg:=0;
|
||||
|
||||
count:=self_hdr^.Num_Segments;
|
||||
|
||||
For i:=0 to count-1 do
|
||||
if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then
|
||||
begin
|
||||
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
|
||||
s:=elf_phdr[s].p_offset;
|
||||
MinSeg:=MinInt64(s,MinSeg);
|
||||
s:=s+minInt64(self_segs[i].filesz,self_segs[i].filesz);
|
||||
MaxSeg:=MaxInt64(s,MaxSeg);
|
||||
end;
|
||||
|
||||
if (MinSeg>MaxSeg) then
|
||||
begin
|
||||
FreeMem(self_hdr);
|
||||
Exit(EFAULT);
|
||||
end;
|
||||
|
||||
imgp^.image_header:=AllocMem(MaxSeg);
|
||||
imgp^.elf_size :=MaxSeg;
|
||||
|
||||
//elf_hdr part
|
||||
n:=ptruint(elf_hdr)-ptruint(self_hdr); //offset to hdr
|
||||
s:=self_hdr^.Header_Size+self_hdr^.Meta_size; //offset to end
|
||||
s:=MinInt64(obj_size,s); //min size
|
||||
s:=MaxInt64(s,n)-n; //get size
|
||||
|
||||
//first page
|
||||
Move(elf_hdr^,imgp^.image_header^,s);
|
||||
|
||||
count:=self_hdr^.Num_Segments;
|
||||
|
||||
For i:=0 to count-1 do
|
||||
if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then
|
||||
begin
|
||||
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
|
||||
|
||||
mem_size:=minInt64(self_segs[i].filesz,self_segs[i].memsz);
|
||||
|
||||
src_ofs:=self_segs[i].offset; //start offset
|
||||
dst_ofs:=elf_phdr[s].p_offset; //start offset
|
||||
|
||||
fixup_offset_size(src_ofs,mem_size,obj_size);
|
||||
fixup_offset_size(dst_ofs,mem_size,MaxSeg);
|
||||
|
||||
Move( (Pointer(self_hdr) +src_ofs)^, //src
|
||||
(Pointer(imgp^.image_header)+dst_ofs)^, //dst
|
||||
mem_size); //size
|
||||
end;
|
||||
|
||||
imgp^.image_self:=self_hdr;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure exec_load_authinfo(imgp:p_image_params);
|
||||
var
|
||||
hdr:p_elf64_hdr;
|
||||
authinfo:p_self_authinfo;
|
||||
s:ptruint;
|
||||
begin
|
||||
if (imgp=nil) then Exit;
|
||||
|
||||
imgp^.authinfo:=Default(t_authinfo);
|
||||
imgp^.authinfo.app_type_id:=QWORD($3100000000000001);
|
||||
|
||||
if (imgp^.image_header=nil) then Exit;
|
||||
if (imgp^.image_self =nil) then Exit;
|
||||
|
||||
hdr:=imgp^.image_header;
|
||||
s:=SizeOf(t_self_header);
|
||||
s:=s+(imgp^.image_self^.Num_Segments*SizeOf(t_self_segment));
|
||||
s:=s+get_elf_phdr_offset(hdr);
|
||||
s:=s+(hdr^.e_phnum*SizeOf(elf64_phdr));
|
||||
s:=AlignUp(s,SELF_SEGMENT_BLOCK_ALIGNMENT);
|
||||
|
||||
authinfo:=Pointer(Pointer(imgp^.image_self)+s);
|
||||
|
||||
imgp^.authinfo.app_type_id:=authinfo^.AuthorityID;
|
||||
end;
|
||||
|
||||
function is_used_mode_2mb(phdr:p_elf64_phdr;is_dynlib,budget_ptype_caller:Integer):Boolean;
|
||||
var
|
||||
flag_write:Integer;
|
||||
begin
|
||||
Result:=False;
|
||||
|
||||
if (budget_ptype_caller=0) then
|
||||
begin
|
||||
flag_write:=2;
|
||||
if (phdr^.p_type<>PT_SCE_RELRO) then
|
||||
begin
|
||||
flag_write:=phdr^.p_flags and 2;
|
||||
end;
|
||||
|
||||
case g_mode_2mb of
|
||||
M2MB_NOTDYN_FIXED:Result:=(is_dynlib=0) and (g_self_fixed<>0);
|
||||
M2MB_READONLY :Result:=(flag_write=0);
|
||||
M2MB_ENABLE :Result:=True;
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
function rtld_dirname(path,bname:pchar):Integer;
|
||||
var
|
||||
endp:pchar;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
{ Empty or NULL string gets treated as "." }
|
||||
if (path=nil) or (path^=#0) then
|
||||
begin
|
||||
bname[0]:='.';
|
||||
bname[1]:=#0;
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{ Strip trailing slashes }
|
||||
endp:=path + strlen(path) - 1;
|
||||
while (endp > path) and ((endp^='/') or (endp^='\')) do Dec(endp);
|
||||
|
||||
{ Find the start of the dir }
|
||||
while (endp > path) and ((endp^<>'/') and (endp^<>'\')) do Dec(endp);
|
||||
|
||||
{ Either the dir is "/" or there are no slashes }
|
||||
if (endp=path) then
|
||||
begin
|
||||
if ((endp^='/') or (endp^='\')) then
|
||||
begin
|
||||
bname[0]:='/';
|
||||
end else
|
||||
begin
|
||||
bname[0]:='.';
|
||||
end;
|
||||
bname[1]:=#0;
|
||||
Exit(0);
|
||||
end else
|
||||
begin
|
||||
repeat
|
||||
Dec(endp);
|
||||
until not ((endp > path) and ((endp^='/') or (endp^='\')));
|
||||
end;
|
||||
|
||||
if ((endp - path + 2) > PATH_MAX) then
|
||||
begin
|
||||
Writeln(StdErr,'Filename is too long:',path);
|
||||
Exit(-1);
|
||||
end;
|
||||
|
||||
Move(path^, bname^, endp - path + 1);
|
||||
bname[endp - path + 1]:=#0;
|
||||
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function rtld_file_exists(path:pchar):Boolean;
|
||||
var
|
||||
nd:t_nameidata;
|
||||
error:Integer;
|
||||
begin
|
||||
Result:=False;
|
||||
if (path=nil) then Exit;
|
||||
|
||||
NDINIT(@nd,LOOKUP,LOCKLEAF or FOLLOW or SAVENAME or MPSAFE, UIO_SYSSPACE, path, curkthread);
|
||||
|
||||
error:=nd_namei(@nd);
|
||||
|
||||
if (error=0) then
|
||||
begin
|
||||
NDFREE(@nd, NDF_ONLY_PNBUF);
|
||||
vput(nd.ni_vp);
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
NDFREE(@nd, NDF_ONLY_PNBUF);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -303,8 +303,9 @@ var
|
|||
p_nvcsw :Int64;
|
||||
p_nivcsw :Int64;
|
||||
|
||||
p_comm :array[0..MAXCOMLEN] of AnsiChar;
|
||||
prog_name:array[0..1023] of AnsiChar;
|
||||
p_comm :array[0..MAXCOMLEN] of AnsiChar;
|
||||
prog_name :array[0..1023] of AnsiChar;
|
||||
p_randomized_path:array[0..7] of AnsiChar;
|
||||
|
||||
p_klist:t_knlist;
|
||||
|
||||
|
@ -528,6 +529,8 @@ begin
|
|||
mtx_init(p_proc.p_mtx,'process lock');
|
||||
|
||||
knlist_init_mtx(@p_proc.p_klist,@p_proc.p_mtx);
|
||||
|
||||
p_proc.p_randomized_path:='system';
|
||||
end;
|
||||
|
||||
//
|
||||
|
|
|
@ -6,159 +6,11 @@ unit subr_dynlib;
|
|||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
mqueue,
|
||||
elf64,
|
||||
kern_thr,
|
||||
vfile,
|
||||
vnode,
|
||||
vm_object,
|
||||
vuio,
|
||||
elf64;
|
||||
|
||||
type
|
||||
p_image_args=^t_image_args;
|
||||
t_image_args=packed record
|
||||
buf :PChar; //pointer to string buffer
|
||||
begin_argv :PChar; //beginning of argv in buf
|
||||
begin_envv :PChar; //beginning of envv in buf
|
||||
endp :PChar; //current `end' pointer of arg & env strings
|
||||
fname :PChar; //pointer to filename of executable (system space)
|
||||
fname_buf :PChar; //pointer to optional malloc(M_TEMP) buffer
|
||||
stringspace:Integer; //space left in arg & env buffer
|
||||
argc :Integer; //count of argument strings
|
||||
envc :Integer; //count of environment strings
|
||||
fd :Integer; //file descriptor of the executable
|
||||
end;
|
||||
|
||||
p_elf64_auxargs=^t_elf64_auxargs;
|
||||
t_elf64_auxargs=packed record
|
||||
execfd:Int64;
|
||||
phdr :QWORD;
|
||||
phent :QWORD;
|
||||
phnum :QWORD;
|
||||
pagesz:QWORD;
|
||||
base :QWORD;
|
||||
flags :QWORD;
|
||||
entry :QWORD;
|
||||
end;
|
||||
|
||||
p_authinfo=^t_authinfo;
|
||||
t_authinfo=packed record
|
||||
app_type_id:QWORD;
|
||||
app_flags :QWORD;
|
||||
app_cap :QWORD;
|
||||
unknow1 :array[0..1] of QWORD;
|
||||
s_prog_attr:QWORD;
|
||||
unknow2 :array[0..10] of QWORD;
|
||||
end;
|
||||
{$IF sizeof(t_authinfo)<>136}{$STOP sizeof(t_authinfo)<>136}{$ENDIF}
|
||||
|
||||
p_image_params=^t_image_params;
|
||||
t_image_params=packed record
|
||||
vp :p_vnode;
|
||||
obj :vm_object_t;
|
||||
attr :p_vattr;
|
||||
image_self :p_self_header;
|
||||
image_header:p_elf64_hdr;
|
||||
entry_addr :Pointer;
|
||||
reloc_base :Pointer;
|
||||
opened :Integer;
|
||||
elf_size :Integer;
|
||||
auxargs :p_elf64_auxargs;
|
||||
auxarg_size :QWORD;
|
||||
args :p_image_args;
|
||||
execpath :PChar;
|
||||
execpathp :Pointer;
|
||||
freepath :PChar;
|
||||
canary :Pointer;
|
||||
pagesizes :Pointer;
|
||||
canarylen :Integer;
|
||||
pagesizeslen:Integer;
|
||||
|
||||
dyn_vaddr:p_elf64_dyn;
|
||||
|
||||
tls_size :QWORD;
|
||||
tls_align :QWORD;
|
||||
tls_init_size:QWORD;
|
||||
tls_init_addr:Pointer;
|
||||
|
||||
eh_frame_hdr_addr:Pointer;
|
||||
eh_frame_hdr_size:QWORD;
|
||||
|
||||
authinfo:t_authinfo;
|
||||
|
||||
proc_param_addr:pSceProcParam;
|
||||
proc_param_size:QWORD;
|
||||
|
||||
module_param_addr:psceModuleParam;
|
||||
module_param_size:QWORD;
|
||||
|
||||
dyn_id :Integer;
|
||||
sce_dynlib_data_id:Integer;
|
||||
sce_comment_id :Integer;
|
||||
dyn_exist :Integer;
|
||||
|
||||
dyn_offset :QWORD;
|
||||
dyn_filesz :QWORD;
|
||||
|
||||
sce_dynlib_data_addr:QWORD;
|
||||
sce_dynlib_data_size:QWORD;
|
||||
|
||||
sce_comment_offset :QWORD;
|
||||
sce_comment_filesz :QWORD;
|
||||
|
||||
min_addr:QWORD;
|
||||
max_addr:QWORD;
|
||||
|
||||
relro_addr:Pointer;
|
||||
relro_size:QWORD;
|
||||
|
||||
hdr_e_type:Integer;
|
||||
end;
|
||||
|
||||
const
|
||||
AT_NULL = 0; // Terminates the vector.
|
||||
AT_IGNORE = 1; // Ignored entry.
|
||||
AT_EXECFD = 2; // File descriptor of program to load.
|
||||
AT_PHDR = 3; // Program header of program already loaded.
|
||||
AT_PHENT = 4; // Size of each program header entry.
|
||||
AT_PHNUM = 5; // Number of program header entries.
|
||||
AT_PAGESZ = 6; // Page size in bytes.
|
||||
AT_BASE = 7; // Interpreter's base address.
|
||||
AT_FLAGS = 8; // Flags (unused for i386).
|
||||
AT_ENTRY = 9; // Where interpreter should transfer control.
|
||||
AT_NOTELF =10; // Program is not ELF ??
|
||||
AT_UID =11; // Real uid.
|
||||
AT_EUID =12; // Effective uid.
|
||||
AT_GID =13; // Real gid.
|
||||
AT_EGID =14; // Effective gid.
|
||||
AT_EXECPATH =15; // Path to the executable.
|
||||
AT_CANARY =16; // Canary for SSP
|
||||
AT_CANARYLEN =17; // Length of the canary.
|
||||
AT_OSRELDATE =18; // OSRELDATE.
|
||||
AT_NCPUS =19; // Number of CPUs.
|
||||
AT_PAGESIZES =20; // Pagesizes.
|
||||
AT_PAGESIZESLEN=21; // Number of pagesizes.
|
||||
AT_TIMEKEEP =22; // Pointer to timehands.
|
||||
AT_STACKPROT =23; // Initial stack protection.
|
||||
|
||||
AT_COUNT =24; // Count of defined aux entry types.
|
||||
|
||||
ARG_MAX=262144; // max bytes for an exec function
|
||||
|
||||
type
|
||||
p_ps_strings=^t_ps_strings;
|
||||
t_ps_strings=packed record
|
||||
ps_argvstr :ppchar; //first of 0 or more argument string
|
||||
ps_nargvstr:Integer; //the number of argument strings
|
||||
_align1 :Integer; //
|
||||
ps_envstr :ppchar; //first of 0 or more environment strings
|
||||
ps_nenvstr :Integer; //the number of environment strings
|
||||
_align2 :Integer; //
|
||||
end;
|
||||
{$IF sizeof(t_ps_strings)<>32}{$STOP sizeof(t_ps_strings)<>32}{$ENDIF}
|
||||
|
||||
const
|
||||
ps_arg_cache_limit=$400;
|
||||
kern_rtld;
|
||||
|
||||
type
|
||||
p_rel_data=^t_rel_data;
|
||||
|
@ -339,26 +191,7 @@ type
|
|||
|
||||
end;
|
||||
|
||||
const
|
||||
M2MB_NOTDYN_FIXED=0; //Default =0 (ATTRIBUTE2:0x00000)
|
||||
M2MB_DISABLE =1; //NotUsed =32768 (ATTRIBUTE2:0x08000)
|
||||
M2MB_READONLY =2; //Text_rodata=65536 (ATTRIBUTE2:0x10000)
|
||||
M2MB_ENABLE =3; //All_section=98304 (ATTRIBUTE2:0x18000)
|
||||
|
||||
const
|
||||
g_self_fixed:Integer=0;
|
||||
g_mode_2mb :Integer=M2MB_NOTDYN_FIXED;
|
||||
budget_ptype_caller:Integer=0;
|
||||
|
||||
function maxInt64(a,b:Int64):Int64; inline;
|
||||
function minInt64(a,b:Int64):Int64; inline;
|
||||
|
||||
function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr; inline;
|
||||
procedure exec_load_free(imgp:p_image_params);
|
||||
function exec_load_self(imgp:p_image_params):Integer;
|
||||
procedure exec_load_authinfo(imgp:p_image_params);
|
||||
function scan_phdr(imgp:p_image_params;phdr:p_elf64_phdr;count:Integer):Integer;
|
||||
function is_used_mode_2mb(phdr:p_elf64_phdr;is_dynlib,budget_ptype_caller:Integer):Boolean;
|
||||
function trans_prot(flags:Elf64_Word):Byte;
|
||||
|
||||
function obj_new():p_lib_info;
|
||||
|
@ -366,6 +199,7 @@ procedure obj_free(lib:p_lib_info);
|
|||
|
||||
function obj_get_str(lib:p_lib_info;offset:Int64):pchar;
|
||||
procedure object_add_name(obj:p_lib_info;name:pchar);
|
||||
function object_match_name(obj:p_lib_info;name:pchar):Boolean;
|
||||
|
||||
function Needed_new(lib:p_lib_info;str:pchar):p_Needed_Entry;
|
||||
function Lib_new(d_tag:DWORD;d_val:QWORD):p_Lib_Entry;
|
||||
|
@ -393,6 +227,13 @@ procedure initlist_add_neededs(var fini_proc_list:TAILQ_HEAD;
|
|||
|
||||
function digest_dynamic(lib:p_lib_info):Integer;
|
||||
|
||||
procedure dynlibs_add_obj(lib:p_lib_info);
|
||||
|
||||
procedure init_relo_bits_process(lib:p_lib_info);
|
||||
|
||||
function do_load_object(path:pchar):p_lib_info;
|
||||
function preload_prx_modules(const path:RawByteString):p_lib_info;
|
||||
|
||||
var
|
||||
dynlibs_info:t_dynlibs_info;
|
||||
|
||||
|
@ -403,253 +244,7 @@ uses
|
|||
systm,
|
||||
vm,
|
||||
vmparam,
|
||||
vnode_if;
|
||||
|
||||
function maxInt64(a,b:Int64):Int64; inline;
|
||||
begin
|
||||
if (a>b) then Result:=a else Result:=b;
|
||||
end;
|
||||
|
||||
function minInt64(a,b:Int64):Int64; inline;
|
||||
begin
|
||||
if (a<b) then Result:=a else Result:=b;
|
||||
end;
|
||||
|
||||
function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr; inline;
|
||||
begin
|
||||
Result:=Pointer(elf_hdr+1);
|
||||
end;
|
||||
|
||||
function get_elf_phdr_offset(elf_hdr:p_elf64_hdr):Int64; inline;
|
||||
begin
|
||||
Result:=SizeOf(elf64_hdr);
|
||||
end;
|
||||
|
||||
procedure fixup_offset_size(var offset,size:Int64;max:Int64);
|
||||
var
|
||||
s,e:Int64;
|
||||
begin
|
||||
s:=offset;
|
||||
e:=s+size;
|
||||
|
||||
s:=MinInt64(s,max);
|
||||
e:=MinInt64(e,max);
|
||||
|
||||
offset:=s;
|
||||
size :=(e-s);
|
||||
end;
|
||||
|
||||
function kread(vp:p_vnode;buf:Pointer;nbyte,offset:Integer):Integer;
|
||||
var
|
||||
uio:t_uio;
|
||||
aio:iovec;
|
||||
begin
|
||||
uio:=Default(t_uio);
|
||||
aio:=Default(iovec);
|
||||
//
|
||||
aio.iov_base :=buf;
|
||||
aio.iov_len :=nbyte;
|
||||
//
|
||||
uio.uio_iov :=@aio;
|
||||
uio.uio_iovcnt:=1;
|
||||
uio.uio_offset:=offset;
|
||||
uio.uio_segflg:=UIO_SYSSPACE;
|
||||
uio.uio_rw :=UIO_READ;
|
||||
uio.uio_resid :=nbyte;
|
||||
uio.uio_td :=curkthread;
|
||||
//
|
||||
Result:=VOP_READ(vp,@uio,0);
|
||||
|
||||
if (Result=0) then
|
||||
begin
|
||||
if (uio.uio_resid<>0) then
|
||||
begin
|
||||
Result:=ENOEXEC;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure exec_load_free(imgp:p_image_params);
|
||||
begin
|
||||
FreeMem(imgp^.image_header);
|
||||
FreeMem(imgp^.image_self);
|
||||
imgp^.image_header:=nil;
|
||||
imgp^.image_self:=nil;
|
||||
imgp^.elf_size:=0;
|
||||
end;
|
||||
|
||||
function exec_load_self(imgp:p_image_params):Integer;
|
||||
Var
|
||||
vp:p_vnode;
|
||||
obj_size:Int64;
|
||||
n,s:Int64;
|
||||
Magic:DWORD;
|
||||
i,count:Integer;
|
||||
self_hdr :p_self_header;
|
||||
self_segs:p_self_segment;
|
||||
elf_hdr :p_elf64_hdr;
|
||||
elf_phdr :p_elf64_phdr;
|
||||
MinSeg :Int64;
|
||||
MaxSeg :Int64;
|
||||
src_ofs :Int64;
|
||||
dst_ofs :Int64;
|
||||
mem_size :Int64;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
if (imgp=nil) then Exit(EINVAL);
|
||||
|
||||
vp:=imgp^.vp;
|
||||
obj_size:=imgp^.attr^.va_size;
|
||||
|
||||
if (obj_size=0) then Exit(ENOEXEC);
|
||||
|
||||
Result:=kread(vp,@Magic,SizeOf(DWORD),0);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
case Magic of
|
||||
ELFMAG: //elf64
|
||||
begin
|
||||
elf_hdr:=AllocMem(obj_size);
|
||||
|
||||
Result:=kread(vp,elf_hdr,obj_size,0);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
FreeMem(elf_hdr);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
imgp^.image_header:=elf_hdr;
|
||||
imgp^.image_self :=nil;
|
||||
imgp^.elf_size :=obj_size;
|
||||
end;
|
||||
SELF_MAGIC: //self
|
||||
begin
|
||||
self_hdr:=AllocMem(obj_size);
|
||||
|
||||
Result:=kread(vp,self_hdr,obj_size,0);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
FreeMem(self_hdr);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if (self_hdr^.File_size>obj_size) then
|
||||
begin
|
||||
FreeMem(self_hdr);
|
||||
Exit(EFAULT);
|
||||
end;
|
||||
|
||||
count:=self_hdr^.Num_Segments;
|
||||
|
||||
if (count=0) then
|
||||
begin
|
||||
FreeMem(self_hdr);
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
self_segs:=Pointer(self_hdr+1);
|
||||
|
||||
For i:=0 to count-1 do
|
||||
if ((self_segs[i].flags and (SELF_PROPS_ENCRYPTED or SELF_PROPS_COMPRESSED))<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'exec_load_self:',imgp^.execpath,'is encrypted!');
|
||||
FreeMem(self_hdr);
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
elf_hdr:=Pointer(self_segs)+(count*SizeOf(t_self_segment));
|
||||
|
||||
elf_phdr:=get_elf_phdr(elf_hdr);
|
||||
|
||||
MinSeg:=High(Int64);
|
||||
MaxSeg:=0;
|
||||
|
||||
count:=self_hdr^.Num_Segments;
|
||||
|
||||
For i:=0 to count-1 do
|
||||
if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then
|
||||
begin
|
||||
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
|
||||
s:=elf_phdr[s].p_offset;
|
||||
MinSeg:=MinInt64(s,MinSeg);
|
||||
s:=s+minInt64(self_segs[i].filesz,self_segs[i].filesz);
|
||||
MaxSeg:=MaxInt64(s,MaxSeg);
|
||||
end;
|
||||
|
||||
if (MinSeg>MaxSeg) then
|
||||
begin
|
||||
FreeMem(self_hdr);
|
||||
Exit(EFAULT);
|
||||
end;
|
||||
|
||||
imgp^.image_header:=AllocMem(MaxSeg);
|
||||
imgp^.elf_size :=MaxSeg;
|
||||
|
||||
//elf_hdr part
|
||||
n:=ptruint(elf_hdr)-ptruint(self_hdr); //offset to hdr
|
||||
s:=self_hdr^.Header_Size+self_hdr^.Meta_size; //offset to end
|
||||
s:=MinInt64(obj_size,s); //min size
|
||||
s:=MaxInt64(s,n)-n; //get size
|
||||
|
||||
//first page
|
||||
Move(elf_hdr^,imgp^.image_header^,s);
|
||||
|
||||
count:=self_hdr^.Num_Segments;
|
||||
|
||||
For i:=0 to count-1 do
|
||||
if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then
|
||||
begin
|
||||
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
|
||||
|
||||
mem_size:=minInt64(self_segs[i].filesz,self_segs[i].memsz);
|
||||
|
||||
src_ofs:=self_segs[i].offset; //start offset
|
||||
dst_ofs:=elf_phdr[s].p_offset; //start offset
|
||||
|
||||
fixup_offset_size(src_ofs,mem_size,obj_size);
|
||||
fixup_offset_size(dst_ofs,mem_size,MaxSeg);
|
||||
|
||||
Move( (Pointer(self_hdr) +src_ofs)^, //src
|
||||
(Pointer(imgp^.image_header)+dst_ofs)^, //dst
|
||||
mem_size); //size
|
||||
end;
|
||||
|
||||
imgp^.image_self:=self_hdr;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure exec_load_authinfo(imgp:p_image_params);
|
||||
var
|
||||
hdr:p_elf64_hdr;
|
||||
authinfo:p_self_authinfo;
|
||||
s:ptruint;
|
||||
begin
|
||||
if (imgp=nil) then Exit;
|
||||
|
||||
imgp^.authinfo:=Default(t_authinfo);
|
||||
imgp^.authinfo.app_type_id:=QWORD($3100000000000001);
|
||||
|
||||
if (imgp^.image_header=nil) then Exit;
|
||||
if (imgp^.image_self =nil) then Exit;
|
||||
|
||||
hdr:=imgp^.image_header;
|
||||
s:=SizeOf(t_self_header);
|
||||
s:=s+(imgp^.image_self^.Num_Segments*SizeOf(t_self_segment));
|
||||
s:=s+get_elf_phdr_offset(hdr);
|
||||
s:=s+(hdr^.e_phnum*SizeOf(elf64_phdr));
|
||||
s:=AlignUp(s,SELF_SEGMENT_BLOCK_ALIGNMENT);
|
||||
|
||||
authinfo:=Pointer(Pointer(imgp^.image_self)+s);
|
||||
|
||||
imgp^.authinfo.app_type_id:=authinfo^.AuthorityID;
|
||||
end;
|
||||
vm_map;
|
||||
|
||||
function scan_phdr(imgp:p_image_params;phdr:p_elf64_phdr;count:Integer):Integer;
|
||||
var
|
||||
|
@ -921,30 +516,6 @@ begin
|
|||
Result:=0;
|
||||
end;
|
||||
|
||||
function is_used_mode_2mb(phdr:p_elf64_phdr;is_dynlib,budget_ptype_caller:Integer):Boolean;
|
||||
var
|
||||
flag_write:Integer;
|
||||
begin
|
||||
Result:=False;
|
||||
|
||||
if (budget_ptype_caller=0) then
|
||||
begin
|
||||
flag_write:=2;
|
||||
if (phdr^.p_type<>PT_SCE_RELRO) then
|
||||
begin
|
||||
flag_write:=phdr^.p_flags and 2;
|
||||
end;
|
||||
|
||||
case g_mode_2mb of
|
||||
M2MB_NOTDYN_FIXED:Result:=(is_dynlib=0) and (g_self_fixed<>0);
|
||||
M2MB_READONLY :Result:=(flag_write=0);
|
||||
M2MB_ENABLE :Result:=True;
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
function trans_prot(flags:Elf64_Word):Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
|
@ -1545,6 +1116,21 @@ begin
|
|||
TAILQ_INSERT_TAIL(@obj^.names,entry,@entry^.link);
|
||||
end;
|
||||
|
||||
function object_match_name(obj:p_lib_info;name:pchar):Boolean;
|
||||
var
|
||||
entry:p_Name_Entry;
|
||||
begin
|
||||
entry:=TAILQ_FIRST(@obj^.names);
|
||||
while (entry<>nil) do
|
||||
begin
|
||||
if (StrComp(name,@entry^.name)=0) then
|
||||
begin
|
||||
Exit(True);
|
||||
end;
|
||||
end;
|
||||
Result:=False;
|
||||
end;
|
||||
|
||||
function Needed_new(lib:p_lib_info;str:pchar):p_Needed_Entry;
|
||||
var
|
||||
len:Integer;
|
||||
|
@ -1562,60 +1148,6 @@ begin
|
|||
Result^.export:=ord(d_tag=DT_SCE_IMPORT_LIB);
|
||||
end;
|
||||
|
||||
function rtld_dirname(path,bname:pchar):Integer;
|
||||
var
|
||||
endp:pchar;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
{ Empty or NULL string gets treated as "." }
|
||||
if (path=nil) or (path^=#0) then
|
||||
begin
|
||||
bname[0]:='.';
|
||||
bname[1]:=#0;
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
{ Strip trailing slashes }
|
||||
endp:=path + strlen(path) - 1;
|
||||
while (endp > path) and ((endp^='/') or (endp^='\')) do Dec(endp);
|
||||
|
||||
{ Find the start of the dir }
|
||||
while (endp > path) and ((endp^<>'/') and (endp^<>'\')) do Dec(endp);
|
||||
|
||||
{ Either the dir is "/" or there are no slashes }
|
||||
if (endp=path) then
|
||||
begin
|
||||
if ((endp^='/') or (endp^='\')) then
|
||||
begin
|
||||
bname[0]:='/';
|
||||
end else
|
||||
begin
|
||||
bname[0]:='.';
|
||||
end;
|
||||
bname[1]:=#0;
|
||||
Exit(0);
|
||||
end else
|
||||
begin
|
||||
repeat
|
||||
Dec(endp);
|
||||
until not ((endp > path) and ((endp^='/') or (endp^='\')));
|
||||
end;
|
||||
|
||||
if ((endp - path + 2) > PATH_MAX) then
|
||||
begin
|
||||
Writeln(StdErr,'Filename is too long:',path);
|
||||
Exit(-1);
|
||||
end;
|
||||
|
||||
Move(path^, bname^, endp - path + 1);
|
||||
bname[endp - path + 1]:=#0;
|
||||
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure initlist_add_objects(var fini_proc_list:TAILQ_HEAD;
|
||||
obj :p_lib_info;
|
||||
tail:p_lib_info;
|
||||
|
@ -1974,6 +1506,183 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure dynlibs_add_obj(lib:p_lib_info);
|
||||
begin
|
||||
TAILQ_INSERT_TAIL(@dynlibs_info.lib_list,lib,@lib^.entry);
|
||||
Inc(dynlibs_info.obj_count);
|
||||
end;
|
||||
|
||||
procedure init_relo_bits_process(lib:p_lib_info);
|
||||
var
|
||||
count:Integer;
|
||||
begin
|
||||
if (lib^.rel_data=nil) then
|
||||
begin
|
||||
count:=0;
|
||||
end else
|
||||
begin
|
||||
count:=(lib^.rel_data^.pltrela_size div sizeof(elf64_rela))+(lib^.rel_data^.rela_size div sizeof(elf64_rela));
|
||||
end;
|
||||
|
||||
lib^.relo_bits_process:=AllocMem((count+7) div 8);
|
||||
end;
|
||||
|
||||
function self_load_shared_object(path:pchar;new:p_lib_info):Integer;
|
||||
begin
|
||||
Result:=-1;
|
||||
|
||||
//////////
|
||||
end;
|
||||
|
||||
function do_load_object(path:pchar):p_lib_info;
|
||||
label
|
||||
_inc_max,
|
||||
_error;
|
||||
var
|
||||
fname:RawByteString;
|
||||
new:p_lib_info;
|
||||
lib:p_lib_info;
|
||||
i,err:Integer;
|
||||
tls_max:Integer;
|
||||
map_base:Pointer;
|
||||
map_size:QWORD;
|
||||
map:vm_map_t;
|
||||
begin
|
||||
Result:=nil;
|
||||
|
||||
new:=obj_new();
|
||||
|
||||
err:=self_load_shared_object(path,new);
|
||||
if (err<>0) then
|
||||
begin
|
||||
goto _error;
|
||||
end;
|
||||
|
||||
fname:=ExtractFileName(path);
|
||||
object_add_name(new,pchar(fname));
|
||||
|
||||
_set_lib_path(new,path);
|
||||
|
||||
if (new^.tls_size=0) then
|
||||
begin
|
||||
i:=0;
|
||||
end else
|
||||
begin
|
||||
dynlibs_info.tls_count:=dynlibs_info.tls_count + 1;
|
||||
tls_max:=dynlibs_info.tls_max;
|
||||
|
||||
if (tls_max<1) then
|
||||
begin
|
||||
_inc_max:
|
||||
i:=tls_max+1;
|
||||
dynlibs_info.tls_max:=i;
|
||||
end else
|
||||
begin
|
||||
i:=1;
|
||||
lib:=TAILQ_FIRST(@dynlibs_info.lib_list);
|
||||
while (lib<>nil) do
|
||||
begin
|
||||
while (lib^.tls_index=i) do
|
||||
begin
|
||||
i:=i+1;
|
||||
lib:=TAILQ_FIRST(@dynlibs_info.lib_list);
|
||||
if (tls_max < i) then
|
||||
begin
|
||||
goto _inc_max;
|
||||
end;
|
||||
end;
|
||||
lib:=TAILQ_NEXT(lib,@lib^.entry);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
new^.tls_index:=i;
|
||||
|
||||
err:=digest_dynamic(new);
|
||||
if (err<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'do_load_object:','digest_dynamic() failed rv=',err);
|
||||
goto _error;
|
||||
end;
|
||||
|
||||
//err:=dynlib_initialize_pltgot_each(new);
|
||||
if (err<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'do_load_object:','dynlib_initialize_pltgot_each() failed rv=',err);
|
||||
goto _error;
|
||||
end;
|
||||
|
||||
if (new^.textrel<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'do_load_object:',new^.lib_path,' has impure text');
|
||||
err:=EINVAL;
|
||||
goto _error;
|
||||
end;
|
||||
|
||||
init_relo_bits_process(lib);
|
||||
dynlibs_add_obj(new);
|
||||
new^.loaded:=1;
|
||||
Exit(new);
|
||||
|
||||
_error:
|
||||
|
||||
map_base:=new^.map_base;
|
||||
map_size:=new^.map_size;
|
||||
|
||||
if (map_base<>nil) then
|
||||
begin
|
||||
map:=@g_vmspace.vm_map;
|
||||
|
||||
vm_map_lock(map);
|
||||
vm_map_delete(map,QWORD(map_base),QWORD(map_base) + map_size);
|
||||
vm_map_unlock(map);
|
||||
end;
|
||||
|
||||
obj_free(new);
|
||||
|
||||
Exit(nil);
|
||||
end;
|
||||
|
||||
function preload_prx_modules(const path:RawByteString):p_lib_info;
|
||||
label
|
||||
_do_load;
|
||||
var
|
||||
lib:p_lib_info;
|
||||
fname:RawByteString;
|
||||
begin
|
||||
Result:=nil;
|
||||
|
||||
fname:=ExtractFileName(path);
|
||||
|
||||
lib:=TAILQ_FIRST(@dynlibs_info.lib_list);
|
||||
while (lib<>nil) do
|
||||
begin
|
||||
if object_match_name(lib,pchar(fname)) then
|
||||
begin
|
||||
Exit(lib);
|
||||
end;
|
||||
lib:=TAILQ_NEXT(lib,@lib^.entry);
|
||||
end;
|
||||
|
||||
fname:=path;
|
||||
if (fname[1]='/') then //relative?
|
||||
begin
|
||||
fname:=p_proc.p_randomized_path+fname;
|
||||
end;
|
||||
|
||||
if rtld_file_exists(pchar(fname)) then goto _do_load;
|
||||
|
||||
fname:=ChangeFileExt(fname,'.sprx');
|
||||
if rtld_file_exists(pchar(fname)) then goto _do_load;
|
||||
|
||||
fname:=ChangeFileExt(fname,'.prx');
|
||||
if rtld_file_exists(pchar(fname)) then goto _do_load;
|
||||
|
||||
Exit(nil);
|
||||
_do_load:
|
||||
|
||||
Result:=do_load_object(pchar(fname));
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
@ -573,6 +573,10 @@
|
|||
<Filename Value="..\kern\subr_dynlib.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\kern\kern_rtld.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
|
@ -1095,10 +1095,14 @@ begin
|
|||
FreeMem(ndp^.ni_cnd.cn_pnbuf);
|
||||
ndp^.ni_cnd.cn_flags:=ndp^.ni_cnd.cn_flags and (not HASBUF);
|
||||
end;
|
||||
|
||||
if ((flags and NDF_NO_VP_UNLOCK)=0) and
|
||||
((ndp^.ni_cnd.cn_flags and LOCKLEAF)<>0) and
|
||||
(ndp^.ni_vp<>nil) then
|
||||
begin
|
||||
unlock_vp:=1;
|
||||
end;
|
||||
|
||||
if (((flags and NDF_NO_VP_RELE)=0) and (ndp^.ni_vp<>nil)) then
|
||||
begin
|
||||
if (unlock_vp<>0) then
|
||||
|
@ -1106,15 +1110,24 @@ begin
|
|||
vput(ndp^.ni_vp);
|
||||
unlock_vp:=0;
|
||||
end else
|
||||
begin
|
||||
vrele(ndp^.ni_vp);
|
||||
end;
|
||||
ndp^.ni_vp:=nil;
|
||||
end;
|
||||
|
||||
if (unlock_vp<>0) then
|
||||
begin
|
||||
VOP_UNLOCK(ndp^.ni_vp, 0);
|
||||
end;
|
||||
|
||||
if ((flags and NDF_NO_DVP_UNLOCK)=0) and
|
||||
((ndp^.ni_cnd.cn_flags and LOCKPARENT)<>0) and
|
||||
(ndp^.ni_dvp<>ndp^.ni_vp) then
|
||||
begin
|
||||
unlock_dvp:=1;
|
||||
end;
|
||||
|
||||
if ((flags and NDF_NO_DVP_RELE)=0) and
|
||||
((ndp^.ni_cnd.cn_flags and (LOCKPARENT or WANTPARENT))<>0) then
|
||||
begin
|
||||
|
@ -1123,11 +1136,17 @@ begin
|
|||
vput(ndp^.ni_dvp);
|
||||
unlock_dvp:=0;
|
||||
end else
|
||||
begin
|
||||
vrele(ndp^.ni_dvp);
|
||||
end;
|
||||
ndp^.ni_dvp:=nil;
|
||||
end;
|
||||
|
||||
if (unlock_dvp<>0) then
|
||||
begin
|
||||
VOP_UNLOCK(ndp^.ni_dvp, 0);
|
||||
end;
|
||||
|
||||
if ((flags and NDF_NO_STARTDIR_RELE)=0) and
|
||||
((ndp^.ni_cnd.cn_flags and SAVESTART)<>0) then
|
||||
begin
|
||||
|
|
|
@ -386,6 +386,12 @@ begin
|
|||
error:=vfs_mountroot_simple('ufs','/app0','/',nil,0);
|
||||
end;
|
||||
|
||||
error:=kern_mkdir('system',UIO_SYSSPACE,&777);
|
||||
if (error=0) then
|
||||
begin
|
||||
error:=vfs_mountroot_simple('ufs','/system','/system',nil,0);
|
||||
end;
|
||||
|
||||
//error:=kern_unmount('/app0',0);
|
||||
|
||||
mount_print;
|
||||
|
|
Loading…
Reference in New Issue