mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
8740fedec5
commit
4a8b4a910e
|
@ -5,21 +5,282 @@ unit kern_dlsym;
|
|||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
mqueue,
|
||||
elf64,
|
||||
kern_thr,
|
||||
kern_rtld,
|
||||
subr_dynlib;
|
||||
|
||||
function do_dlsym(obj:p_lib_info;symbol,libname:pchar;flags:DWORD):Pointer;
|
||||
const
|
||||
SYMLOOK_BASE64 =$001;
|
||||
SYMLOOK_IN_PLT =$002;
|
||||
SYMLOOK_NOT_DBG =$008;
|
||||
SYMLOOK_DLSYM =$00A;
|
||||
SYMLOOK_MANGLED =$100;
|
||||
|
||||
type
|
||||
p_SymLook=^t_SymLook;
|
||||
t_SymLook=record
|
||||
name :pchar;
|
||||
modname :pchar;
|
||||
libname :pchar;
|
||||
symbol :pchar;
|
||||
hash :QWORD;
|
||||
flags :DWORD;
|
||||
obj :p_lib_info;
|
||||
defobj_out:p_lib_info;
|
||||
sym_out :p_elf64_sym;
|
||||
end;
|
||||
|
||||
function do_dlsym(obj:p_lib_info;symbol,modname:pchar;flags:DWORD):Pointer;
|
||||
function find_symdef(symnum:QWORD;refobj:p_lib_info;var defobj_out:p_lib_info;flags:DWORD;cache:p_SymCache):p_elf64_sym;
|
||||
|
||||
implementation
|
||||
|
||||
function do_dlsym(obj:p_lib_info;symbol,libname:pchar;flags:DWORD):Pointer;
|
||||
uses
|
||||
errno,
|
||||
elf_nid_utils;
|
||||
|
||||
function convert_raw_symbol_str_to_base64(symbol:pchar):RawByteString;
|
||||
var
|
||||
nid:QWORD;
|
||||
begin
|
||||
nid:=ps4_nid_hash(symbol);
|
||||
Result:=EncodeValue64(nid);
|
||||
end;
|
||||
|
||||
function symlook_obj(req:p_SymLook;obj:p_lib_info):Integer;
|
||||
begin
|
||||
///////
|
||||
|
||||
end;
|
||||
|
||||
function symlook_list(req:p_SymLook;var objlist:TAILQ_HEAD;var dlp:t_DoneList):Integer;
|
||||
label
|
||||
_symlook_obj;
|
||||
var
|
||||
libname:pchar;
|
||||
req1:t_SymLook;
|
||||
elm:p_Objlist_Entry;
|
||||
def:p_elf64_sym;
|
||||
defobj:p_lib_info;
|
||||
lib_entry:p_Lib_Entry;
|
||||
offset:QWORD;
|
||||
str:pchar;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
if ((req^.flags and SYMLOOK_MANGLED)=0) then
|
||||
begin
|
||||
libname:=req^.libname;
|
||||
end else
|
||||
if (req^.symbol=nil) then
|
||||
begin
|
||||
libname:=nil;
|
||||
end else
|
||||
begin
|
||||
libname:=strrscan(req^.symbol,'#');
|
||||
if (libname<>nil) then
|
||||
begin
|
||||
libname:=libname+1;
|
||||
end;
|
||||
end;
|
||||
|
||||
def :=nil;
|
||||
defobj:=nil;
|
||||
|
||||
elm:=TAILQ_FIRST(@objlist);
|
||||
|
||||
while (elm<>nil) do
|
||||
begin
|
||||
if not donelist_check(dlp,elm^.obj) then
|
||||
begin
|
||||
if (libname=nil) then
|
||||
begin
|
||||
_symlook_obj:
|
||||
req1:=req^;
|
||||
Result:=symlook_obj(@req1,elm^.obj);
|
||||
|
||||
if (Result=0) then
|
||||
begin
|
||||
if (def=nil) or (ELF64_ST_BIND(req1.sym_out^.st_info)<>STB_WEAK) then
|
||||
begin
|
||||
def :=req1.sym_out;
|
||||
defobj:=req1.defobj_out;
|
||||
if (ELF64_ST_BIND(def^.st_info)<>STB_WEAK) then Break;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
lib_entry:=TAILQ_FIRST(@elm^.obj^.lib_table);
|
||||
while (lib_entry<>nil) do
|
||||
begin
|
||||
if (lib_entry^.dval.id=0) then //export?
|
||||
begin
|
||||
offset:=lib_entry^.dval.name_offset;
|
||||
str:=obj_get_str(elm^.obj,offset);
|
||||
if (StrComp(str,libname)=0) then
|
||||
begin
|
||||
goto _symlook_obj;
|
||||
end;
|
||||
Break;
|
||||
end;
|
||||
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
elm:=TAILQ_NEXT(elm,@elm^.link);
|
||||
end;
|
||||
|
||||
if (def<>nil) then
|
||||
begin
|
||||
req^.sym_out :=def;
|
||||
req^.defobj_out:=defobj;
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
Exit(ESRCH);
|
||||
end;
|
||||
|
||||
function symlook_global(req:p_SymLook;var donelist:t_DoneList):Integer;
|
||||
var
|
||||
req1:t_SymLook;
|
||||
elm:p_Objlist_Entry;
|
||||
begin
|
||||
req1:=req^;
|
||||
|
||||
//Search all objects loaded at program start up.
|
||||
if (req^.defobj_out=nil) or
|
||||
(ELF64_ST_BIND(req^.sym_out^.st_info)=STB_WEAK) then
|
||||
begin
|
||||
|
||||
Result:=symlook_list(@req1, dynlibs_info.needed, donelist);
|
||||
|
||||
if (Result=0) then
|
||||
begin
|
||||
if (req^.defobj_out=nil) or
|
||||
(ELF64_ST_BIND(req1.sym_out^.st_info)<>STB_WEAK) then
|
||||
begin
|
||||
req^.sym_out :=req1.sym_out;
|
||||
req^.defobj_out:=req1.defobj_out;
|
||||
Assert(req^.defobj_out<>nil,'req->defobj_out is NULL #1');
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
//Search all DAGs whose roots are RTLD_GLOBAL objects.
|
||||
elm:=TAILQ_FIRST(@dynlibs_info.list_global);
|
||||
while (elm<>nil) do
|
||||
begin
|
||||
if (req^.defobj_out<>nil) and
|
||||
(ELF64_ST_BIND(req^.sym_out^.st_info)<>STB_WEAK) then
|
||||
begin
|
||||
Break;
|
||||
end;
|
||||
|
||||
Result:=symlook_list(@req1,elm^.obj^.dagmembers,donelist);
|
||||
|
||||
if (Result=0) then
|
||||
begin
|
||||
if (req^.defobj_out=nil) or
|
||||
(ELF64_ST_BIND(req1.sym_out^.st_info)<>STB_WEAK) then
|
||||
begin
|
||||
req^.sym_out :=req1.sym_out;
|
||||
req^.defobj_out:=req1.defobj_out;
|
||||
Assert(req^.defobj_out<>nil,'req->defobj_out is NULL #2');
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
elm:=TAILQ_NEXT(elm,@elm^.link);
|
||||
end;
|
||||
|
||||
if (req^.sym_out<>nil) then
|
||||
Exit(0)
|
||||
else
|
||||
Exit(ESRCH);
|
||||
end;
|
||||
|
||||
function do_dlsym(obj:p_lib_info;symbol,modname:pchar;flags:DWORD):Pointer;
|
||||
var
|
||||
req:t_SymLook;
|
||||
lib_entry:p_Lib_Entry;
|
||||
offset:QWORD;
|
||||
base64:RawByteString;
|
||||
donelist:t_DoneList;
|
||||
err:Integer;
|
||||
begin
|
||||
Result:=nil;
|
||||
////
|
||||
|
||||
if TAILQ_EMPTY(@obj^.lib_table) then
|
||||
begin
|
||||
req.libname:=nil;
|
||||
end else
|
||||
begin
|
||||
req.libname:=nil;
|
||||
lib_entry:=TAILQ_FIRST(@obj^.lib_table);
|
||||
while (lib_entry<>nil) do
|
||||
begin
|
||||
if (lib_entry^.dval.id=0) then //export?
|
||||
begin
|
||||
offset:=lib_entry^.dval.name_offset;
|
||||
req.libname:=obj_get_str(obj,offset);
|
||||
end;
|
||||
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
|
||||
end;
|
||||
end;
|
||||
|
||||
req.flags:=flags or SYMLOOK_DLSYM;
|
||||
|
||||
if ((flags and SYMLOOK_BASE64)=0) then
|
||||
begin
|
||||
req.modname:=modname;
|
||||
if (modname=nil) then
|
||||
begin
|
||||
req.modname:=req.libname;
|
||||
end;
|
||||
base64:=convert_raw_symbol_str_to_base64(symbol);
|
||||
symbol:=pchar(base64);
|
||||
end else
|
||||
begin
|
||||
req.modname:=nil;
|
||||
req.libname:=nil;
|
||||
end;
|
||||
|
||||
req.symbol :=nil;
|
||||
req.name :=symbol;
|
||||
//req.hash :=elf_hash(@req);
|
||||
req.defobj_out:=nil;
|
||||
req.sym_out :=nil;
|
||||
req.obj :=obj;
|
||||
|
||||
donelist:=Default(t_DoneList);
|
||||
donelist_init(donelist);
|
||||
|
||||
err:=0;
|
||||
if (obj^.mainprog=0) then
|
||||
begin
|
||||
err:=symlook_list(@req,obj^.dagmembers,donelist);
|
||||
end else
|
||||
begin
|
||||
err:=symlook_global(@req,donelist);
|
||||
end;
|
||||
|
||||
if (err<>0) then
|
||||
begin
|
||||
req.defobj_out:=nil;
|
||||
req.sym_out :=nil;
|
||||
end;
|
||||
|
||||
if (req.sym_out=nil) then
|
||||
begin
|
||||
Result:=nil;
|
||||
end else
|
||||
begin
|
||||
Result:=req.defobj_out^.relocbase + req.sym_out^.st_value;
|
||||
end;
|
||||
end;
|
||||
|
||||
function find_symdef(symnum:QWORD;refobj:p_lib_info;var defobj_out:p_lib_info;flags:DWORD;cache:p_SymCache):p_elf64_sym;
|
||||
|
|
|
@ -159,7 +159,7 @@ begin
|
|||
Result:=copyin(where,@data,SizeOf(Pointer)); //data:=where^
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyin() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyin() failed. where=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -168,7 +168,7 @@ begin
|
|||
Result:=copyout(@data,where,8); //where^:=data
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -180,7 +180,7 @@ begin
|
|||
Result:=copyin(where,@data,SizeOf(Pointer)); //data:=where^
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyin() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyin() failed. where=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -189,7 +189,7 @@ begin
|
|||
Result:=copyout(@data,where,8); //where^:=data
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -209,7 +209,7 @@ begin
|
|||
Result:=copyout(@data,where,SizeOf(Pointer));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -247,7 +247,7 @@ begin
|
|||
Result:=check_addr(defobj,data,SizeOf(Integer));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','idx=',i,' where32=0x',HexStr(data32,8),' ref=',dynlib_basename(defobj^.lib_path));
|
||||
Writeln(StdErr,'reloc_non_plt:','idx=',i,' where32=0x',HexStr(where),' ref=',dynlib_basename(defobj^.lib_path));
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
@ -255,7 +255,7 @@ begin
|
|||
Result:=relocate_text_or_data_segment(obj,@data32,where,SizeOf(Integer));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where32=0x',HexStr(data32,8),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where32=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -267,7 +267,7 @@ begin
|
|||
Result:=copyin(where,@data,SizeOf(Pointer)); //data:=where^
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyin() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyin() failed. where32=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -276,7 +276,7 @@ begin
|
|||
Result:=copyout(@data,where,8); //where^:=data
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where32=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -297,7 +297,7 @@ begin
|
|||
Result:=copyout(@data32,where,SizeOf(Integer));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where32=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -327,14 +327,14 @@ begin
|
|||
Result:=check_addr(defobj,data,SizeOf(Pointer));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','idx=',i,' where=0x',HexStr(data),' ref=',dynlib_basename(defobj^.lib_path));
|
||||
Writeln(StdErr,'reloc_non_plt:','idx=',i,' where=0x',HexStr(where),' ref=',dynlib_basename(defobj^.lib_path));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Result:=relocate_text_or_data_segment(obj,@data,where,SizeOf(Pointer));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(data),' [',r_type,']');
|
||||
Writeln(StdErr,'reloc_non_plt:','copyout() failed. where=0x',HexStr(where),' [',r_type,']');
|
||||
Exit(ENOEXEC);
|
||||
end;
|
||||
|
||||
|
@ -343,11 +343,102 @@ begin
|
|||
goto _next;
|
||||
end;
|
||||
|
||||
function reloc_jmpslot(obj:p_lib_info;i:Integer;cache:p_SymCache;flags:Integer):Integer;
|
||||
var
|
||||
idofs:Integer;
|
||||
entry:p_elf64_rela;
|
||||
|
||||
function reloc_jmplots(obj:p_lib_info):Integer;
|
||||
where:Pointer;
|
||||
data:Pointer;
|
||||
|
||||
def:p_elf64_sym;
|
||||
defobj:p_lib_info;
|
||||
begin
|
||||
Result:=0;
|
||||
//////
|
||||
|
||||
if (i<0) or (i>=(obj^.rel_data^.pltrela_size div SizeOf(elf64_rela))) then
|
||||
begin
|
||||
Exit(1);
|
||||
end;
|
||||
|
||||
idofs:=obj^.rel_data^.rela_size div SizeOf(elf64_rela);
|
||||
idofs:=idofs+i;
|
||||
|
||||
if check_relo_bits(obj,idofs) then Exit;
|
||||
|
||||
entry:=obj^.rel_data^.pltrela_addr+i;
|
||||
|
||||
if (ELF64_R_TYPE(entry^.r_info)<>R_X86_64_JUMP_SLOT) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_jmpslot:','R_TYPE (',ELF64_R_TYPE(entry^.r_info),') at index ',i,' is bad. (Expected: R_X86_64_JMP_SLOT) in ',obj^.lib_path);
|
||||
Exit(3);
|
||||
end;
|
||||
|
||||
where:=(obj^.relocbase + entry^.r_offset);
|
||||
|
||||
defobj:=nil;
|
||||
def:=find_symdef(ELF64_R_SYM(entry^.r_info),obj,defobj,1,cache);
|
||||
|
||||
if (def=nil) then
|
||||
begin
|
||||
Exit(1);
|
||||
end;
|
||||
|
||||
if (flags=1) and
|
||||
(obj^.jmpslots_done=0) and
|
||||
(defobj^.jmpslots_done=0) then
|
||||
begin
|
||||
Exit(5);
|
||||
end;
|
||||
|
||||
if (ELF64_ST_VISIBILITY(def^.st_other)=STV_HIDDEN) and
|
||||
(defobj<>obj) then
|
||||
begin
|
||||
Exit(2);
|
||||
end;
|
||||
|
||||
data:=defobj^.relocbase + entry^.r_addend + def^.st_value;
|
||||
|
||||
Result:=copyout(@data,where,SizeOf(Pointer));
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'reloc_jmpslot:','copyout() failed. where=0x',HexStr(where));
|
||||
Exit(4);
|
||||
end;
|
||||
|
||||
set_relo_bits(obj,idofs);
|
||||
|
||||
if (flags=0) then Exit;
|
||||
|
||||
//dl_debug_flags
|
||||
end;
|
||||
|
||||
function reloc_jmpslots(obj:p_lib_info):Integer;
|
||||
var
|
||||
cache:array of t_SymCache;
|
||||
|
||||
i,count:Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
cache:=nil;
|
||||
SetLength(cache,obj^.rel_data^.dynsymcount);
|
||||
|
||||
count:=obj^.rel_data^.pltrela_size div SizeOf(elf64_rela);
|
||||
|
||||
if (obj^.rel_data^.pltrela_addr<>nil) and (count<>0) then
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
Result:=reloc_jmpslot(obj,i,@cache[0],0);
|
||||
case Result of
|
||||
3:Exit(EINVAL);
|
||||
4:Exit(ENOEXEC);
|
||||
5:Exit(ENOEXEC);
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function relocate_one_object(obj:p_lib_info;jmpslots:Integer):Integer;
|
||||
|
@ -359,7 +450,7 @@ begin
|
|||
Exit;
|
||||
end;
|
||||
|
||||
Result:=reloc_jmplots(obj);
|
||||
Result:=reloc_jmpslots(obj);
|
||||
if (Result<>0) then
|
||||
begin
|
||||
Writeln(StdErr,'relocate_one_object:','reloc_jmplots() failed. obj=',obj^.lib_path,' rv=',Result);
|
||||
|
|
|
@ -249,8 +249,8 @@ procedure init_relo_bits (obj:p_lib_info);
|
|||
function check_relo_bits(obj:p_lib_info;i:Integer):Boolean;
|
||||
procedure set_relo_bits(obj:p_lib_info;i:Integer);
|
||||
|
||||
procedure donelist_init(var dlp:t_DoneList); inline;
|
||||
function donelist_check(var dlp:t_DoneList;obj:p_lib_info):Boolean; inline;
|
||||
procedure donelist_init(var dlp:t_DoneList);
|
||||
function donelist_check(var dlp:t_DoneList;obj:p_lib_info):Boolean;
|
||||
|
||||
function change_relro_protection(obj:p_lib_info;prot:Integer):Integer;
|
||||
function change_relro_protection_all(prot:Integer):Integer;
|
||||
|
@ -1150,14 +1150,14 @@ begin
|
|||
begin
|
||||
dval:=dt_ent^.d_un.d_val;
|
||||
|
||||
lib_entry:=lib^.lib_table.tqh_first;
|
||||
lib_entry:=TAILQ_FIRST(@lib^.lib_table);
|
||||
while (lib_entry<>nil) do
|
||||
begin
|
||||
if (TLibraryAttr(dval).id=lib_entry^.dval.id) then
|
||||
begin
|
||||
Break;
|
||||
end;
|
||||
lib_entry:=lib_entry^.link.tqe_next;
|
||||
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
|
||||
end;
|
||||
|
||||
if (lib_entry=nil) then
|
||||
|
|
|
@ -88,9 +88,15 @@ uses
|
|||
kern_event,
|
||||
kern_callout,
|
||||
kern_timeout,
|
||||
kern_exec;
|
||||
kern_exec,
|
||||
vmparam;
|
||||
|
||||
const
|
||||
PAGE_MAP_COUNT=(qword(VM_MAXUSER_ADDRESS) shr PAGE_SHIFT);
|
||||
|
||||
var
|
||||
PAGE_MAP:array[0..PAGE_MAP_COUNT-1] of DWORD;
|
||||
|
||||
mtx:umutex;
|
||||
rwl:urwlock;
|
||||
e:Integer;
|
||||
|
@ -1240,6 +1246,11 @@ begin
|
|||
//tailq;
|
||||
id_test;
|
||||
|
||||
PAGE_MAP[200]:=3;
|
||||
writeln(PAGE_MAP[200]);
|
||||
writeln(PAGE_MAP_COUNT-1);
|
||||
writeln(sizeof(PAGE_MAP));
|
||||
|
||||
//test_map;
|
||||
sys_init;
|
||||
|
||||
|
|
Loading…
Reference in New Issue