This commit is contained in:
Pavel 2023-07-19 14:41:07 +03:00
parent 8740fedec5
commit 4a8b4a910e
4 changed files with 386 additions and 23 deletions

View File

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

View File

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

View File

@ -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

View File

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