This commit is contained in:
Pavel 2023-07-21 00:54:23 +03:00
parent f811fc4753
commit c320cb59e2
5 changed files with 565 additions and 344 deletions

View File

@ -32,7 +32,7 @@ type
sym_out :p_elf64_sym;
end;
function do_dlsym(obj:p_lib_info;symbol,modname:pchar;flags:DWORD):Pointer;
function do_dlsym(obj:p_lib_info;symbol,libname: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
@ -133,8 +133,6 @@ var
elm:p_Objlist_Entry;
def:p_elf64_sym;
defobj:p_lib_info;
lib_entry:p_Lib_Entry;
offset:QWORD;
str:pchar;
begin
Result:=0;
@ -164,7 +162,7 @@ begin
begin
if not donelist_check(dlp,elm^.obj) then
begin
if (modname=nil) then
if (modname=nil) then //any module?
begin
_symlook_obj:
req1:=req^;
@ -181,20 +179,10 @@ begin
end;
end else
begin
lib_entry:=TAILQ_FIRST(@elm^.obj^.mod_table);
while (lib_entry<>nil) do
str:=get_mod_name(elm^.obj,0); //export=0
if (StrComp(str,modname)=0) then
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,modname)=0) then
begin
goto _symlook_obj;
end;
Break;
end;
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
goto _symlook_obj;
end;
end;
end;
@ -222,7 +210,6 @@ begin
if (req^.defobj_out=nil) or
(ELF64_ST_BIND(req^.sym_out^.st_info)=STB_WEAK) then
begin
Result:=symlook_list(@req1, dynlibs_info.list_main, donelist);
if (Result=0) then
@ -235,7 +222,6 @@ begin
Assert(req^.defobj_out<>nil,'req->defobj_out is NULL #1');
end;
end;
end;
//Search all DAGs whose roots are RTLD_GLOBAL objects.
@ -318,42 +304,23 @@ begin
Exit(ESRCH);
end;
function do_dlsym(obj:p_lib_info;symbol,modname:pchar;flags:DWORD):Pointer;
function do_dlsym(obj:p_lib_info;symbol,libname: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^.mod_table) then
begin
req.modname:=nil;
end else
begin
req.modname:=nil;
lib_entry:=TAILQ_FIRST(@obj^.mod_table);
while (lib_entry<>nil) do
begin
if (lib_entry^.dval.id=0) then //export?
begin
offset:=lib_entry^.dval.name_offset;
req.modname:=obj_get_str(obj,offset);
Break;
end;
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
end;
end;
req:=Default(t_SymLook);
req.modname:=get_mod_name(obj,0); //export=0
req.flags:=flags or SYMLOOK_DLSYM;
if ((flags and SYMLOOK_BASE64)=0) then
begin
req.libname:=modname;
if (modname=nil) then
req.libname:=libname;
if (libname=nil) then
begin
req.libname:=req.modname;
end;
@ -365,11 +332,8 @@ begin
req.modname:=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);
@ -407,6 +371,7 @@ var
defobj:p_lib_info;
str:pchar;
err:Integer;
ST_BIND:Integer;
begin
Result:=nil;
@ -431,13 +396,14 @@ begin
str:=obj_get_str(refobj,ref^.st_name);
if (ELF64_ST_BIND(ref^.st_info)=STB_LOCAL) then
ST_BIND:=ELF64_ST_BIND(ref^.st_info);
if (ST_BIND=STB_LOCAL) then
begin
def :=ref;
defobj:=refobj;
end else
begin
if (ELF64_ST_TYPE(ref^.st_info)=STT_SECTION) then
if (ST_BIND=STT_SECTION) then
begin
Writeln(StdErr,'find_symdef:',refobj^.lib_path,': Bogus symbol table entry ',symnum);
end;

View File

@ -37,7 +37,7 @@ function sys_dynlib_dlsym(handle:Integer;symbol:pchar;addrp:ppointer):Integer;
label
_exit;
var
lib:p_lib_info;
obj:p_lib_info;
flags:Integer;
ptr:Pointer;
@ -56,8 +56,8 @@ begin
dynlibs_lock;
lib:=find_obj_by_handle(handle);
if (lib=nil) then
obj:=find_obj_by_handle(handle);
if (obj=nil) then
begin
Result:=ESRCH;
goto _exit;
@ -70,7 +70,7 @@ begin
flags:=SYMLOOK_BASE64;
end;
ptr:=do_dlsym(lib,@fsym,nil,flags);
ptr:=do_dlsym(obj,@fsym,nil,flags);
if (ptr=nil) then
begin
@ -119,7 +119,7 @@ var
len:ptruint;
fname:array[0..1024-1] of char;
lib:p_lib_info;
obj:p_lib_info;
key:Integer;
allocs:Boolean;
begin
@ -140,32 +140,32 @@ begin
dynlibs_lock;
lib:=nil;
Result:=load_prx(@fname,flags or ord(budget_ptype_caller=0),lib);
obj:=nil;
Result:=load_prx(@fname,flags or ord(budget_ptype_caller=0),obj);
if (Result=0) then
begin
allocs:=(lib^.id<=0);
allocs:=(obj^.id<=0);
if (lib^.ref_count < 2) then
if (obj^.ref_count < 2) then
begin
if not alloc_obj_id(lib) then
if not alloc_obj_id(obj) then
begin
//unload_prx(lib);
unload_prx(obj);
Result:=EAGAIN;
goto _exit;
end;
end;
key:=lib^.id;
key:=obj^.id;
Result:=copyout(@key,pRes,SizeOf(Integer));
if (Result<>0) then
begin
if allocs then
begin
free_obj_id(lib^.id);
lib^.id:=0;
free_obj_id(obj^.id);
obj^.id:=0;
end;
//unload_prx(lib);
unload_prx(obj);
Result:=EFAULT;
end;
end;
@ -178,7 +178,7 @@ end;
function sys_dynlib_load_prx(handle:Integer):Integer;
var
lib:p_lib_info;
obj:p_lib_info;
ref,id:Integer;
begin
if not_dynamic then
@ -189,15 +189,16 @@ begin
dynlibs_lock;
lib:=find_obj_id(handle);
if (lib=nil) then
obj:=find_obj_id(handle);
if (obj=nil) then
begin
Result:=ESRCH;
end else
begin
ref:=lib^.ref_count;
id :=lib^.id;
//Result:=unload_prx(lib);
ref:=obj^.ref_count;
id :=obj^.id;
//
Result:=unload_prx(obj);
//
if (ref=1) then
begin

View File

@ -745,7 +745,7 @@ end;
function dynlib_proc_initialize_step1(imgp:p_image_params):Integer;
var
lib:p_lib_info;
obj:p_lib_info;
text_addr:Pointer;
eh_frame_addr:Pointer;
eh_frame_size:QWORD;
@ -766,28 +766,28 @@ begin
dynlibs_info.tls_max :=1;
//dynlibs_info.bits :=0;
lib:=obj_new();
lib^.mainprog:=1;
lib^.relocbase:=imgp^.reloc_base;
obj:=obj_new();
obj^.mainprog:=1;
obj^.relocbase:=imgp^.reloc_base;
text_addr:=g_vmspace.vm_taddr;
lib^.map_base:=text_addr;
obj^.map_base:=text_addr;
lib^.text_size:=g_vmspace.vm_tsize * PAGE_SIZE;
lib^.data_addr:=g_vmspace.vm_daddr;
lib^.data_size:=g_vmspace.vm_dsize * PAGE_SIZE;
obj^.text_size:=g_vmspace.vm_tsize * PAGE_SIZE;
obj^.data_addr:=g_vmspace.vm_daddr;
obj^.data_size:=g_vmspace.vm_dsize * PAGE_SIZE;
lib^.map_size :=((QWORD(lib^.data_addr) + lib^.data_size + $3fff) and QWORD($ffffffffffffc000)) - QWORD(text_addr);
obj^.map_size :=((QWORD(obj^.data_addr) + obj^.data_size + $3fff) and QWORD($ffffffffffffc000)) - QWORD(text_addr);
lib^.relro_addr:=imgp^.relro_addr;
lib^.relro_size:=imgp^.relro_size;
obj^.relro_addr:=imgp^.relro_addr;
obj^.relro_size:=imgp^.relro_size;
lib^.tls_index :=1;
lib^.tls_size :=imgp^.tls_size;
lib^.tls_align :=imgp^.tls_align;
lib^.tls_init_size:=imgp^.tls_init_size;
lib^.tls_init_addr:=imgp^.tls_init_addr;
obj^.tls_index :=1;
obj^.tls_size :=imgp^.tls_size;
obj^.tls_align :=imgp^.tls_align;
obj^.tls_init_size:=imgp^.tls_init_size;
obj^.tls_init_addr:=imgp^.tls_init_addr;
eh_frame_addr:=nil;
eh_frame_size:=0;
@ -795,7 +795,7 @@ begin
if (elf64_get_eh_frame_info(imgp^.eh_frame_hdr_addr,
imgp^.eh_frame_hdr_size,
0,
lib^.text_size + QWORD(text_addr),
obj^.text_size + QWORD(text_addr),
@eh_frame_addr,
@eh_frame_size)<>0) then
begin
@ -803,31 +803,31 @@ begin
eh_frame_size:=0;
end;
lib^.eh_frame_hdr_addr:=imgp^.eh_frame_hdr_addr;
lib^.eh_frame_hdr_size:=imgp^.eh_frame_hdr_size;
lib^.eh_frame_addr :=eh_frame_addr;
lib^.eh_frame_size :=eh_frame_size;
obj^.eh_frame_hdr_addr:=imgp^.eh_frame_hdr_addr;
obj^.eh_frame_hdr_size:=imgp^.eh_frame_hdr_size;
obj^.eh_frame_addr :=eh_frame_addr;
obj^.eh_frame_size :=eh_frame_size;
lib^.entry_addr :=imgp^.entry_addr;
obj^.entry_addr :=imgp^.entry_addr;
_set_lib_path(lib,imgp^.execpath);
obj_set_lib_path(obj,imgp^.execpath);
//*(byte *)&lib^.rtld_flags:=*(byte *)&lib^.rtld_flags | 1;
//*(byte *)&obj^.rtld_flags:=*(byte *)&obj^.rtld_flags | 1;
lib^.loaded:=4;
obj^.loaded:=4;
dynlibs_info.libprogram:=lib;
dynlibs_info.libprogram:=obj;
if (imgp^.dyn_exist=0) then
begin
dynlibs_info.dyn_non_exist:=1;
lib^.rel_data:=nil;
obj^.rel_data:=nil;
//
end else
begin
dynlibs_info.dyn_non_exist:=0;
Result:=acquire_per_file_info_obj(imgp,lib);
Result:=acquire_per_file_info_obj(imgp,obj);
if (Result<>0) then
begin
@ -838,7 +838,7 @@ end;
function dynlib_proc_initialize_step2(imgp:p_image_params):Integer;
var
lib,tail:p_lib_info;
obj,tail:p_lib_info;
init_proc_addr:Pointer;
fini_proc_addr:Pointer;
@ -848,34 +848,34 @@ begin
dynlibs_info.proc_param_addr:=imgp^.proc_param_addr;
dynlibs_info.proc_param_size:=imgp^.proc_param_size;
lib:=dynlibs_info.libprogram;
obj:=dynlibs_info.libprogram;
if (imgp^.dyn_exist=0) then
begin
dynlibs_add_obj(lib);
dynlibs_add_obj(obj);
Exit;
end;
Result:=digest_dynamic(lib);
Result:=digest_dynamic(obj);
if (Result<>0) then
begin
Writeln(StdErr,'dynlib_proc_initialize_step2:','digest_dynamic()=',Result);
Exit;
end;
init_relo_bits(lib);
init_relo_bits(obj);
dynlibs_add_obj(lib);
dynlibs_add_obj(obj);
dynlibs_info.sym_zero.st_info :=(STB_GLOBAL shl 4) or STT_NOTYPE;
dynlibs_info.sym_zero.st_shndx:=SHN_UNDEF;
dynlibs_info.sym_zero.st_value:=-Int64(lib^.relocbase);
dynlibs_info.sym_zero.st_value:=-Int64(obj^.relocbase);
init_proc_addr:=lib^.init_proc_addr;
fini_proc_addr:=lib^.fini_proc_addr;
init_proc_addr:=obj^.init_proc_addr;
fini_proc_addr:=obj^.fini_proc_addr;
lib^.fini_proc_addr:=nil;
lib^.init_proc_addr:=nil;
obj^.fini_proc_addr:=nil;
obj^.init_proc_addr:=nil;
tail:=TAILQ_LAST(@dynlibs_info.obj_list);
if (tail=nil) then
@ -888,8 +888,8 @@ begin
tail,
dynlibs_info.init_proc_list);
lib^.init_proc_addr:=init_proc_addr;
lib^.fini_proc_addr:=fini_proc_addr;
obj^.init_proc_addr:=init_proc_addr;
obj^.fini_proc_addr:=fini_proc_addr;
///
end;
@ -914,15 +914,14 @@ procedure dynlib_proc_initialize_step3(imgp:p_image_params);
label
_dyn_not_exist;
var
lib:p_lib_info;
obj:p_lib_info;
str:RawByteString;
err:Integer;
key:Integer;
flags:DWORD;
begin
err:=0;
lib:=nil;
obj:=nil;
//if (td_proc->sdk_version < 0x5000000) {
// *(byte *)&dynlibs_info->bits = *(byte *)&dynlibs_info->bits | 0x20;
@ -934,35 +933,34 @@ begin
if (budget_ptype_caller=0) then flags:=flags or $20; //vm_map_wire
str:='libkernel.sprx';
lib:=preload_prx_modules(pchar(str),flags,err);
dynlibs_info.libkernel:=lib;
obj:=preload_prx_modules(pchar(str),flags,err);
dynlibs_info.libkernel:=obj;
if (lib=nil) then
if (obj=nil) then
begin
Writeln(StdErr,'preload_prx_modules:',str,' not loaded');
end;
str:='libSceLibcInternal.sprx';
lib:=preload_prx_modules(pchar(str),flags,err);
obj:=preload_prx_modules(pchar(str),flags,err);
if (lib=nil) then
if (obj=nil) then
begin
Writeln(StdErr,'preload_prx_modules:',str,' not loaded');
end;
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (lib<>nil) do
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
objlist_push_tail(dynlibs_info.list_main,lib);
objlist_push_tail(dynlibs_info.list_main,obj);
Inc(lib^.ref_count);
Inc(obj^.ref_count);
objlist_push_tail(lib^.dagmembers,lib);
objlist_push_tail(lib^.dldags ,lib);
objlist_push_tail(obj^.dagmembers,obj);
objlist_push_tail(obj^.dldags ,obj);
//
lib:=TAILQ_NEXT(lib,@lib^.link);
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
dynlibs_info.rep_unpf:=do_dlsym(dynlibs_info.libkernel,'sceKernelReportUnpatchedFunctionCall',nil,0);
@ -970,34 +968,31 @@ begin
dynlibs_info.sysc_s00:=do_dlsym(dynlibs_info.libkernel,'sysc_s00','libkernel_sysc_se', 0);
dynlibs_info.sysc_e00:=do_dlsym(dynlibs_info.libkernel,'sysc_e00','libkernel_sysc_se', 0);
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (lib<>nil) do
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
dynlib_initialize_pltgot_each(lib);
dynlib_initialize_pltgot_each(obj);
//
lib:=TAILQ_NEXT(lib,@lib^.link);
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
imgp^.entry_addr:=dynlibs_info.libkernel^.entry_addr;
_dyn_not_exist:
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (lib<>nil) do
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
if not alloc_obj_id(lib) then
if not alloc_obj_id(obj) then
begin
Assert(False,'ID for PRX cannot be assigned.');
end;
//
lib:=TAILQ_NEXT(lib,@lib^.link);
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
end;
function exec_self_imgact(imgp:p_image_params):Integer;
var
hdr :p_elf64_hdr;

View File

@ -13,6 +13,7 @@ uses
function relocate_one_object(obj:p_lib_info;jmpslots:Integer):Integer;
function check_copy_relocations(obj:p_lib_info):Integer;
function dynlib_unlink_imported_symbols_each(root,obj:p_lib_info):Integer;
implementation
@ -97,7 +98,7 @@ begin
R_X86_64_COPY:
if (obj^.mainprog=0) then
begin
Writeln(StdErr,'reloc_non_plt:','Unexpected R_X86_64_COPY relocation in shared library');
Writeln(StdErr,'reloc_non_plt:','Unexpected R_X86_64_COPY relocation in shared library ',dynlib_basename(obj^.lib_path));
Exit(ENOEXEC);
end; //R_X86_64_COPY
@ -369,7 +370,7 @@ begin
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);
Writeln(StdErr,'reloc_jmpslot:','R_TYPE (',ELF64_R_TYPE(entry^.r_info),') at index ',i,' is bad. (Expected: R_X86_64_JMP_SLOT) in ',dynlib_basename(obj^.lib_path));
Exit(3);
end;
@ -445,7 +446,7 @@ begin
Result:=reloc_non_plt(obj);
if (Result<>0) then
begin
Writeln(StdErr,'relocate_one_object:','reloc_non_plt() failed. obj=',obj^.lib_path,' rv=',Result);
Writeln(StdErr,'relocate_one_object:','reloc_non_plt() failed. obj=',dynlib_basename(obj^.lib_path),' rv=',Result);
Exit;
end;
@ -454,7 +455,7 @@ begin
Result:=reloc_jmpslots(obj);
if (Result<>0) then
begin
Writeln(StdErr,'relocate_one_object:','reloc_jmplots() failed. obj=',obj^.lib_path,' rv=',Result);
Writeln(StdErr,'relocate_one_object:','reloc_jmplots() failed. obj=',dynlib_basename(obj^.lib_path),' rv=',Result);
Exit;
end;
end;
@ -477,13 +478,208 @@ begin
begin
if (ELF64_R_TYPE(rela^.r_info)=R_X86_64_COPY) then
begin
Writeln(StdErr,'check_copy_relocations:','R_X86_64_COPY found in ',obj^.lib_path);
Writeln(StdErr,'check_copy_relocations:','R_X86_64_COPY found in ',dynlib_basename(obj^.lib_path));
Exit(EINVAL);
end;
Inc(rela);
end;
end;
function dynlib_unlink_non_plt_reloc_each(root,obj:p_lib_info):Integer;
var
rela:p_elf64_rela;
where:Pointer;
data:Pointer;
data32:Integer;
r_type:Integer;
i,count:Integer;
begin
Result:=0;
Assert(root<>nil,'Bad dynamic library is specified.');
rela :=obj^.rel_data^.rela_addr;
count:=obj^.rel_data^.rela_size div SizeOf(elf64_rela);
if (rela<>nil) and (count<>0) then
For i:=0 to count-1 do
if check_relo_bits(obj,i) then
begin
where:=Pointer(obj^.relocbase)+rela^.r_offset;
r_type:=ELF64_R_TYPE(rela^.r_info);
case r_type of
R_X86_64_NONE:; //ignore
R_X86_64_COPY:
if (obj^.mainprog=0) then
begin
Writeln(StdErr,'dynlib_unlink_non_plt_reloc_each:','Unexpected R_X86_64_COPY relocation in dynamic library ',dynlib_basename(obj^.lib_path));
Exit(-1);
end; //R_X86_64_COPY
R_X86_64_64,
R_X86_64_GLOB_DAT,
R_X86_64_RELATIVE,
R_X86_64_TPOFF64:
begin
data:=Pointer(QWORD($840000000));
Result:=relocate_text_or_data_segment(obj,@data,where,SizeOf(Pointer));
if (Result<>0) then
begin
Writeln(StdErr,'dynlib_unlink_non_plt_reloc_each:','copyout() failed. where=0x',HexStr(where),' ref=',dynlib_basename(obj^.lib_path));
Exit(-1);
end;
reset_relo_bits(obj,i);
end; //64
R_X86_64_PC32,
R_X86_64_TPOFF32:
begin
data32:=Integer($40000000);
Result:=relocate_text_or_data_segment(obj,@data32,where,SizeOf(Integer));
if (Result<>0) then
begin
Writeln(StdErr,'dynlib_unlink_non_plt_reloc_each:','copyout() failed. where32=0x',HexStr(where),' ref=',dynlib_basename(obj^.lib_path));
Exit(-1);
end;
reset_relo_bits(obj,i);
end; //32
R_X86_64_DTPMOD64,
R_X86_64_DTPOFF64:
begin
data:=nil;
Result:=copyout(@data,where,SizeOf(Pointer));
if (Result<>0) then
begin
Writeln(StdErr,'dynlib_unlink_non_plt_reloc_each:','copyout() failed. where=0x',HexStr(where),' ref=',dynlib_basename(obj^.lib_path));
Exit(-1);
end;
reset_relo_bits(obj,i);
end; //64
R_X86_64_DTPOFF32:
begin
data32:=0;
Result:=copyout(@data32,where,SizeOf(Integer));
if (Result<>0) then
begin
Writeln(StdErr,'dynlib_unlink_non_plt_reloc_each:','copyout() failed. where32=0x',HexStr(where),' ref=',dynlib_basename(obj^.lib_path));
Exit(-1);
end;
reset_relo_bits(obj,i);
end; //32
else
begin
Writeln(StdErr,'dynlib_unlink_non_plt_reloc_each:','Unsupported reloc type=',r_type);
Exit(-1);
end;
end;
end; //case
end;
function dynlib_unlink_plt_reloc_each(root,obj:p_lib_info):Integer;
var
i,count,idofs:Integer;
entry:p_elf64_rela;
def:p_elf64_sym;
defobj:p_lib_info;
where:Pointer;
data:QWORD;
str:pchar;
begin
Result:=0;
count:=obj^.rel_data^.pltrela_size div SizeOf(elf64_rela);
idofs:=obj^.rel_data^.rela_size div SizeOf(elf64_rela);
if (obj^.rel_data^.pltrela_addr<>nil) and (count<>0) then
For i:=0 to count-1 do
if check_relo_bits(obj,idofs+i) then
begin
entry:=obj^.rel_data^.pltrela_addr+i;
if (ELF64_R_TYPE(entry^.r_info)<>R_X86_64_JUMP_SLOT) then
begin
Writeln(StdErr,'dynlib_unlink_plt_reloc_each:','R_TYPE (',ELF64_R_TYPE(entry^.r_info),') at index ',i,' is bad. (Expected: R_X86_64_JMP_SLOT) in ',dynlib_basename(obj^.lib_path));
Exit(-1);
end;
defobj:=nil;
def:=find_symdef(ELF64_R_SYM(entry^.r_info),obj,defobj,1,nil);
if (def=nil) then
begin
if (ELF64_R_SYM(entry^.r_info)<=(obj^.rel_data^.symtab_size div SizeOf(elf64_sym))) then
begin
def:=nil;
str:='';
end else
begin
def:=obj^.rel_data^.symtab_addr + ELF64_R_SYM(entry^.r_info);
str:=obj_get_str(obj,def^.st_name);
end;
Writeln(StdErr,'dynlib_unlink_plt_reloc_each:','failed to lookup symbol symp=0x',HexStr(def),' name=',str);
Exit(-1);
end else
if (defobj=root) then
begin
where:=Pointer(obj^.relocbase) + entry^.r_offset;
data:=i or QWORD($effffffe00000000);
Result:=copyout(@data,where,SizeOf(Pointer));
if (Result<>0) then
begin
Writeln(StdErr,'dynlib_unlink_plt_reloc_each:','copyout() failed. where=0x',HexStr(where),' ref=',dynlib_basename(obj^.lib_path));
Exit(-1);
end;
reset_relo_bits(obj,idofs+i);
end;
end;
end;
function dynlib_unlink_imported_symbols_each(root,obj:p_lib_info):Integer;
begin
Result:=dynlib_unlink_non_plt_reloc_each(root,obj);
if (Result<>0) then
begin
Writeln(StdErr,'dynlib_unlink_imported_symbols_each:','dynlib_unlink_non_plt_reloc_each() fails ',Result);
Exit;
end;
Result:=dynlib_unlink_plt_reloc_each(root,obj);
if (Result<>0) then
begin
Writeln(StdErr,'dynlib_unlink_imported_symbols_each:','dynlib_unlink_plt_reloc_each() fails ',Result);
Exit;
end;
end;
end.

View File

@ -216,22 +216,26 @@ procedure dynlibs_lock;
procedure dynlibs_unlock;
function obj_new():p_lib_info;
procedure obj_free(lib:p_lib_info);
procedure obj_free(obj:p_lib_info);
procedure objlist_push_tail(var list:TAILQ_HEAD;obj:p_lib_info);
function objlist_find(var list:TAILQ_HEAD;obj:p_lib_info):p_Objlist_Entry;
procedure objlist_remove(var list:TAILQ_HEAD;obj: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 obj_get_str (obj: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;
procedure obj_set_lib_path (obj:p_lib_info;path:PAnsiChar);
function Needed_new(lib:p_lib_info;str:pchar):p_Needed_Entry;
function Lib_new(d_val:QWORD;import:Word):p_Lib_Entry;
function Needed_new(obj:p_lib_info;str:pchar):p_Needed_Entry;
procedure _set_lib_path(lib:p_lib_info;path:PAnsiChar);
function Lib_Entry_new(d_val:QWORD;import:Word):p_Lib_Entry;
procedure Lib_Entry_free(lib:p_Lib_Entry);
procedure release_per_file_info_obj(lib:p_lib_info);
function get_mod_name(obj:p_lib_info;id:Word):pchar;
function get_lib_name(obj:p_lib_info;id:Word):pchar;
procedure release_per_file_info_obj(obj:p_lib_info);
function acquire_per_file_info_obj(imgp:p_image_params;new:p_lib_info):Integer;
function allocate_tls_offset(obj:p_lib_info):Boolean;
@ -246,13 +250,14 @@ procedure initlist_add_neededs(var fini_proc_list:TAILQ_HEAD;
needed:p_Needed_Entry;
var init_proc_list:TAILQ_HEAD);
function digest_dynamic(lib:p_lib_info):Integer;
function digest_dynamic(obj:p_lib_info):Integer;
procedure dynlibs_add_obj(lib:p_lib_info);
procedure dynlibs_add_obj(obj:p_lib_info);
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 set_relo_bits (obj:p_lib_info;i:Integer);
procedure reset_relo_bits(obj:p_lib_info;i:Integer);
procedure donelist_init(var dlp:t_DoneList);
function donelist_check(var dlp:t_DoneList;obj:p_lib_info):Boolean;
@ -271,13 +276,14 @@ function dynlib_initialize_pltgot_each(obj:p_lib_info):Integer;
function do_load_object(path:pchar;flags:DWORD;var err:Integer):p_lib_info;
procedure unload_object(root:p_lib_info);
function relocate_object(lib:p_lib_info):Integer;
function relocate_object(root:p_lib_info):Integer;
function dynlib_load_relocate():Integer;
function preload_prx_modules(path:pchar;flags:DWORD;var err:Integer):p_lib_info;
function load_prx(path:pchar;flags:DWORD;var plib:p_lib_info):Integer;
function load_prx(path:pchar;flags:DWORD;var pobj:p_lib_info):Integer;
function unload_prx(obj:p_lib_info):Integer;
function alloc_obj_id(lib:p_lib_info):Boolean;
function alloc_obj_id(obj:p_lib_info):Boolean;
function free_obj_id (id:Integer):Boolean;
function find_obj_id (id:Integer):p_lib_info;
@ -338,15 +344,6 @@ begin
//*puVar1:=*puVar1 | 2;
end;
procedure _set_lib_path(lib:p_lib_info;path:PAnsiChar);
var
size:int64;
begin
size:=strlen(path);
lib^.lib_path:=AllocMem(size+1);
Move(path^,lib^.lib_path^,size);
end;
function preprocess_dt_entries(new:p_lib_info;hdr_e_type:Integer):Integer;
label
_unsupp;
@ -629,12 +626,12 @@ begin
end;
procedure release_per_file_info_obj(lib:p_lib_info);
procedure release_per_file_info_obj(obj:p_lib_info);
begin
if (lib^.rel_data<>nil) then
if (obj^.rel_data<>nil) then
begin
FreeMem(lib^.rel_data);
lib^.rel_data:=nil;
FreeMem(obj^.rel_data);
obj^.rel_data:=nil;
end;
end;
@ -764,85 +761,84 @@ begin
end;
end;
procedure obj_free(lib:p_lib_info);
procedure obj_free(obj:p_lib_info);
var
needed:p_Needed_Entry;
names:p_Name_Entry;
dag:p_Objlist_Entry;
libs:p_Lib_Entry;
Lib_Entry:p_Lib_Entry;
begin
free_tls_offset(obj);
free_tls_offset(lib);
needed:=TAILQ_FIRST(@lib^.needed);
needed:=TAILQ_FIRST(@obj^.needed);
while (needed<>nil) do
begin
TAILQ_REMOVE(@lib^.needed,needed,@needed^.link);
TAILQ_REMOVE(@obj^.needed,needed,@needed^.link);
FreeMem(needed);
needed:=TAILQ_FIRST(@lib^.needed);
needed:=TAILQ_FIRST(@obj^.needed);
end;
names:=TAILQ_FIRST(@lib^.names);
names:=TAILQ_FIRST(@obj^.names);
while (names<>nil) do
begin
TAILQ_REMOVE(@lib^.names,names,@names^.link);
TAILQ_REMOVE(@obj^.names,names,@names^.link);
FreeMem(names);
names:=TAILQ_FIRST(@lib^.names);
names:=TAILQ_FIRST(@obj^.names);
end;
dag:=TAILQ_FIRST(@lib^.dldags);
dag:=TAILQ_FIRST(@obj^.dldags);
while (dag<>nil) do
begin
TAILQ_REMOVE(@lib^.dldags,dag,@dag^.link);
TAILQ_REMOVE(@obj^.dldags,dag,@dag^.link);
FreeMem(dag);
dag:=TAILQ_FIRST(@lib^.dldags);
dag:=TAILQ_FIRST(@obj^.dldags);
end;
dag:=TAILQ_FIRST(@lib^.dagmembers);
dag:=TAILQ_FIRST(@obj^.dagmembers);
while (dag<>nil) do
begin
TAILQ_REMOVE(@lib^.dagmembers,dag,@dag^.link);
TAILQ_REMOVE(@obj^.dagmembers,dag,@dag^.link);
FreeMem(dag);
dag:=TAILQ_FIRST(@lib^.dagmembers);
dag:=TAILQ_FIRST(@obj^.dagmembers);
end;
if (lib^.lib_dirname<>nil) then
if (obj^.lib_dirname<>nil) then
begin
FreeMem(lib^.lib_dirname);
lib^.lib_dirname:=nil;
FreeMem(obj^.lib_dirname);
obj^.lib_dirname:=nil;
end;
if (lib^.lib_path<>nil) then
if (obj^.lib_path<>nil) then
begin
FreeMem(lib^.lib_path);
lib^.lib_path:=nil;
FreeMem(obj^.lib_path);
obj^.lib_path:=nil;
end;
if (lib^.relo_bits<>nil) then
if (obj^.relo_bits<>nil) then
begin
FreeMem(lib^.relo_bits);
lib^.relo_bits:=nil
FreeMem(obj^.relo_bits);
obj^.relo_bits:=nil
end;
libs:=TAILQ_FIRST(@lib^.lib_table);
while (libs<>nil) do
Lib_Entry:=TAILQ_FIRST(@obj^.lib_table);
while (Lib_Entry<>nil) do
begin
TAILQ_REMOVE(@lib^.lib_table,libs,@libs^.link);
FreeMem(libs);
libs:=TAILQ_FIRST(@lib^.lib_table);
TAILQ_REMOVE(@obj^.lib_table,Lib_Entry,@Lib_Entry^.link);
Lib_Entry_free(Lib_Entry);
Lib_Entry:=TAILQ_FIRST(@obj^.lib_table);
end;
libs:=TAILQ_FIRST(@lib^.mod_table);
while (libs<>nil) do
Lib_Entry:=TAILQ_FIRST(@obj^.mod_table);
while (Lib_Entry<>nil) do
begin
TAILQ_REMOVE(@lib^.mod_table,libs,@libs^.link);
FreeMem(libs);
libs:=TAILQ_FIRST(@lib^.mod_table);
TAILQ_REMOVE(@obj^.mod_table,Lib_Entry,@Lib_Entry^.link);
Lib_Entry_free(Lib_Entry);
Lib_Entry:=TAILQ_FIRST(@obj^.mod_table);
end;
release_per_file_info_obj(lib);
release_per_file_info_obj(obj);
FreeMem(lib);
FreeMem(obj);
end;
procedure objlist_push_tail(var list:TAILQ_HEAD;obj:p_lib_info);
@ -881,15 +877,15 @@ begin
end;
end;
function obj_get_str(lib:p_lib_info;offset:Int64):pchar;
function obj_get_str(obj:p_lib_info;offset:Int64):pchar;
begin
if (lib^.rel_data^.strtab_size<=offset) then
if (obj^.rel_data^.strtab_size<=offset) then
begin
Writeln(StdErr,'obj_get_str:','offset=0x',HexStr(offset,8),' is out of range of string table of ',lib^.lib_path);
Writeln(StdErr,'obj_get_str:','offset=0x',HexStr(offset,8),' is out of range of string table of ',obj^.lib_path);
Exit(nil);
end;
Result:=lib^.rel_data^.strtab_addr+offset;
Result:=obj^.rel_data^.strtab_addr+offset;
end;
procedure object_add_name(obj:p_lib_info;name:pchar);
@ -920,23 +916,76 @@ begin
Result:=False;
end;
function Needed_new(lib:p_lib_info;str:pchar):p_Needed_Entry;
procedure obj_set_lib_path(obj:p_lib_info;path:PAnsiChar);
var
size:int64;
begin
size:=strlen(path);
obj^.lib_path:=AllocMem(size+1);
Move(path^,obj^.lib_path^,size);
end;
function Needed_new(obj:p_lib_info;str:pchar):p_Needed_Entry;
var
len:Integer;
begin
len:=strlen(str);
Result:=AllocMem(SizeOf(Needed_Entry)+len);
Result^.obj :=lib;
Result^.obj :=obj;
Move(str^,Result^.name,len);
end;
function Lib_new(d_val:QWORD;import:Word):p_Lib_Entry;
function Lib_Entry_new(d_val:QWORD;import:Word):p_Lib_Entry;
begin
Result:=AllocMem(SizeOf(Lib_Entry));
QWORD(Result^.dval):=d_val;
Result^.import:=import;
end;
procedure Lib_Entry_free(lib:p_Lib_Entry);
begin
//
FreeMem(lib);
end;
function get_mod_name(obj:p_lib_info;id:Word):pchar;
var
lib_entry:p_Lib_Entry;
offset:QWORD;
begin
Result:=nil;
lib_entry:=TAILQ_FIRST(@obj^.mod_table);
while (lib_entry<>nil) do
begin
if (lib_entry^.dval.id=id) then
begin
offset:=lib_entry^.dval.name_offset;
Result:=obj_get_str(obj,offset);
Exit;
end;
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
end;
end;
function get_lib_name(obj:p_lib_info;id:Word):pchar;
var
lib_entry:p_Lib_Entry;
offset:QWORD;
begin
Result:=nil;
lib_entry:=TAILQ_FIRST(@obj^.lib_table);
while (lib_entry<>nil) do
begin
if (lib_entry^.dval.id=id) then
begin
offset:=lib_entry^.dval.name_offset;
Result:=obj_get_str(obj,offset);
Exit;
end;
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
end;
end;
procedure initlist_add_objects(var fini_proc_list:TAILQ_HEAD;
obj :p_lib_info;
tail:p_lib_info;
@ -986,8 +1035,7 @@ begin
end;
end;
function digest_dynamic(lib:p_lib_info):Integer;
function digest_dynamic(obj:p_lib_info):Integer;
var
dt_ent:p_elf64_dyn;
i,count:Integer;
@ -1008,10 +1056,10 @@ begin
dyn_soname:=nil;
dt_fingerprint:=-1;
if (lib^.rel_data<>nil) then
if (obj^.rel_data<>nil) then
begin
dt_ent:=lib^.rel_data^.dynamic_addr;
count :=lib^.rel_data^.dynamic_size div sizeof(elf64_dyn);
dt_ent:=obj^.rel_data^.dynamic_addr;
count :=obj^.rel_data^.dynamic_size div sizeof(elf64_dyn);
if (count<>0) then
For i:=0 to count-1 do
@ -1065,7 +1113,7 @@ begin
DT_NEEDED:
begin
str:=obj_get_str(lib,dt_ent^.d_un.d_val);
str:=obj_get_str(obj,dt_ent^.d_un.d_val);
if (str=nil) then
begin
@ -1073,16 +1121,16 @@ begin
Exit(EINVAL);
end;
needed:=Needed_new(lib,str);
TAILQ_INSERT_TAIL(@lib^.needed,needed,@Needed^.link);
needed:=Needed_new(obj,str);
TAILQ_INSERT_TAIL(@obj^.needed,needed,@Needed^.link);
end;
DT_INIT:
begin
addr:=lib^.relocbase+dt_ent^.d_un.d_val;
lib^.init_proc_addr:=addr;
addr:=obj^.relocbase+dt_ent^.d_un.d_val;
obj^.init_proc_addr:=addr;
if (lib^.map_base>addr) or ((addr+8)>(lib^.map_base+lib^.text_size)) then
if (obj^.map_base>addr) or ((addr+8)>(obj^.map_base+obj^.text_size)) then
begin
Writeln(StdErr,'digest_dynamic:',{$INCLUDE %LINE%});
Exit(ENOEXEC);
@ -1091,10 +1139,10 @@ begin
DT_FINI:
begin
addr:=lib^.relocbase+dt_ent^.d_un.d_val;
lib^.fini_proc_addr:=addr;
addr:=obj^.relocbase+dt_ent^.d_un.d_val;
obj^.fini_proc_addr:=addr;
if (lib^.map_base>addr) or ((addr+8)>(lib^.map_base+lib^.text_size)) then
if (obj^.map_base>addr) or ((addr+8)>(obj^.map_base+obj^.text_size)) then
begin
Writeln(StdErr,'digest_dynamic:',{$INCLUDE %LINE%});
Exit(ENOEXEC);
@ -1109,7 +1157,7 @@ begin
DT_TEXTREL:
begin
lib^.textrel:=1;
obj^.textrel:=1;
end;
DT_FLAGS:
@ -1130,7 +1178,7 @@ begin
if ((dval and DF_TEXTREL)<>0) then
begin
lib^.textrel:=1;
obj^.textrel:=1;
end;
end;
@ -1138,8 +1186,8 @@ begin
begin
dt_fingerprint:=dt_ent^.d_un.d_val;
if (lib^.rel_data=nil) or
((dt_fingerprint + 20)>lib^.rel_data^.sce_dynlib_size) then
if (obj^.rel_data=nil) or
((dt_fingerprint + 20)>obj^.rel_data^.sce_dynlib_size) then
begin
Writeln(StdErr,'digest_dynamic:',{$INCLUDE %LINE%});
Exit(ENOEXEC);
@ -1148,7 +1196,7 @@ begin
DT_SCE_ORIGINAL_FILENAME:
begin
str:=obj_get_str(lib,dt_ent^.d_un.d_val);
str:=obj_get_str(obj,dt_ent^.d_un.d_val);
if (str=nil) then
begin
@ -1156,21 +1204,21 @@ begin
Exit(EINVAL);
end;
lib^.rel_data^.original_filename:=str;
obj^.rel_data^.original_filename:=str;
end;
DT_SCE_MODULE_INFO,
DT_SCE_NEEDED_MODULE:
begin
lib_entry:=Lib_new(dt_ent^.d_un.d_val,ord(dt_ent^.d_tag=DT_SCE_NEEDED_MODULE));
TAILQ_INSERT_TAIL(@lib^.mod_table,lib_entry,@lib_entry^.link);
lib_entry:=Lib_Entry_new(dt_ent^.d_un.d_val,ord(dt_ent^.d_tag=DT_SCE_NEEDED_MODULE));
TAILQ_INSERT_TAIL(@obj^.mod_table,lib_entry,@lib_entry^.link);
end;
DT_SCE_MODULE_ATTR:
begin
dval:=dt_ent^.d_un.d_val;
lib_entry:=TAILQ_FIRST(@lib^.mod_table);
lib_entry:=TAILQ_FIRST(@obj^.mod_table);
while (lib_entry<>nil) do
begin
if (TLibraryAttr(dval).id=lib_entry^.dval.id) then
@ -1192,8 +1240,8 @@ begin
DT_SCE_EXPORT_LIB,
DT_SCE_IMPORT_LIB:
begin
lib_entry:=Lib_new(dt_ent^.d_un.d_val,ord(dt_ent^.d_tag=DT_SCE_IMPORT_LIB));
TAILQ_INSERT_TAIL(@lib^.lib_table,lib_entry,@lib_entry^.link);
lib_entry:=Lib_Entry_new(dt_ent^.d_un.d_val,ord(dt_ent^.d_tag=DT_SCE_IMPORT_LIB));
TAILQ_INSERT_TAIL(@obj^.lib_table,lib_entry,@lib_entry^.link);
end;
DT_SCE_EXPORT_LIB_ATTR,
@ -1201,7 +1249,7 @@ begin
begin
dval:=dt_ent^.d_un.d_val;
lib_entry:=TAILQ_FIRST(@lib^.lib_table);
lib_entry:=TAILQ_FIRST(@obj^.lib_table);
while (lib_entry<>nil) do
begin
if (TLibraryAttr(dval).id=lib_entry^.dval.id) then
@ -1251,7 +1299,7 @@ begin
else
begin
Writeln(StdErr,'digest_dynamic:','Unsupported DT tag 0x',HexStr(dt_ent^.d_tag,8),' found in ',lib^.lib_path);
Writeln(StdErr,'digest_dynamic:','Unsupported DT tag 0x',HexStr(dt_ent^.d_tag,8),' found in ',obj^.lib_path);
Exit(ENOEXEC);
end;
@ -1262,27 +1310,27 @@ begin
end;
addr:=lib^.rel_data^.sce_dynlib_addr;
addr:=obj^.rel_data^.sce_dynlib_addr;
if (dt_fingerprint=-1) then
begin
if (addr<>nil) then
begin
Move(addr^,lib^.fingerprint,20);
Move(addr^,obj^.fingerprint,20);
end;
end else
begin
if (addr<>nil) then
begin
Move((addr+dt_fingerprint)^,lib^.fingerprint,20);
Move((addr+dt_fingerprint)^,obj^.fingerprint,20);
end;
end;
if (lib^.lib_path<>nil) then
if (obj^.lib_path<>nil) then
begin
lib^.lib_dirname:=AllocMem(strlen(lib^.lib_path)+1);
obj^.lib_dirname:=AllocMem(strlen(obj^.lib_path)+1);
//
Result:=rtld_dirname(lib^.lib_path,lib^.lib_dirname);
Result:=rtld_dirname(obj^.lib_path,obj^.lib_dirname);
if (Result<>0) then
begin
Exit(EINVAL);
@ -1291,7 +1339,7 @@ begin
if (dyn_soname<>nil) then
begin
str:=obj_get_str(lib,dyn_soname^.d_un.d_val);
str:=obj_get_str(obj,dyn_soname^.d_un.d_val);
if (str=nil) then
begin
@ -1299,14 +1347,14 @@ begin
Exit(EINVAL);
end;
object_add_name(lib,str);
object_add_name(obj,str);
end;
end;
procedure dynlibs_add_obj(lib:p_lib_info);
procedure dynlibs_add_obj(obj:p_lib_info);
begin
TAILQ_INSERT_TAIL(@dynlibs_info.obj_list,lib,@lib^.link);
TAILQ_INSERT_TAIL(@dynlibs_info.obj_list,obj,@obj^.link);
Inc(dynlibs_info.obj_count);
end;
@ -1346,6 +1394,13 @@ begin
obj^.relo_bits[i shr 3]:=obj^.relo_bits[i shr 3] or (1 shl (i and 7))
end;
procedure reset_relo_bits(obj:p_lib_info;i:Integer);
begin
if (obj^.relo_bits=nil) then Exit;
obj^.relo_bits[i shr 3]:=obj^.relo_bits[i shr 3] and (not (1 shl (i and 7)))
end;
function dynlib_load_sections(imgp:p_image_params;new:p_lib_info;phdr:p_elf64_phdr;count:Integer;delta:QWORD):Integer;
var
i:Integer;
@ -1751,16 +1806,16 @@ end;
function change_relro_protection_all(prot:Integer):Integer;
var
lib:p_lib_info;
obj:p_lib_info;
begin
Result:=0;
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (lib<>nil) do
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
Result:=change_relro_protection(lib,prot);
Result:=change_relro_protection(obj,prot);
if (Result<>0) then Exit;
//
lib:=TAILQ_NEXT(lib,@lib^.link);
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
end;
@ -1967,7 +2022,7 @@ label
var
fname:RawByteString;
new:p_lib_info;
lib:p_lib_info;
obj:p_lib_info;
i:Integer;
tls_max:Integer;
begin
@ -1984,7 +2039,7 @@ begin
fname:=ExtractFileName(path);
object_add_name(new,pchar(fname));
_set_lib_path(new,path);
obj_set_lib_path(new,path);
if (new^.tls_size=0) then
begin
@ -2002,19 +2057,19 @@ begin
end else
begin
i:=1;
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (lib<>nil) do
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
while (lib^.tls_index=i) do
while (obj^.tls_index=i) do
begin
i:=i+1;
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
if (tls_max < i) then
begin
goto _inc_max;
end;
end;
lib:=TAILQ_NEXT(lib,@lib^.link);
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
end;
end;
@ -2042,7 +2097,7 @@ begin
goto _error;
end;
init_relo_bits(lib);
init_relo_bits(obj);
dynlibs_add_obj(new);
new^.loaded:=1;
Exit(new);
@ -2119,7 +2174,7 @@ function preload_prx_modules(path:pchar;flags:DWORD;var err:Integer):p_lib_info;
label
_do_load;
var
lib:p_lib_info;
obj:p_lib_info;
fname:RawByteString;
begin
Result:=nil;
@ -2127,14 +2182,14 @@ begin
fname:=ExtractFileName(path);
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (lib<>nil) do
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
if object_match_name(lib,pchar(fname)) then
if object_match_name(obj,pchar(fname)) then
begin
Exit(lib);
Exit(obj);
end;
lib:=TAILQ_NEXT(lib,@lib^.link);
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
fname:=path;
@ -2172,14 +2227,14 @@ begin
Result:=do_load_object(pchar(fname),flags,err);
end;
function relocate_object(lib:p_lib_info):Integer;
function relocate_object(root:p_lib_info):Integer;
var
obj:p_lib_info;
begin
Result:=change_relro_protection_all(VM_PROT_RW);
if (Result<>0) then Exit;
Result:=relocate_one_object(lib,ord(lib^.jmpslots_done=0));
Result:=relocate_one_object(root,ord(root^.jmpslots_done=0));
if (Result=0) then
begin
@ -2187,9 +2242,9 @@ begin
while (obj<>nil) do
begin
if (obj<>lib) then
if (obj<>root) then
begin
Result:=relocate_one_object(obj,ord(lib^.jmpslots_done=0));
Result:=relocate_one_object(obj,ord(root^.jmpslots_done=0));
end;
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
@ -2213,95 +2268,110 @@ begin
Result:=relocate_object(dynlibs_info.libprogram);
end;
function load_prx(path:pchar;flags:DWORD;var plib:p_lib_info):Integer;
function load_prx(path:pchar;flags:DWORD;var pobj:p_lib_info):Integer;
var
lib:p_lib_info;
obj:p_lib_info;
err,pflags:Integer;
begin
Result:=0;
err:=0;
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (lib<>nil) do
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
if (StrLComp(lib^.lib_path,path,$400)=0) then
if (StrLComp(obj^.lib_path,path,$400)=0) then
begin
Exit(0);
end;
//
lib:=TAILQ_NEXT(lib,@lib^.link);
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
pflags:=2;
if ((flags and $00001)<>0) then pflags:=pflags or $20; //vm_map_wire
if ((flags and $10000)<>0) then pflags:=pflags or $40; //priv libs?
lib:=preload_prx_modules(path,pflags,err);
if (lib=nil) then Exit(err);
obj:=preload_prx_modules(path,pflags,err);
if (obj=nil) then Exit(err);
if (objlist_find(dynlibs_info.list_global,lib)=nil) then
if (objlist_find(dynlibs_info.list_global,obj)=nil) then
begin
objlist_push_tail(dynlibs_info.list_global,lib);
objlist_push_tail(dynlibs_info.list_global,obj);
end;
if (lib^.ref_count=0) then
if (obj^.ref_count=0) then
begin
if ((flags and $20000)<>0) then //reset jmpslots_done?
begin
lib^.jmpslots_done:=0;
obj^.jmpslots_done:=0;
end;
if ((flags and $40000)<>0) then //reset on_fini_list?
begin
lib^.on_fini_list:=0;
obj^.on_fini_list:=0;
end;
init_dag(lib);
ref_dag(lib);
init_dag(obj);
ref_dag(obj);
err:=relocate_object(lib);
err:=relocate_object(obj);
if (err<>0) then
begin
unref_dag(lib);
if (lib^.ref_count=0) then
unref_dag(obj);
if (obj^.ref_count=0) then
begin
unload_object(lib);
unload_object(obj);
end;
Writeln(StdErr,'load_prx:','Fail to relocate ',path);
Exit(err);
end;
end else
begin
ref_dag(lib);
ref_dag(obj);
end;
plib:=lib;
pobj:=obj;
Result:=0;
end;
function dynlib_unlink_imported_symbols_each(root,obj:p_lib_info):Integer;
begin
////////
end;
function dynlib_unlink_imported_symbols(root:p_lib_info;libname:pchar):Integer;
function dynlib_unlink_imported_symbols(root:p_lib_info;modname:pchar):Integer;
var
obj:p_lib_info;
lib_entry:p_Lib_Entry;
offset:QWORD;
str:pchar;
begin
Result:=change_relro_protection_all(VM_PROT_RW);
if (Result<>0) then Exit;
if (Result=0) then
begin
obj:=dynlibs_info.libprogram;
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
//dynlib_unlink_imported_symbols_each(root,obj:p_lib_info):Integer;
if (obj<>root) then
begin
lib_entry:=TAILQ_FIRST(@obj^.mod_table);
while (lib_entry<>nil) do
begin
if (lib_entry^.dval.id<>0) then //import
begin
offset:=lib_entry^.dval.name_offset;
str:=obj_get_str(obj,offset);
//
if (modname<>nil) then
if (StrComp(str,modname)=0) then //used module
begin
Result:=dynlib_unlink_imported_symbols_each(root,obj);
//ended
Break;
end;
end;
//
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
end;
end;
//
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
end;
@ -2309,58 +2379,51 @@ begin
change_relro_protection_all(VM_PROT_READ);
end;
function unload_prx(lib:p_lib_info):Integer;
function unload_prx(obj:p_lib_info):Integer;
var
lib_entry:p_Lib_Entry;
str:pchar;
modname:pchar;
begin
if (lib^.ref_count=0) then
if (obj^.ref_count=0) then
begin
Assert(False,'Invalid shared object handle');
Exit(EINVAL);
end;
unref_dag(lib);
lib_entry:=TAILQ_FIRST(@lib^.mod_table);
while (lib_entry<>nil) do
unref_dag(obj);
if (obj^.ref_count<>1) then
begin
if (lib_entry^.dval.id=0) then
begin
str:=obj_get_str(lib,lib_entry^.dval.name_offset);
if (str<>nil) then
begin
Result:=dynlib_unlink_imported_symbols(lib,str);
end;
////
end;
lib_entry:=TAILQ_NEXT(lib_entry,@lib_entry^.link)
Exit(0);
end;
modname:=get_mod_name(obj,0); //export=0
if (modname<>nil) then
begin
Result:=dynlib_unlink_imported_symbols(obj,modname);
end;
unload_object(obj);
Result:=0;
end;
function alloc_obj_id(lib:p_lib_info):Boolean;
function alloc_obj_id(obj:p_lib_info):Boolean;
var
key:Integer;
begin
Result:=False;
if (lib^.id>0) then Exit(True);
if (obj^.id>0) then Exit(True);
lib^.desc.free:=nil;
lib^.objt:=NAMED_DYNL;
lib^.name:='';
obj^.desc.free:=nil;
obj^.objt:=NAMED_DYNL;
obj^.name:='';
key:=-1;
if id_name_new(@named_table,lib,@key) then
if id_name_new(@named_table,obj,@key) then
begin
lib^.id:=(key+1);
id_release(lib);
obj^.id:=(key+1);
id_release(obj);
Result:=True;
end;
end;
@ -2389,19 +2452,19 @@ end;
function find_obj_by_handle(id:Integer):p_lib_info;
var
lib:p_lib_info;
obj:p_lib_info;
begin
Result:=nil;
lib:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (lib<>nil) do
obj:=TAILQ_FIRST(@dynlibs_info.obj_list);
while (obj<>nil) do
begin
if (lib^.id=id) then
if (obj^.id=id) then
begin
Exit(lib);
Exit(obj);
end;
//
lib:=TAILQ_NEXT(lib,@lib^.link);
obj:=TAILQ_NEXT(obj,@obj^.link);
end;
end;