diff --git a/sys/kern/kern_dlsym.pas b/sys/kern/kern_dlsym.pas index 6c16626c..0f04c067 100644 --- a/sys/kern/kern_dlsym.pas +++ b/sys/kern/kern_dlsym.pas @@ -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; diff --git a/sys/kern/kern_dynlib.pas b/sys/kern/kern_dynlib.pas index cf7e189a..9d126ca5 100644 --- a/sys/kern/kern_dynlib.pas +++ b/sys/kern/kern_dynlib.pas @@ -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 diff --git a/sys/kern/kern_exec.pas b/sys/kern/kern_exec.pas index 78058e89..a4091c3b 100644 --- a/sys/kern/kern_exec.pas +++ b/sys/kern/kern_exec.pas @@ -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; diff --git a/sys/kern/kern_reloc.pas b/sys/kern/kern_reloc.pas index cabeec48..923a66e3 100644 --- a/sys/kern/kern_reloc.pas +++ b/sys/kern/kern_reloc.pas @@ -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. diff --git a/sys/kern/subr_dynlib.pas b/sys/kern/subr_dynlib.pas index 0881ce96..fca3cc31 100644 --- a/sys/kern/subr_dynlib.pas +++ b/sys/kern/subr_dynlib.pas @@ -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;