mirror of https://github.com/red-prig/fpPS4.git
2373 lines
68 KiB
Plaintext
2373 lines
68 KiB
Plaintext
program readself;
|
|
|
|
uses
|
|
sysutils,
|
|
elf64 in '..\..\sys\elf64.pas',
|
|
elf_nid_utils,
|
|
ps4libdoc;
|
|
|
|
type
|
|
p_elf_obj=^elf_obj;
|
|
elf_obj=packed record
|
|
is_encrypted:Integer;
|
|
self:record
|
|
hdr :p_self_header;
|
|
segs :p_self_segment;
|
|
elf_hdr :p_elf64_hdr;
|
|
MinSeg :Int64;
|
|
MaxSeg :Int64;
|
|
end;
|
|
elf:record
|
|
hdr :p_elf64_hdr;
|
|
size:Int64;
|
|
end;
|
|
size:Int64;
|
|
//
|
|
min_offset:Int64;
|
|
max_offset:Int64;
|
|
//
|
|
dyn_addr:p_elf64_dyn;
|
|
dyn_size:Int64;
|
|
//
|
|
tls_addr:Pointer;
|
|
tls_size:Int64;
|
|
//
|
|
sce_dynlib_addr:Pointer;
|
|
sce_dynlib_size:Int64;
|
|
//
|
|
proc_param_addr:PSceProcParam;
|
|
proc_param_size:Int64;
|
|
//
|
|
module_param_addr:PsceModuleParam;
|
|
module_param_size:Int64;
|
|
//
|
|
eh_frame_hdr_addr:Pointer;
|
|
eh_frame_hdr_size:Int64;
|
|
//
|
|
dt_symtab_addr:p_elf64_sym;
|
|
dt_symtab_size:Int64;
|
|
//
|
|
dt_strtab_addr:PAnsiChar;
|
|
dt_strtab_size:Int64;
|
|
//
|
|
dt_rela_addr:p_elf64_rela;
|
|
dt_rela_size:Int64;
|
|
//
|
|
dt_rela_plt_addr:p_elf64_rela;
|
|
dt_rela_plt_size:Int64;
|
|
end;
|
|
|
|
function maxInt64(a,b:Int64):Int64; inline;
|
|
begin
|
|
if (a>b) then Result:=a else Result:=b;
|
|
end;
|
|
|
|
function minInt64(a,b:Int64):Int64; inline;
|
|
begin
|
|
if (a<b) then Result:=a else Result:=b;
|
|
end;
|
|
|
|
procedure free_elf_obj(obj:p_elf_obj);
|
|
begin
|
|
if (obj=nil) then Exit;
|
|
FreeMem(obj^.self.hdr);
|
|
FreeMem(obj^.elf.hdr);
|
|
obj^:=Default(elf_obj);
|
|
end;
|
|
|
|
function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr;
|
|
begin
|
|
if (elf_hdr=nil) then Exit(nil);
|
|
if (elf_hdr^.e_phoff=0) then
|
|
begin
|
|
Result:=Pointer(elf_hdr+1);
|
|
end else
|
|
begin
|
|
Result:=Pointer(elf_hdr)+elf_hdr^.e_phoff;
|
|
end;
|
|
end;
|
|
|
|
function get_elf_phdr_offset(elf_hdr:p_elf64_hdr):Int64;
|
|
begin
|
|
if (elf_hdr=nil) then Exit(0);
|
|
if (elf_hdr^.e_phoff=0) then
|
|
begin
|
|
Result:=SizeOf(elf64_hdr);
|
|
end else
|
|
begin
|
|
Result:=elf_hdr^.e_phoff;
|
|
end;
|
|
end;
|
|
|
|
procedure fixup_offset_size(var offset,size:Int64;max:Int64);
|
|
var
|
|
s,e:Int64;
|
|
begin
|
|
s:=offset;
|
|
e:=s+size;
|
|
|
|
s:=MinInt64(s,max);
|
|
e:=MinInt64(e,max);
|
|
|
|
offset:=s;
|
|
size :=(e-s);
|
|
end;
|
|
|
|
function load_self(Const name:RawByteString;obj:p_elf_obj):Integer;
|
|
Var
|
|
F:THandle;
|
|
n,s:Int64;
|
|
Magic:DWORD;
|
|
i,count:Integer;
|
|
is_encrypted:Integer;
|
|
self_hdr :p_self_header;
|
|
self_segs:p_self_segment;
|
|
elf_hdr :p_elf64_hdr;
|
|
elf_phdr :p_elf64_phdr;
|
|
MinSeg :Int64;
|
|
MaxSeg :Int64;
|
|
src_ofs :Int64;
|
|
dst_ofs :Int64;
|
|
mem_size :Int64;
|
|
begin
|
|
Result:=0;
|
|
|
|
if (name='') or (obj=nil) then Exit(-1);
|
|
|
|
F:=FileOpen(name,fmOpenRead);
|
|
if (F=feInvalidHandle) then Exit(-2);
|
|
|
|
n:=FileRead(F,Magic,SizeOf(DWORD));
|
|
if (n<>SizeOf(DWORD)) then
|
|
begin
|
|
FileClose(F);
|
|
Exit(-3);
|
|
end;
|
|
|
|
case Magic of
|
|
ELFMAG: //elf64
|
|
begin
|
|
obj^.size:=FileSeek(F,0,fsFromEnd);
|
|
|
|
if (obj^.size<=0) then
|
|
begin
|
|
FileClose(F);
|
|
Exit(-4);
|
|
end;
|
|
|
|
obj^.elf.hdr :=GetMem(obj^.size);
|
|
obj^.elf.size:=obj^.size;
|
|
|
|
FileSeek(F,0,fsFromBeginning);
|
|
n:=FileRead(F,obj^.elf.hdr^,obj^.size);
|
|
FileClose(F);
|
|
|
|
if (n<>obj^.size) then
|
|
begin
|
|
FreeMem(obj^.elf.hdr);
|
|
obj^.elf.hdr:=nil;
|
|
Exit(-5);
|
|
end;
|
|
end;
|
|
SELF_MAGIC:
|
|
begin
|
|
obj^.size:=FileSeek(F,0,fsFromEnd);
|
|
|
|
if (obj^.size<=0) then
|
|
begin
|
|
FileClose(F);
|
|
Exit(-4);
|
|
end;
|
|
|
|
self_hdr:=GetMem(obj^.size);
|
|
obj^.self.hdr:=self_hdr;
|
|
|
|
FileSeek(F,0,fsFromBeginning);
|
|
n:=FileRead(F,self_hdr^,obj^.size);
|
|
FileClose(F);
|
|
|
|
if (n<>obj^.size) then
|
|
begin
|
|
FreeMem(obj^.self.hdr);
|
|
obj^.self.hdr:=nil;
|
|
Exit(-5);
|
|
end;
|
|
|
|
count:=self_hdr^.Num_Segments;
|
|
|
|
self_segs:=Pointer(self_hdr+1);
|
|
obj^.self.segs:=self_segs;
|
|
|
|
is_encrypted:=0;
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
if ((self_segs[i].flags and (SELF_PROPS_ENCRYPTED or SELF_PROPS_COMPRESSED))<>0) then
|
|
begin
|
|
is_encrypted:=1;
|
|
Break;
|
|
end;
|
|
|
|
obj^.is_encrypted:=is_encrypted;
|
|
|
|
elf_hdr:=Pointer(self_segs)+(count*SizeOf(t_self_segment));
|
|
obj^.self.elf_hdr:=elf_hdr;
|
|
|
|
elf_phdr:=get_elf_phdr(elf_hdr);
|
|
|
|
MinSeg:=High(Int64);
|
|
MaxSeg:=0;
|
|
|
|
count:=self_hdr^.Num_Segments;
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then
|
|
begin
|
|
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
|
|
s:=elf_phdr[s].p_offset;
|
|
MinSeg:=MinInt64(s,MinSeg);
|
|
s:=s+minInt64(self_segs[i].filesz,self_segs[i].filesz);
|
|
MaxSeg:=MaxInt64(s,MaxSeg);
|
|
end;
|
|
|
|
obj^.self.MinSeg:=MinSeg;
|
|
obj^.self.MaxSeg:=MaxSeg;
|
|
|
|
if (is_encrypted=0) then //load elf
|
|
begin
|
|
obj^.elf.hdr :=AllocMem(MaxSeg);
|
|
obj^.elf.size:=MaxSeg;
|
|
|
|
//elf_hdr part
|
|
n:=ptruint(elf_hdr)-ptruint(self_hdr); //offset to hdr
|
|
s:=self_hdr^.Header_Size+self_hdr^.Meta_size; //offset to end
|
|
s:=MinInt64(obj^.size,s); //min size
|
|
s:=MaxInt64(s,n)-n; //get size
|
|
|
|
//first page
|
|
Move(elf_hdr^,obj^.elf.hdr^,s);
|
|
|
|
count:=self_hdr^.Num_Segments;
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then
|
|
begin
|
|
s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
|
|
|
|
mem_size:=minInt64(self_segs[i].filesz,self_segs[i].memsz);
|
|
|
|
src_ofs:=self_segs[i].offset; //start offset
|
|
dst_ofs:=elf_phdr[s].p_offset; //start offset
|
|
|
|
fixup_offset_size(src_ofs,mem_size,obj^.size);
|
|
fixup_offset_size(dst_ofs,mem_size,MaxSeg);
|
|
|
|
Move( (Pointer(self_hdr) +src_ofs)^, //src
|
|
(Pointer(obj^.elf.hdr)+dst_ofs)^, //dst
|
|
mem_size); //size
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
else
|
|
begin
|
|
FileClose(F);
|
|
Exit(-1);
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure print_file_size(obj:p_elf_obj);
|
|
begin
|
|
Writeln('FILE Size:',obj^.size);
|
|
Writeln();
|
|
end;
|
|
|
|
procedure print_self_header(obj:p_elf_obj);
|
|
var
|
|
s,e:ptruint;
|
|
begin
|
|
if (obj^.self.hdr<>nil) then
|
|
begin
|
|
s:=0;
|
|
e:=obj^.self.hdr^.Header_Size+obj^.self.hdr^.Meta_size;
|
|
|
|
Writeln('SELF Header:0x',HexStr(s,8),'..0x',HexStr(e,8),':',e);
|
|
|
|
Writeln(' Magic :0x',HexStr(obj^.self.hdr^.Magic,8));
|
|
Writeln(' Version :',obj^.self.hdr^.Version );
|
|
Writeln(' Mode :',obj^.self.hdr^.Mode );
|
|
Writeln(' Endian :',obj^.self.hdr^.Endian );
|
|
Writeln(' Attr :',obj^.self.hdr^.Attr );
|
|
Writeln(' Content_Type:',obj^.self.hdr^.Content_Type);
|
|
Writeln(' Program_Type:0x',HexStr(obj^.self.hdr^.Program_Type,2));
|
|
Writeln(' Header_Size :',obj^.self.hdr^.Header_Size );
|
|
Writeln(' Meta_size :',obj^.self.hdr^.Meta_size );
|
|
Writeln(' File_size :',obj^.self.hdr^.File_size );
|
|
Writeln(' Num_Segments:',obj^.self.hdr^.Num_Segments);
|
|
Writeln(' Flags :0x',HexStr(obj^.self.hdr^.Flags,4));
|
|
Writeln(' MinSeg :0x',HexStr(obj^.self.MinSeg,8));
|
|
Writeln(' MaxSeg :0x',HexStr(obj^.self.MaxSeg,8));
|
|
end else
|
|
begin
|
|
Writeln('SELF Header:','not exist');
|
|
end;
|
|
Writeln();
|
|
end;
|
|
|
|
Function get_bytes_str(p:PByte;size:Integer):RawByteString;
|
|
begin
|
|
Result:='';
|
|
while (size<>0) do
|
|
begin
|
|
Result:=Result+HexStr(P^,2);
|
|
Inc(P);
|
|
Dec(size);
|
|
end;
|
|
end;
|
|
|
|
Function get_chars(p:PAnsiChar;size:Integer):RawByteString;
|
|
begin
|
|
Result:='';
|
|
SetString(Result,p,size);
|
|
end;
|
|
|
|
function get_program_type_str(pt:Byte):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case pt of
|
|
SELF_PT_FAKE :Result:='(FAKE)';
|
|
SELF_PT_NPDRM_EXEC :Result:='(NPDRM_EXEC)';
|
|
SELF_PT_NPDRM_DYNLIB :Result:='(NPDRM_DYNLIB)';
|
|
SELF_PT_SYSTEM_EXEC :Result:='(SYSTEM_EXEC)';
|
|
SELF_PT_SYSTEM_DYNLIB:Result:='(SYSTEM_DYNLIB)';
|
|
SELF_PT_HOST_KERNEL :Result:='(HOST_KERNEL)';
|
|
SELF_PT_SECURE_MODULE:Result:='(SECURE_MODULE)';
|
|
SELF_PT_SECURE_KERNEL:Result:='(SECURE_KERNEL)';
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
function get_sdk_version_str(version:QWORD):RawByteString;
|
|
begin
|
|
Result:=HexStr((version shr 24),2)+'.'+HexStr(((version shr 12) and $fff),3)+'.'+HexStr((version and $fff),3);
|
|
end;
|
|
|
|
procedure print_self_authinfo(obj:p_elf_obj);
|
|
label
|
|
_not_exist;
|
|
var
|
|
s,e,len:ptruint;
|
|
elf_hdr:p_elf64_hdr;
|
|
authinfo:p_self_authinfo_npdrm;
|
|
begin
|
|
if (obj^.self.hdr<>nil) then
|
|
begin
|
|
elf_hdr:=obj^.self.elf_hdr;
|
|
s:=SizeOf(t_self_header);
|
|
s:=s+(obj^.self.hdr^.Num_Segments*SizeOf(t_self_segment));
|
|
s:=s+get_elf_phdr_offset(elf_hdr);
|
|
s:=s+(elf_hdr^.e_phnum*SizeOf(elf64_phdr));
|
|
s:=AlignUp(s,SELF_SEGMENT_BLOCK_ALIGNMENT);
|
|
|
|
e:=obj^.self.hdr^.Header_Size;
|
|
|
|
if (s>=e) then goto _not_exist;
|
|
|
|
len:=(e-s);
|
|
|
|
if (len<SizeOf(t_self_authinfo)) then goto _not_exist;
|
|
|
|
Writeln('SELF authinfo:0x',HexStr(s,8),'..0x',HexStr(e,8),':',len);
|
|
|
|
authinfo:=Pointer(Pointer(obj^.self.hdr)+s);
|
|
|
|
Writeln(' AuthorityID :0x',HexStr(authinfo^.AuthorityID,16));
|
|
Writeln(' Program_Type :0x',HexStr(authinfo^.Program_Type,2),' ',get_program_type_str(authinfo^.Program_Type));
|
|
Writeln(' Program_Version:0x',HexStr(authinfo^.Program_Version shr 16,8),'(',get_sdk_version_str(authinfo^.Program_Version shr 16),')');
|
|
Writeln(' System_Version :0x',HexStr(authinfo^.System_Version shr 16,8),'(',get_sdk_version_str(authinfo^.System_Version shr 16),')');
|
|
|
|
Writeln(' Digest_SHA_256 :',get_bytes_str(@authinfo^.Digest_SHA_256,32));
|
|
|
|
if (len>=SizeOf(t_self_authinfo_npdrm)) then
|
|
case authinfo^.Program_Type of
|
|
SELF_PT_NPDRM_EXEC,
|
|
SELF_PT_NPDRM_DYNLIB:
|
|
begin
|
|
Writeln(' Unknow :',get_bytes_str(@authinfo^.Unknow,16));
|
|
Writeln(' Content_ID :',get_chars(@authinfo^.Content_ID,32));
|
|
end;
|
|
else;
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
_not_exist:
|
|
Writeln('SELF authinfo:','not exist');
|
|
end;
|
|
Writeln();
|
|
end;
|
|
|
|
function get_program_type_dump(pt:Byte):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case pt of
|
|
SELF_PT_FAKE :Result:='FAKE ';
|
|
SELF_PT_NPDRM_EXEC :Result:='NPDRM_EXEC ';
|
|
SELF_PT_NPDRM_DYNLIB :Result:='NPDRM_DYNLIB ';
|
|
SELF_PT_SYSTEM_EXEC :Result:='SYSTEM_EXEC ';
|
|
SELF_PT_SYSTEM_DYNLIB:Result:='SYSTEM_DYNLIB';
|
|
SELF_PT_HOST_KERNEL :Result:='HOST_KERNEL ';
|
|
SELF_PT_SECURE_MODULE:Result:='SECURE_MODULE';
|
|
SELF_PT_SECURE_KERNEL:Result:='SECURE_KERNEL';
|
|
else Result:='0x'+HexStr(pt,2)+' ';
|
|
end;
|
|
end;
|
|
|
|
procedure dump_self_authinfo(obj:p_elf_obj);
|
|
var
|
|
s,e,len:ptruint;
|
|
elf_hdr:p_elf64_hdr;
|
|
authinfo:p_self_authinfo;
|
|
begin
|
|
if (obj^.self.hdr=nil) then Exit;
|
|
|
|
elf_hdr:=obj^.self.elf_hdr;
|
|
s:=SizeOf(t_self_header);
|
|
s:=s+(obj^.self.hdr^.Num_Segments*SizeOf(t_self_segment));
|
|
s:=s+get_elf_phdr_offset(elf_hdr);
|
|
s:=s+(elf_hdr^.e_phnum*SizeOf(elf64_phdr));
|
|
s:=AlignUp(s,SELF_SEGMENT_BLOCK_ALIGNMENT);
|
|
|
|
e:=obj^.self.hdr^.Header_Size;
|
|
|
|
if (s>=e) then Exit;
|
|
|
|
len:=(e-s);
|
|
|
|
if (len<SizeOf(t_self_authinfo)) then Exit;
|
|
|
|
authinfo:=Pointer(Pointer(obj^.self.hdr)+s);
|
|
|
|
Write(HexStr(authinfo^.AuthorityID,16),'|');
|
|
Write(get_program_type_dump(authinfo^.Program_Type),'|');
|
|
Write(get_sdk_version_str(authinfo^.Program_Version shr 16),'|');
|
|
Write(get_sdk_version_str(authinfo^.System_Version shr 16));
|
|
|
|
Writeln();
|
|
end;
|
|
|
|
procedure print_hex(m:PBYTE;s,e:ptruint);
|
|
var
|
|
i:ptruint;
|
|
T:RawByteString;
|
|
begin
|
|
Writeln(' Offset(h)|00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F');
|
|
Writeln(' ---------+-----------------------------------------------');
|
|
|
|
T:='';
|
|
|
|
for i:=s to e-1 do
|
|
begin
|
|
if ((i mod 16)=0) then
|
|
begin
|
|
if (T<>'') then
|
|
begin
|
|
Writeln(T);
|
|
T:='';
|
|
end;
|
|
T:=T+' 0x'+HexStr(i-(i mod 16),7)+'|';
|
|
end;
|
|
T:=T+HexStr(m^,2)+' ';
|
|
Inc(m);
|
|
end;
|
|
|
|
if (T<>'') then
|
|
begin
|
|
Writeln(T);
|
|
T:='';
|
|
end;
|
|
end;
|
|
|
|
procedure print_self_metadata(obj:p_elf_obj);
|
|
label
|
|
_not_exist;
|
|
var
|
|
s,e:ptruint;
|
|
m:PBYTE;
|
|
begin
|
|
if (obj^.self.hdr<>nil) then
|
|
begin
|
|
s:=obj^.self.hdr^.Header_Size;
|
|
e:=s+obj^.self.hdr^.Meta_size;
|
|
|
|
if (s>=e) then goto _not_exist;
|
|
|
|
Writeln('SELF Metadata:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
m:=Pointer(Pointer(obj^.self.hdr)+s);
|
|
|
|
print_hex(m,s,e);
|
|
end else
|
|
begin
|
|
_not_exist:
|
|
Writeln('SELF Metadata:','not exist');
|
|
end;
|
|
Writeln;
|
|
end;
|
|
|
|
function get_seg_flags_str(flags:QWORD):RawByteString;
|
|
begin
|
|
Result:='_______';
|
|
|
|
if ((flags and SELF_PROPS_ORDERED )<>0) then Result[1]:='O';
|
|
if ((flags and SELF_PROPS_ENCRYPTED )<>0) then Result[2]:='E';
|
|
if ((flags and SELF_PROPS_SIGNED )<>0) then Result[3]:='S';
|
|
if ((flags and SELF_PROPS_COMPRESSED )<>0) then Result[4]:='C';
|
|
if ((flags and SELF_PROPS_BLOCKED )<>0) then Result[5]:='B';
|
|
if ((flags and SELF_PROPS_HAS_DIGESTS)<>0) then Result[6]:='D';
|
|
if ((flags and SELF_PROPS_HAS_EXTENTS)<>0) then Result[7]:='E';
|
|
end;
|
|
|
|
procedure print_self_segs(obj:p_elf_obj);
|
|
label
|
|
_not_exist;
|
|
var
|
|
i,count:Integer;
|
|
seg:p_self_segment;
|
|
s,e:ptruint;
|
|
begin
|
|
if (obj^.self.segs<>nil) then
|
|
begin
|
|
count:=obj^.self.hdr^.Num_Segments;
|
|
|
|
if (count=0) then goto _not_exist;
|
|
|
|
s:=ptruint(obj^.self.segs)-ptruint(obj^.self.hdr);
|
|
e:=s+(count*SizeOf(t_self_segment));
|
|
|
|
Writeln('SELF Segments Headers:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
seg:=obj^.self.segs;
|
|
|
|
Writeln(' Num Flags W BlockSize SEGID Offset Filesz Memsz');
|
|
|
|
For i:=0 to count-1 do
|
|
begin
|
|
Write(' ',i:3,' ');
|
|
Write(get_seg_flags_str(seg^.flags) ,' ');
|
|
Write(SELF_WINDOW(seg^.flags) ,' ');
|
|
Write('0x',HexStr(SELF_BLOCK_SIZE(seg^.flags),8),' ');
|
|
Write(SELF_SEGMENT_INDEX(seg^.flags):5,' ');
|
|
|
|
Write('0x',HexStr(seg^.offset,8),' ');
|
|
Write('0x',HexStr(seg^.filesz,8),' ');
|
|
Write('0x',HexStr(seg^.memsz ,8),' ');
|
|
|
|
Writeln();
|
|
Inc(seg);
|
|
end;
|
|
end else
|
|
begin
|
|
_not_exist:
|
|
Writeln('SELF Segments Headers:','not exist');
|
|
end;
|
|
Writeln();
|
|
end;
|
|
|
|
function get_elf_hdr_offset(obj:p_elf_obj):Int64;
|
|
begin
|
|
if (obj^.self.hdr<>nil) then
|
|
begin
|
|
Result:=obj^.self.hdr^.Num_Segments*SizeOf(t_self_segment);
|
|
end else
|
|
begin
|
|
Result:=0;
|
|
end;
|
|
end;
|
|
|
|
function get_e_class_str(e_class:Byte):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case e_class of
|
|
0:Result:='(SNONE)';
|
|
1:Result:='(S32)';
|
|
2:Result:='(S64)';
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
function get_e_data_str(e_data:Byte):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case e_data of
|
|
0:Result:='(NONE)';
|
|
1:Result:='(2LSB)';
|
|
2:Result:='(2MSB)';
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
function get_e_type_str(e_type:Word):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case e_type of
|
|
ET_NONE :Result:='(NONE)';
|
|
ET_REL :Result:='(REL)';
|
|
ET_EXEC :Result:='(EXEC)';
|
|
ET_DYN :Result:='(DYN)';
|
|
ET_CORE :Result:='(CORE)';
|
|
ET_SCE_EXEC :Result:='(SCE_EXEC)';
|
|
ET_SCE_REPLAY_EXEC:Result:='(SCE_REPLAY_EXEC)';
|
|
ET_SCE_RELEXEC :Result:='(SCE_RELEXEC)';
|
|
ET_SCE_STUBLIB :Result:='(SCE_STUBLIB)';
|
|
ET_SCE_DYNEXEC :Result:='(SCE_DYNEXEC)';
|
|
ET_SCE_DYNAMIC :Result:='(SCE_DYNAMIC)';
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
function get_e_machine_str(e_machine:Word):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case e_machine of
|
|
EM_NONE :Result:='(NONE)';
|
|
EM_X86_64:Result:='(X86_64)';
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
function get_osabi_name(e_machine:Word):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case e_machine of
|
|
0:Result:='(NONE)';
|
|
3:Result:='(LINUX)';
|
|
9:Result:='(FREEBSD)';
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
procedure print_elf_header(obj:p_elf_obj);
|
|
var
|
|
s,e:ptruint;
|
|
elf_hdr:p_elf64_hdr;
|
|
begin
|
|
if (obj^.elf.hdr<>nil) then
|
|
begin
|
|
elf_hdr:=obj^.elf.hdr;
|
|
s:=get_elf_hdr_offset(obj);
|
|
e:=s+SizeOf(elf64_hdr);
|
|
|
|
Writeln('ELF Header:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
Writeln(' Magic :0x',HexStr(PDWORD(@elf_hdr^.e_ident)^,8));
|
|
Writeln(' Class: :',elf_hdr^.e_ident[EI_CLASS],' ',get_e_class_str(elf_hdr^.e_ident[EI_CLASS]));
|
|
Writeln(' Data: :',elf_hdr^.e_ident[EI_DATA],' ',get_e_data_str(elf_hdr^.e_ident[EI_DATA]));
|
|
Writeln(' Version: :',elf_hdr^.e_ident[EI_VERSION]);
|
|
Writeln(' OS/ABI: :',elf_hdr^.e_ident[EI_OSABI],' ',get_osabi_name(elf_hdr^.e_ident[EI_OSABI]));
|
|
Writeln(' ABI Version:',elf_hdr^.e_ident[EI_ABIVERSION]);
|
|
|
|
Writeln(' e_type :0x',HexStr(elf_hdr^.e_type,4),' ',get_e_type_str(elf_hdr^.e_type));
|
|
Writeln(' e_machine :',elf_hdr^.e_machine,' ',get_e_machine_str(elf_hdr^.e_machine));
|
|
Writeln(' e_version :',elf_hdr^.e_version );
|
|
Writeln(' e_entry :0x',HexStr(elf_hdr^.e_entry,8));
|
|
Writeln(' e_phoff :0x',HexStr(elf_hdr^.e_phoff,8));
|
|
Writeln(' e_shoff :0x',HexStr(elf_hdr^.e_shoff,8));
|
|
Writeln(' e_flags :0x',HexStr(elf_hdr^.e_flags,8));
|
|
Writeln(' e_ehsize :',elf_hdr^.e_ehsize );
|
|
Writeln(' e_phentsize:',elf_hdr^.e_phentsize);
|
|
Writeln(' e_phnum :',elf_hdr^.e_phnum );
|
|
Writeln(' e_shentsize:',elf_hdr^.e_shentsize);
|
|
Writeln(' e_shnum :',elf_hdr^.e_shnum );
|
|
Writeln(' e_shstrndx :',elf_hdr^.e_shstrndx );
|
|
|
|
end else
|
|
begin
|
|
Writeln('ELF Header:','not exist');
|
|
end;
|
|
Writeln();
|
|
end;
|
|
|
|
function get_pt_name(p_type:DWORD):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case p_type of
|
|
PT_NULL :Result:='NULL ';
|
|
PT_LOAD :Result:='LOAD ';
|
|
PT_DYNAMIC :Result:='DYNAMIC ';
|
|
PT_INTERP :Result:='INTERP ';
|
|
PT_NOTE :Result:='NOTE ';
|
|
PT_SHLIB :Result:='SHLIB ';
|
|
PT_PHDR :Result:='PHDR ';
|
|
PT_TLS :Result:='TLS ';
|
|
PT_SCE_RELA :Result:='SCE_RELA ';
|
|
PT_SCE_DYNLIBDATA :Result:='SCE_DYNLIBDATA ';
|
|
PT_SCE_PROCPARAM :Result:='SCE_PROCPARAM ';
|
|
PT_SCE_MODULE_PARAM:Result:='SCE_MODULE_PARAM';
|
|
PT_SCE_RELRO :Result:='SCE_RELRO ';
|
|
PT_GNU_EH_FRAME :Result:='GNU_EH_FRAME ';
|
|
PT_GNU_STACK :Result:='GNU_STACK ';
|
|
PT_SCE_COMMENT :Result:='SCE_COMMENT ';
|
|
PT_SCE_VERSION :Result:='SCE_VERSION ';
|
|
PT_SCE_SEGSYM :Result:='SCE_SEGSYM ';
|
|
else Result:='0x'+HexStr(p_type,8)+' ';
|
|
end;
|
|
end;
|
|
|
|
function get_p_flags_str(flags:DWORD):RawByteString;
|
|
begin
|
|
Result:='___';
|
|
|
|
if ((flags and PF_X)<>0) then Result[1]:='X';
|
|
if ((flags and PF_W)<>0) then Result[2]:='W';
|
|
if ((flags and PF_R)<>0) then Result[3]:='R';
|
|
end;
|
|
|
|
procedure print_elf_phdr(obj:p_elf_obj);
|
|
var
|
|
s,e:ptruint;
|
|
elf_hdr :p_elf64_hdr;
|
|
elf_phdr:p_elf64_phdr;
|
|
i,count:Integer;
|
|
begin
|
|
if (obj^.elf.hdr<>nil) then
|
|
begin
|
|
elf_hdr :=obj^.elf.hdr;
|
|
elf_phdr:=get_elf_phdr(elf_hdr);
|
|
count:=elf_hdr^.e_phnum;
|
|
|
|
s:=get_elf_hdr_offset(obj);
|
|
s:=s+get_elf_phdr_offset(elf_hdr);
|
|
e:=s+count*SizeOf(elf64_phdr);
|
|
|
|
Writeln('Program Headers:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
Writeln(' Num Type Flags Offset VirtAddr PhysAddr FileSize MemSize Align');
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
Write(' ',i:3,' ');
|
|
Write(' ',get_pt_name(elf_phdr^.p_type),' ');
|
|
Write(get_p_flags_str(elf_phdr^.p_flags),' ');
|
|
|
|
Write('0x'+HexStr(elf_phdr^.p_offset,8),' ');
|
|
Write('0x'+HexStr(elf_phdr^.p_vaddr ,8),' ');
|
|
Write('0x'+HexStr(elf_phdr^.p_paddr ,8),' ');
|
|
Write('0x'+HexStr(elf_phdr^.p_filesz,8),' ');
|
|
Write('0x'+HexStr(elf_phdr^.p_memsz ,8),' ');
|
|
Write('0x'+HexStr(elf_phdr^.p_align ,8),' ');
|
|
|
|
Writeln;
|
|
|
|
Inc(elf_phdr);
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
Writeln('Program Headers:','not exist');
|
|
end;
|
|
Writeln();
|
|
end;
|
|
|
|
procedure scan_phdr(obj:p_elf_obj);
|
|
var
|
|
elf_hdr:p_elf64_hdr;
|
|
entry:p_elf64_phdr;
|
|
i,count:Integer;
|
|
begin
|
|
if (obj^.elf.hdr=nil) then Exit;
|
|
|
|
elf_hdr :=obj^.elf.hdr;
|
|
entry:=get_elf_phdr(elf_hdr);
|
|
count:=elf_hdr^.e_phnum;
|
|
|
|
obj^.min_offset:=High(Int64);
|
|
obj^.max_offset:=0;
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
case entry^.p_type of
|
|
PT_LOAD,
|
|
PT_SCE_RELA:
|
|
begin
|
|
obj^.min_offset:=MinInt64(obj^.min_offset,entry^.p_offset);
|
|
obj^.max_offset:=MaxInt64(obj^.max_offset,entry^.p_offset+entry^.p_filesz);
|
|
end;
|
|
|
|
PT_DYNAMIC:
|
|
begin
|
|
obj^.dyn_addr:=Pointer(elf_hdr)+entry^.p_offset;
|
|
obj^.dyn_size:=entry^.p_filesz;
|
|
end;
|
|
|
|
PT_TLS:
|
|
begin
|
|
obj^.tls_addr:=Pointer(elf_hdr)+entry^.p_offset;
|
|
obj^.tls_size:=entry^.p_filesz;
|
|
end;
|
|
|
|
PT_SCE_DYNLIBDATA:
|
|
begin
|
|
obj^.sce_dynlib_addr:=Pointer(elf_hdr)+entry^.p_offset;
|
|
obj^.sce_dynlib_size:=entry^.p_filesz;
|
|
end;
|
|
|
|
PT_SCE_PROCPARAM:
|
|
begin
|
|
obj^.proc_param_addr:=Pointer(elf_hdr)+entry^.p_offset;
|
|
obj^.proc_param_size:=entry^.p_filesz;
|
|
end;
|
|
|
|
PT_SCE_MODULE_PARAM:
|
|
begin
|
|
obj^.module_param_addr:=Pointer(elf_hdr)+entry^.p_offset;
|
|
obj^.module_param_size:=entry^.p_filesz;
|
|
end;
|
|
|
|
PT_GNU_EH_FRAME:
|
|
begin
|
|
obj^.eh_frame_hdr_addr:=Pointer(elf_hdr)+entry^.p_offset;
|
|
obj^.eh_frame_hdr_size:=entry^.p_filesz;
|
|
end;
|
|
|
|
PT_SCE_COMMENT:
|
|
begin
|
|
//
|
|
end;
|
|
|
|
end;
|
|
|
|
Inc(entry);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure scan_dynamic(obj:p_elf_obj);
|
|
var
|
|
entry:p_elf64_dyn;
|
|
i,count:Integer;
|
|
begin
|
|
if (obj^.dyn_addr=nil) then Exit;
|
|
|
|
entry:=obj^.dyn_addr;
|
|
count:=obj^.dyn_size div sizeof(elf64_dyn);
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
case entry^.d_tag of
|
|
|
|
DT_SCE_SYMTAB:
|
|
begin
|
|
obj^.dt_symtab_addr:=obj^.sce_dynlib_addr+entry^.d_un.d_ptr;
|
|
end;
|
|
DT_SCE_SYMTABSZ:
|
|
begin
|
|
obj^.dt_symtab_size:=entry^.d_un.d_val;
|
|
end;
|
|
|
|
DT_SCE_STRTAB:
|
|
begin
|
|
obj^.dt_strtab_addr:=obj^.sce_dynlib_addr+entry^.d_un.d_ptr;
|
|
end;
|
|
|
|
DT_STRSZ,
|
|
DT_SCE_STRSZ:
|
|
begin
|
|
obj^.dt_strtab_size:=entry^.d_un.d_ptr;
|
|
end;
|
|
|
|
DT_SCE_RELA:
|
|
begin
|
|
obj^.dt_rela_addr:=obj^.sce_dynlib_addr+entry^.d_un.d_ptr;
|
|
end;
|
|
|
|
DT_RELASZ,
|
|
DT_SCE_RELASZ:
|
|
begin
|
|
obj^.dt_rela_size:=entry^.d_un.d_val;
|
|
end;
|
|
|
|
DT_SCE_JMPREL:
|
|
begin
|
|
obj^.dt_rela_plt_addr:=obj^.sce_dynlib_addr+entry^.d_un.d_ptr;
|
|
end;
|
|
|
|
DT_PLTRELSZ,
|
|
DT_SCE_PLTRELSZ:
|
|
begin
|
|
obj^.dt_rela_plt_size:=entry^.d_un.d_val;
|
|
end;
|
|
|
|
else;
|
|
end;
|
|
|
|
Inc(entry);
|
|
end;
|
|
|
|
end;
|
|
|
|
function get_dt_name(d_tag:DWORD):RawByteString;
|
|
begin
|
|
Result:='';
|
|
Case d_tag of
|
|
DT_NULL :Result:='NULL ';
|
|
DT_NEEDED :Result:='NEEDED ';
|
|
DT_PLTRELSZ :Result:='PLTRELSZ ';
|
|
DT_PLTGOT :Result:='PLTGOT ';
|
|
DT_HASH :Result:='HASH ';
|
|
DT_STRTAB :Result:='STRTAB ';
|
|
DT_SYMTAB :Result:='SYMTAB ';
|
|
DT_RELA :Result:='RELA ';
|
|
DT_RELASZ :Result:='RELASZ ';
|
|
DT_RELAENT :Result:='RELAENT ';
|
|
DT_STRSZ :Result:='STRSZ ';
|
|
DT_SYMENT :Result:='SYMENT ';
|
|
DT_INIT :Result:='INIT ';
|
|
DT_FINI :Result:='FINI ';
|
|
DT_SONAME :Result:='SONAME ';
|
|
DT_RPATH :Result:='RPATH ';
|
|
DT_SYMBOLIC :Result:='SYMBOLIC ';
|
|
DT_REL :Result:='REL ';
|
|
DT_RELSZ :Result:='RELSZ ';
|
|
DT_RELENT :Result:='RELENT ';
|
|
DT_PLTREL :Result:='PLTREL ';
|
|
DT_DEBUG :Result:='DEBUG ';
|
|
DT_TEXTREL :Result:='TEXTREL ';
|
|
DT_JMPREL :Result:='JMPREL ';
|
|
DT_BIND_NOW :Result:='BIND_NOW ';
|
|
DT_INIT_ARRAY :Result:='INIT_ARRAY ';
|
|
DT_FINI_ARRAY :Result:='FINI_ARRAY ';
|
|
DT_INIT_ARRAYSZ :Result:='INIT_ARRAYSZ ';
|
|
DT_FINI_ARRAYSZ :Result:='FINI_ARRAYSZ ';
|
|
DT_RUNPATH :Result:='RUNPATH ';
|
|
DT_FLAGS :Result:='FLAGS ';
|
|
DT_ENCODING :Result:='ENCODING ';
|
|
DT_PREINIT_ARRAY :Result:='PREINIT_ARRAY ';
|
|
DT_PREINIT_ARRAYSZ :Result:='PREINIT_ARRAYSZ ';
|
|
DT_SCE_IDTABENTSZ :Result:='SCE_IDTABENTSZ ';
|
|
DT_SCE_FINGERPRINT :Result:='SCE_FINGERPRINT ';
|
|
DT_SCE_ORIGINAL_FILENAME :Result:='SCE_ORIGINAL_FILENAME ';
|
|
DT_SCE_MODULE_INFO :Result:='SCE_MODULE_INFO ';
|
|
DT_SCE_NEEDED_MODULE :Result:='SCE_NEEDED_MODULE ';
|
|
DT_SCE_MODULE_ATTR :Result:='SCE_MODULE_ATTR ';
|
|
DT_SCE_EXPORT_LIB :Result:='SCE_EXPORT_LIB ';
|
|
DT_SCE_IMPORT_LIB :Result:='SCE_IMPORT_LIB ';
|
|
DT_SCE_EXPORT_LIB_ATTR :Result:='SCE_EXPORT_LIB_ATTR ';
|
|
DT_SCE_IMPORT_LIB_ATTR :Result:='SCE_IMPORT_LIB_ATTR ';
|
|
DT_SCE_STUB_MODULE_NAME :Result:='SCE_STUB_MODULE_NAME ';
|
|
DT_SCE_STUB_MODULE_VERSION :Result:='SCE_STUB_MODULE_VERSION ';
|
|
DT_SCE_STUB_LIBRARY_NAME :Result:='SCE_STUB_LIBRARY_NAME ';
|
|
DT_SCE_STUB_LIBRARY_VERSION :Result:='SCE_STUB_LIBRARY_VERSION';
|
|
DT_SCE_HASH :Result:='SCE_HASH ';
|
|
DT_SCE_PLTGOT :Result:='SCE_PLTGOT ';
|
|
DT_SCE_JMPREL :Result:='SCE_JMPREL ';
|
|
DT_SCE_PLTREL :Result:='SCE_PLTREL ';
|
|
DT_SCE_PLTRELSZ :Result:='SCE_PLTRELSZ ';
|
|
DT_SCE_RELA :Result:='SCE_RELA ';
|
|
DT_SCE_RELASZ :Result:='SCE_RELASZ ';
|
|
DT_SCE_RELAENT :Result:='SCE_RELAENT ';
|
|
DT_SCE_STRTAB :Result:='SCE_STRTAB ';
|
|
DT_SCE_STRSZ :Result:='SCE_STRSZ ';
|
|
DT_SCE_SYMTAB :Result:='SCE_SYMTAB ';
|
|
DT_SCE_SYMENT :Result:='SCE_SYMENT ';
|
|
DT_SCE_HASHSZ :Result:='SCE_HASHSZ ';
|
|
DT_SCE_SYMTABSZ :Result:='SCE_SYMTABSZ ';
|
|
DT_SCE_HIOS :Result:='SCE_HIOS ';
|
|
DT_GNU_HASH :Result:='GNU_HASH ';
|
|
DT_VERSYM :Result:='VERSYM ';
|
|
DT_RELACOUNT :Result:='RELACOUNT ';
|
|
DT_RELCOUNT :Result:='RELCOUNT ';
|
|
DT_FLAGS_1 :Result:='FLAGS_1 ';
|
|
DT_VERDEF :Result:='VERDEF ';
|
|
DT_VERDEFNUM :Result:='VERDEFNUM ';
|
|
else Result:='0x'+HexStr(d_tag,8)+' ';
|
|
end;
|
|
end;
|
|
|
|
function get_lib_attr_str(id:DWord):RawByteString;
|
|
begin
|
|
Case id of
|
|
$01:Result:='AUTO_EXPORT';
|
|
$02:Result:='WEAK_EXPORT';
|
|
$08:Result:='LOOSE_IMPORT';
|
|
$09:Result:='AUTO_EXPORT|LOOSE_IMPORT';
|
|
$10:Result:='WEAK_EXPORT|LOOSE_IMPORT';
|
|
else
|
|
Result:='0x'+HexStr(id,8);
|
|
end;
|
|
end;
|
|
|
|
function get_mod_attr_str(id:DWord):RawByteString;
|
|
begin
|
|
Case id of
|
|
$00:Result:='NONE';
|
|
$01:Result:='SCE_CANT_STOP';
|
|
$02:Result:='SCE_EXCLUSIVE_LOAD';
|
|
$04:Result:='SCE_EXCLUSIVE_START';
|
|
$08:Result:='SCE_CAN_RESTART';
|
|
$10:Result:='SCE_CAN_RELOCATE';
|
|
$20:Result:='SCE_CANT_SHARE';
|
|
else
|
|
Result:='0x'+HexStr(id,8);
|
|
end;
|
|
end;
|
|
|
|
procedure print_elf_dynamic(obj:p_elf_obj);
|
|
var
|
|
s,e:ptruint;
|
|
entry:p_elf64_dyn;
|
|
i,count:Integer;
|
|
mu:TModuleValue;
|
|
la:TLibraryAttr;
|
|
str:PAnsiChar;
|
|
begin
|
|
if (obj^.dyn_addr<>nil) then
|
|
begin
|
|
entry:=obj^.dyn_addr;
|
|
count:=obj^.dyn_size div sizeof(elf64_dyn);
|
|
|
|
s:=get_elf_hdr_offset(obj);
|
|
s:=s+(Pointer(entry)-Pointer(obj^.elf.hdr));
|
|
e:=s+obj^.dyn_size;
|
|
|
|
Writeln('Dynamic section:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
Writeln(' Tag Name/Value');
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
Write(' ',get_dt_name(entry^.d_tag),' ');
|
|
|
|
case entry^.d_tag of
|
|
DT_SONAME,
|
|
DT_SCE_IMPORT_LIB,
|
|
DT_SCE_EXPORT_LIB,
|
|
DT_SCE_NEEDED_MODULE,
|
|
DT_SCE_MODULE_INFO,
|
|
DT_SCE_ORIGINAL_FILENAME,
|
|
DT_NEEDED:
|
|
begin
|
|
mu.value:=entry^.d_un.d_val;
|
|
str:=@obj^.dt_strtab_addr[mu.name_offset];
|
|
Write(mu.id:2,':',str);
|
|
end;
|
|
|
|
DT_SCE_MODULE_ATTR:
|
|
begin
|
|
mu.value:=entry^.d_un.d_val;
|
|
Write(mu.id:2,':',get_mod_attr_str(mu.name_offset));
|
|
end;
|
|
|
|
DT_SCE_EXPORT_LIB_ATTR,
|
|
DT_SCE_IMPORT_LIB_ATTR:
|
|
begin
|
|
la.value:=entry^.d_un.d_val;
|
|
Write(la.id:2,':',get_lib_attr_str(la.attr));
|
|
end;
|
|
|
|
DT_SCE_FINGERPRINT:
|
|
begin
|
|
Write(get_bytes_str(obj^.sce_dynlib_addr+entry^.d_un.d_val,20));
|
|
end;
|
|
|
|
DT_INIT_ARRAYSZ,
|
|
DT_FINI_ARRAYSZ,
|
|
DT_SCE_HASHSZ,
|
|
DT_SCE_SYMTABSZ,
|
|
DT_STRSZ,
|
|
DT_SCE_STRSZ,
|
|
DT_RELASZ,
|
|
DT_SCE_RELASZ,
|
|
DT_PLTRELSZ,
|
|
DT_SCE_PLTRELSZ,
|
|
DT_SYMENT,
|
|
DT_SCE_SYMENT:
|
|
begin
|
|
Write(entry^.d_un.d_val);
|
|
end;
|
|
|
|
else
|
|
Write('0x'+HexStr(entry^.d_un.d_val,18));
|
|
end;
|
|
|
|
Writeln;
|
|
|
|
Inc(entry);
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
Writeln('Dynamic section:','not exist');
|
|
end;
|
|
Writeln();
|
|
end;
|
|
|
|
function get_r_info_str(r_type:DWORD):RawByteString;
|
|
begin
|
|
Case r_type of
|
|
R_X86_64_NONE :Result:='R_X86_64_NONE ';
|
|
R_X86_64_64 :Result:='R_X86_64_64 ';
|
|
R_X86_64_PC32 :Result:='R_X86_64_PC32 ';
|
|
R_X86_64_GOT32 :Result:='R_X86_64_GOT32 ';
|
|
R_X86_64_PLT32 :Result:='R_X86_64_PLT32 ';
|
|
R_X86_64_COPY :Result:='R_X86_64_COPY ';
|
|
R_X86_64_GLOB_DAT :Result:='R_X86_64_GLOB_DAT ';
|
|
R_X86_64_JUMP_SLOT :Result:='R_X86_64_JUMP_SLOT ';
|
|
R_X86_64_RELATIVE :Result:='R_X86_64_RELATIVE ';
|
|
R_X86_64_GOTPCREL :Result:='R_X86_64_GOTPCREL ';
|
|
R_X86_64_32 :Result:='R_X86_64_32 ';
|
|
R_X86_64_32S :Result:='R_X86_64_32S ';
|
|
R_X86_64_16 :Result:='R_X86_64_16 ';
|
|
R_X86_64_PC16 :Result:='R_X86_64_PC16 ';
|
|
R_X86_64_8 :Result:='R_X86_64_8 ';
|
|
R_X86_64_PC8 :Result:='R_X86_64_PC8 ';
|
|
R_X86_64_DTPMOD64 :Result:='R_X86_64_DTPMOD64 ';
|
|
R_X86_64_DTPOFF64 :Result:='R_X86_64_DTPOFF64 ';
|
|
R_X86_64_TPOFF64 :Result:='R_X86_64_TPOFF64 ';
|
|
R_X86_64_TLSGD :Result:='R_X86_64_TLSGD ';
|
|
R_X86_64_TLSLD :Result:='R_X86_64_TLSLD ';
|
|
R_X86_64_DTPOFF32 :Result:='R_X86_64_DTPOFF32 ';
|
|
R_X86_64_GOTTPOFF :Result:='R_X86_64_GOTTPOFF ';
|
|
R_X86_64_TPOFF32 :Result:='R_X86_64_TPOFF32 ';
|
|
R_X86_64_PC64 :Result:='R_X86_64_PC64 ';
|
|
R_X86_64_GOTOFF64 :Result:='R_X86_64_GOTOFF64 ';
|
|
R_X86_64_GOTPC32 :Result:='R_X86_64_GOTPC32 ';
|
|
R_X86_64_GOT64 :Result:='R_X86_64_GOT64 ';
|
|
R_X86_64_GOTPCREL64 :Result:='R_X86_64_GOTPCREL64 ';
|
|
R_X86_64_GOTPC64 :Result:='R_X86_64_GOTPC64 ';
|
|
R_X86_64_GOTPLT64 :Result:='R_X86_64_GOTPLT64 ';
|
|
R_X86_64_PLTOFF64 :Result:='R_X86_64_PLTOFF64 ';
|
|
R_X86_64_SIZE32 :Result:='R_X86_64_SIZE32 ';
|
|
R_X86_64_SIZE64 :Result:='R_X86_64_SIZE64 ';
|
|
R_X86_64_GOTPC32_TLSDESC :Result:='R_X86_64_GOTPC32_TLSDESC ';
|
|
R_X86_64_TLSDESC_CALL :Result:='R_X86_64_TLSDESC_CALL ';
|
|
R_X86_64_TLSDESC :Result:='R_X86_64_TLSDESC ';
|
|
R_X86_64_IRELATIVE :Result:='R_X86_64_IRELATIVE ';
|
|
R_X86_64_RELATIVE64 :Result:='R_X86_64_RELATIVE64 ';
|
|
R_X86_64_ORBIS_GOTPCREL_LOAD:Result:='R_X86_64_ORBIS_GOTPCREL_LOAD';
|
|
|
|
else
|
|
Result:='0x'+HexStr(r_type,8)+' ';
|
|
end;
|
|
end;
|
|
|
|
procedure print_elf_rela(obj:p_elf_obj);
|
|
var
|
|
s,e:ptruint;
|
|
entry:p_elf64_rela;
|
|
i,count:Integer;
|
|
idx:DWORD;
|
|
sym:p_elf64_sym;
|
|
str:PAnsiChar;
|
|
begin
|
|
if (obj^.dt_rela_addr<>nil) then
|
|
begin
|
|
entry:=obj^.dt_rela_addr;
|
|
count:=obj^.dt_rela_size div sizeof(elf64_rela);
|
|
|
|
s:=get_elf_hdr_offset(obj);
|
|
s:=s+(Pointer(entry)-Pointer(obj^.elf.hdr));
|
|
e:=s+obj^.dt_rela_size;
|
|
|
|
Writeln('Relocation section ''.rela.dyn'':0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
Writeln(' Offset Addend Type Sym. Name');
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
Write(' 0x',HexStr(entry^.r_offset,8),' ');
|
|
|
|
Write('0x',HexStr(entry^.r_addend,8),' ');
|
|
|
|
Write(get_r_info_str(ELF64_R_TYPE(entry^.r_info)),' ');
|
|
|
|
idx:=ELF64_R_SYM(entry^.r_info);
|
|
sym:=@obj^.dt_symtab_addr[idx];
|
|
str:=@obj^.dt_strtab_addr[sym^.st_name];
|
|
|
|
Write(str);
|
|
|
|
writeln;
|
|
|
|
Inc(entry);
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
Writeln('Relocation section ''.rela.dyn''','not exist');
|
|
end;
|
|
Writeln();
|
|
|
|
if (obj^.dt_rela_plt_addr<>nil) then
|
|
begin
|
|
entry:=obj^.dt_rela_plt_addr;
|
|
count:=obj^.dt_rela_plt_size div sizeof(elf64_rela);
|
|
|
|
s:=get_elf_hdr_offset(obj);
|
|
s:=s+(Pointer(entry)-Pointer(obj^.elf.hdr));
|
|
e:=s+obj^.dt_rela_size;
|
|
|
|
Writeln('Relocation section ''.rela.plt'':0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
Writeln(' Offset Addend Type Sym. Name');
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
Write(' 0x',HexStr(entry^.r_offset,8),' ');
|
|
|
|
Write('0x',HexStr(entry^.r_addend,8),' ');
|
|
|
|
Write(get_r_info_str(ELF64_R_TYPE(entry^.r_info)),' ');
|
|
|
|
idx:=ELF64_R_SYM(entry^.r_info);
|
|
sym:=@obj^.dt_symtab_addr[idx];
|
|
str:=@obj^.dt_strtab_addr[sym^.st_name];
|
|
|
|
Write(str);
|
|
|
|
writeln;
|
|
|
|
Inc(entry);
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
Writeln('Relocation section ''.rela.plt''','not exist')
|
|
end;
|
|
Writeln;
|
|
end;
|
|
|
|
function get_st_type_str(st_type:Byte):RawByteString;
|
|
begin
|
|
Case st_type of
|
|
STT_NOTYPE :Result:='NOTYPE ';
|
|
STT_OBJECT :Result:='OBJECT ';
|
|
STT_FUN :Result:='FUN ';
|
|
STT_SECTION:Result:='SECTION';
|
|
STT_FILE :Result:='FILE ';
|
|
STT_COMMON :Result:='COMMON ';
|
|
STT_TLS :Result:='TLS ';
|
|
STT_LOOS :Result:='LOOS ';
|
|
STT_SCE :Result:='SCE ';
|
|
else
|
|
Result:=IntToStr(st_type)+' ';
|
|
end;
|
|
end;
|
|
|
|
function get_st_bind_str(st_bind:Byte):RawByteString;
|
|
begin
|
|
Case st_bind of
|
|
STB_LOCAL :Result:='LOCAL ';
|
|
STB_GLOBAL:Result:='GLOBAL';
|
|
STB_WEAK :Result:='WEAK ';
|
|
else
|
|
Result:=IntToStr(st_bind)+' ';
|
|
end;
|
|
end;
|
|
|
|
function get_st_vis_str(st_vis:Byte):RawByteString;
|
|
begin
|
|
case st_vis of
|
|
STV_DEFAULT :Result:='DEFAULT ';
|
|
STV_INTERNAL :Result:='INTERNAL ';
|
|
STV_HIDDEN :Result:='HIDDEN ';
|
|
STV_PROTECTED:Result:='PROTECTED';
|
|
else Result:=IntToStr(st_vis)+' ';
|
|
end;
|
|
end;
|
|
|
|
function get_st_shndx_str(st_shndx:Word):RawByteString;
|
|
begin
|
|
case st_shndx of
|
|
SHN_UNDEF :Result:='UNDEF';
|
|
else Result:='0x'+HexStr(st_shndx,3);
|
|
end;
|
|
end;
|
|
|
|
procedure print_elf_symtab(obj:p_elf_obj);
|
|
var
|
|
s,e:ptruint;
|
|
entry:p_elf64_sym;
|
|
i,count:Integer;
|
|
str:PAnsiChar;
|
|
begin
|
|
if (obj^.dt_symtab_addr<>nil) then
|
|
begin
|
|
entry:=obj^.dt_symtab_addr;
|
|
count:=obj^.dt_symtab_size div sizeof(elf64_sym);
|
|
|
|
s:=get_elf_hdr_offset(obj);
|
|
s:=s+(Pointer(entry)-Pointer(obj^.elf.hdr));
|
|
e:=s+obj^.dt_symtab_size;
|
|
|
|
Writeln('Symbol table ''.symtab'':0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
Writeln(' Num Value Size Type Bind Vis Ndx Name');
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
Write(' ',i:4,' ');
|
|
|
|
Write('0x',HexStr(entry^.st_value,8),' ');
|
|
|
|
Write(entry^.st_size:4,' ');
|
|
|
|
Write(get_st_type_str(ELF64_ST_TYPE(entry^.st_info)),' ');
|
|
|
|
Write(get_st_bind_str(ELF64_ST_BIND(entry^.st_info)),' ');
|
|
|
|
Write(get_st_vis_str(ELF64_ST_VISIBILITY(entry^.st_other)),' ');
|
|
|
|
Write(get_st_shndx_str(entry^.st_shndx),' ');
|
|
|
|
str:=@obj^.dt_strtab_addr[entry^.st_name];
|
|
|
|
Write(str);
|
|
|
|
writeln;
|
|
|
|
Inc(entry);
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
Writeln('Symbol table ''.symtab''','not exist');
|
|
end;
|
|
Writeln();
|
|
end;
|
|
|
|
function get_vaddr_by_offset(obj:p_elf_obj;offset:Int64):Int64;
|
|
var
|
|
elf_hdr:p_elf64_hdr;
|
|
entry:p_elf64_phdr;
|
|
i,count:Integer;
|
|
begin
|
|
Result:=-1;
|
|
if (obj^.elf.hdr=nil) then Exit;
|
|
|
|
elf_hdr :=obj^.elf.hdr;
|
|
entry:=get_elf_phdr(elf_hdr);
|
|
count:=elf_hdr^.e_phnum;
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
case entry^.p_type of
|
|
PT_LOAD,
|
|
PT_SCE_RELA:
|
|
begin
|
|
if (offset>=entry^.p_offset) and (offset<(entry^.p_offset+entry^.p_filesz)) then
|
|
begin
|
|
offset:=offset-entry^.p_offset; //delta
|
|
Result:=entry^.p_vaddr+offset;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
Inc(entry);
|
|
end;
|
|
end;
|
|
|
|
function get_rela_by_offset(obj:p_elf_obj;offset:Int64):Int64;
|
|
var
|
|
pvaddr:Int64;
|
|
entry:p_elf64_rela;
|
|
i,count:Integer;
|
|
begin
|
|
Result:=-1;
|
|
if (obj^.dt_rela_addr=nil) then Exit;
|
|
|
|
pvaddr:=get_vaddr_by_offset(obj,offset);
|
|
if (pvaddr=-1) then Exit;
|
|
|
|
entry:=obj^.dt_rela_addr;
|
|
count:=obj^.dt_rela_size div SizeOf(elf64_rela);
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
if (entry^.r_offset=pvaddr) then
|
|
begin
|
|
|
|
case ELF64_R_TYPE(entry^.r_info) of
|
|
R_X86_64_RELATIVE:
|
|
begin
|
|
Result:=entry^.r_addend;
|
|
Break;
|
|
end;
|
|
else;
|
|
end;
|
|
|
|
end;
|
|
|
|
Inc(entry);
|
|
end;
|
|
|
|
end;
|
|
|
|
function upgrade_ptr(pp:Pointer;obj:p_elf_obj):Pointer;
|
|
var
|
|
offset:Int64;
|
|
begin
|
|
Result:=nil;
|
|
offset:=Int64(pp)-Int64(obj^.elf.hdr);
|
|
offset:=get_rela_by_offset(obj,offset);
|
|
if (offset<>-1) then
|
|
begin
|
|
Result:=Pointer(obj^.elf.hdr)+offset+obj^.min_offset;
|
|
end else
|
|
if (PInt64(pp)^<>0) then
|
|
begin
|
|
Result:=Pointer(obj^.elf.hdr)+PInt64(pp)^+obj^.min_offset;
|
|
end;
|
|
if (Result<>nil) then
|
|
begin
|
|
if (Result>=(Pointer(obj^.elf.hdr)+obj^.elf.size)) then Result:=nil;
|
|
end;
|
|
end;
|
|
|
|
function upgrade_ptrv(pp:Pointer;obj:p_elf_obj):Pointer;
|
|
var
|
|
offset:Int64;
|
|
begin
|
|
Result:=nil;
|
|
offset:=Int64(pp)-Int64(obj^.elf.hdr);
|
|
offset:=get_rela_by_offset(obj,offset);
|
|
if (offset<>-1) then
|
|
begin
|
|
Result:=Pointer(offset)+$1000000;
|
|
end else
|
|
if (PInt64(pp)^<>0) then
|
|
begin
|
|
Result:=PPointer(pp)^+$1000000;
|
|
end;
|
|
end;
|
|
|
|
procedure WOfsstr(const prefix:RawByteString;pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PChar;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
p:='null';
|
|
end;
|
|
|
|
Writeln(prefix,p);
|
|
end;
|
|
|
|
procedure WOfsByt(const prefix:RawByteString;pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PByte;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(prefix,'null');
|
|
end else
|
|
begin
|
|
Writeln(prefix,'0x',HexStr(p^,2));
|
|
end;
|
|
end;
|
|
|
|
procedure WOfsDwr(const prefix:RawByteString;pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PDWORD;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(prefix,'null');
|
|
end else
|
|
begin
|
|
Writeln(prefix,'0x',HexStr(p^,8));
|
|
end;
|
|
end;
|
|
|
|
procedure WOfsQwr(const prefix:RawByteString;pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PQWORD;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(prefix,'null');
|
|
end else
|
|
begin
|
|
Writeln(prefix,'0x',HexStr(p^,16));
|
|
end;
|
|
end;
|
|
|
|
procedure WOfsPtr(const prefix:RawByteString;pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PQWORD;
|
|
begin
|
|
p:=upgrade_ptrv(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(prefix,'null');
|
|
end else
|
|
begin
|
|
Writeln(prefix,'0x',HexStr(p),' (vaddr)');
|
|
end;
|
|
end;
|
|
|
|
procedure W_sceLibcMallocReplace(pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PsceLibcMallocReplace;
|
|
e:Pointer;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(' _sceLibcMallocReplace :','null');
|
|
Exit;
|
|
end;
|
|
|
|
e:=Pointer(p)+p^.Size;
|
|
|
|
Writeln(' _sceLibcMallocReplace :');
|
|
|
|
if (Pointer(@p^.Size )+SizeOf(p^.Size )<=e) then Writeln(' Size :0x',HexStr(p^.Size ,8));
|
|
if (Pointer(@p^.Unknown1 )+SizeOf(p^.Unknown1 )<=e) then Writeln(' Unknown1 :0x',HexStr(p^.Unknown1,8));
|
|
|
|
if (Pointer(@p^.user_malloc_init )+SizeOf(p^.user_malloc_init )<=e) then WOfsPtr(' user_malloc_init :',@p^.user_malloc_init ,obj);
|
|
if (Pointer(@p^.user_malloc_finalize )+SizeOf(p^.user_malloc_finalize )<=e) then WOfsPtr(' user_malloc_finalize :',@p^.user_malloc_finalize ,obj);
|
|
if (Pointer(@p^.user_malloc )+SizeOf(p^.user_malloc )<=e) then WOfsPtr(' user_malloc :',@p^.user_malloc ,obj);
|
|
if (Pointer(@p^.user_free )+SizeOf(p^.user_free )<=e) then WOfsPtr(' user_free :',@p^.user_free ,obj);
|
|
if (Pointer(@p^.user_calloc )+SizeOf(p^.user_calloc )<=e) then WOfsPtr(' user_calloc :',@p^.user_calloc ,obj);
|
|
if (Pointer(@p^.user_realloc )+SizeOf(p^.user_realloc )<=e) then WOfsPtr(' user_realloc :',@p^.user_realloc ,obj);
|
|
if (Pointer(@p^.user_memalign )+SizeOf(p^.user_memalign )<=e) then WOfsPtr(' user_memalign :',@p^.user_memalign ,obj);
|
|
if (Pointer(@p^.user_reallocalign )+SizeOf(p^.user_reallocalign )<=e) then WOfsPtr(' user_reallocalign :',@p^.user_reallocalign ,obj);
|
|
if (Pointer(@p^.user_posix_memalign )+SizeOf(p^.user_posix_memalign )<=e) then WOfsPtr(' user_posix_memalign :',@p^.user_posix_memalign ,obj);
|
|
if (Pointer(@p^.user_malloc_stats )+SizeOf(p^.user_malloc_stats )<=e) then WOfsPtr(' user_malloc_stats :',@p^.user_malloc_stats ,obj);
|
|
if (Pointer(@p^.user_malloc_stats_fast )+SizeOf(p^.user_malloc_stats_fast )<=e) then WOfsPtr(' user_malloc_stats_fast :',@p^.user_malloc_stats_fast ,obj);
|
|
if (Pointer(@p^.user_malloc_usable_size)+SizeOf(p^.user_malloc_usable_size)<=e) then WOfsPtr(' user_malloc_usable_size :',@p^.user_malloc_usable_size,obj);
|
|
end;
|
|
|
|
procedure W_sceLibcNewReplace(pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PsceLibcNewReplace;
|
|
e:Pointer;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(' _sceLibcNewReplace :','null');
|
|
Exit;
|
|
end;
|
|
|
|
e:=Pointer(p)+p^.Size;
|
|
|
|
Writeln(' _sceLibcNewReplace :');
|
|
|
|
if (Pointer(@p^.Size )+SizeOf(p^.Size )<=e) then Writeln(' Size :0x',HexStr(p^.Size ,8));
|
|
if (Pointer(@p^.Unknown1 )+SizeOf(p^.Unknown1 )<=e) then Writeln(' Unknown1 :0x',HexStr(p^.Unknown1,8));
|
|
|
|
if (Pointer(@p^.user_new_1 )+SizeOf(p^.user_new_1 )<=e) then WOfsPtr(' user_new_1 :',@p^.user_new_1 ,obj);
|
|
if (Pointer(@p^.user_new_2 )+SizeOf(p^.user_new_2 )<=e) then WOfsPtr(' user_new_2 :',@p^.user_new_2 ,obj);
|
|
if (Pointer(@p^.user_new_array_1 )+SizeOf(p^.user_new_array_1 )<=e) then WOfsPtr(' user_new_array_1 :',@p^.user_new_array_1 ,obj);
|
|
if (Pointer(@p^.user_new_array_2 )+SizeOf(p^.user_new_array_2 )<=e) then WOfsPtr(' user_new_array_2 :',@p^.user_new_array_2 ,obj);
|
|
if (Pointer(@p^.user_delete_1 )+SizeOf(p^.user_delete_1 )<=e) then WOfsPtr(' user_delete_1 :',@p^.user_delete_1 ,obj);
|
|
if (Pointer(@p^.user_delete_2 )+SizeOf(p^.user_delete_2 )<=e) then WOfsPtr(' user_delete_2 :',@p^.user_delete_2 ,obj);
|
|
if (Pointer(@p^.user_delete_array_1)+SizeOf(p^.user_delete_array_1)<=e) then WOfsPtr(' user_delete_array_1 :',@p^.user_delete_array_1,obj);
|
|
if (Pointer(@p^.user_delete_array_2)+SizeOf(p^.user_delete_array_2)<=e) then WOfsPtr(' user_delete_array_2 :',@p^.user_delete_array_2,obj);
|
|
if (Pointer(@p^.user_delete_3 )+SizeOf(p^.user_delete_3 )<=e) then WOfsPtr(' user_delete_3 :',@p^.user_delete_3 ,obj);
|
|
if (Pointer(@p^.user_delete_4 )+SizeOf(p^.user_delete_4 )<=e) then WOfsPtr(' user_delete_4 :',@p^.user_delete_4 ,obj);
|
|
if (Pointer(@p^.user_delete_array_3)+SizeOf(p^.user_delete_array_3)<=e) then WOfsPtr(' user_delete_array_3 :',@p^.user_delete_array_3,obj);
|
|
if (Pointer(@p^.user_delete_array_4)+SizeOf(p^.user_delete_array_4)<=e) then WOfsPtr(' user_delete_array_4 :',@p^.user_delete_array_4,obj);
|
|
end;
|
|
|
|
procedure W_sceLibcMallocReplaceForTls(pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PsceLibcMallocReplaceForTls;
|
|
e:Pointer;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(' _sceLibcMallocReplaceForTls :','null');
|
|
Exit;
|
|
end;
|
|
|
|
e:=Pointer(p)+p^.Size;
|
|
|
|
Writeln(' _sceLibcMallocReplaceForTls :');
|
|
|
|
if (Pointer(@p^.Size )+SizeOf(p^.Size )<=e) then Writeln(' Size :0x',HexStr(p^.Size ,8));
|
|
if (Pointer(@p^.Unknown1 )+SizeOf(p^.Unknown1 )<=e) then Writeln(' Unknown1 :0x',HexStr(p^.Unknown1,8));
|
|
|
|
if (Pointer(@p^.user_malloc_init_for_tls )+SizeOf(p^.user_malloc_init_for_tls )<=e) then WOfsPtr(' user_malloc_init_for_tls :',@p^.user_malloc_init_for_tls ,obj);
|
|
if (Pointer(@p^.user_malloc_fini_for_tls )+SizeOf(p^.user_malloc_fini_for_tls )<=e) then WOfsPtr(' user_malloc_fini_for_tls :',@p^.user_malloc_fini_for_tls ,obj);
|
|
if (Pointer(@p^.user_malloc_for_tls )+SizeOf(p^.user_malloc_for_tls )<=e) then WOfsPtr(' user_malloc_for_tls :',@p^.user_malloc_for_tls ,obj);
|
|
if (Pointer(@p^.user_posix_memalign_for_tls)+SizeOf(p^.user_posix_memalign_for_tls)<=e) then WOfsPtr(' user_posix_memalign_for_tls :',@p^.user_posix_memalign_for_tls,obj);
|
|
if (Pointer(@p^.user_free_for_tls )+SizeOf(p^.user_free_for_tls )<=e) then WOfsPtr(' user_free_for_tls :',@p^.user_free_for_tls ,obj);
|
|
end;
|
|
|
|
procedure W_sceLibcParam(pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PSceLibcParam;
|
|
e:Pointer;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(' _sceLibcParam :','null');
|
|
Exit;
|
|
end;
|
|
|
|
e:=Pointer(p)+p^.Size;
|
|
|
|
Writeln(' _sceLibcParam :');
|
|
|
|
if (Pointer(@p^.Size )+SizeOf(p^.Size )<=e) then Writeln(' Size :0x',HexStr(p^.Size,8) );
|
|
if (Pointer(@p^.entry_count )+SizeOf(p^.entry_count )<=e) then Writeln(' entry_count :',p^.entry_count );
|
|
if (Pointer(@p^.SceLibcInternalHeap )+SizeOf(p^.SceLibcInternalHeap )<=e) then Writeln(' SceLibcInternalHeap :',p^.SceLibcInternalHeap);
|
|
|
|
if (Pointer(@p^.sceLibcHeapSize )+SizeOf(p^.sceLibcHeapSize )<=e) then WOfsDwr(' sceLibcHeapSize :',@p^.sceLibcHeapSize ,obj);
|
|
if (Pointer(@p^.sceLibcHeapDelayedAlloc )+SizeOf(p^.sceLibcHeapDelayedAlloc )<=e) then WOfsDwr(' sceLibcHeapDelayedAlloc :',@p^.sceLibcHeapDelayedAlloc ,obj);
|
|
if (Pointer(@p^.sceLibcHeapExtendedAlloc )+SizeOf(p^.sceLibcHeapExtendedAlloc )<=e) then WOfsDwr(' sceLibcHeapExtendedAlloc :',@p^.sceLibcHeapExtendedAlloc ,obj);
|
|
if (Pointer(@p^.sceLibcHeapInitialSize )+SizeOf(p^.sceLibcHeapInitialSize )<=e) then WOfsDwr(' sceLibcHeapInitialSize :',@p^.sceLibcHeapInitialSize ,obj);
|
|
|
|
if (Pointer(@p^._sceLibcMallocReplace )+SizeOf(p^._sceLibcMallocReplace )<=e) then W_sceLibcMallocReplace(@p^._sceLibcMallocReplace,obj);
|
|
if (Pointer(@p^._sceLibcNewReplace )+SizeOf(p^._sceLibcNewReplace )<=e) then W_sceLibcNewReplace (@p^._sceLibcNewReplace ,obj);
|
|
|
|
if (Pointer(@p^.sceLibcHeapHighAddressAlloc )+SizeOf(p^.sceLibcHeapHighAddressAlloc )<=e) then WOfsQwr(' sceLibcHeapHighAddressAlloc :',@p^.sceLibcHeapHighAddressAlloc ,obj);
|
|
if (Pointer(@p^.Need_sceLibc )+SizeOf(p^.Need_sceLibc )<=e) then WOfsDwr(' Need_sceLibc :',@p^.Need_sceLibc ,obj);
|
|
if (Pointer(@p^.sceLibcHeapMemoryLock )+SizeOf(p^.sceLibcHeapMemoryLock )<=e) then WOfsQwr(' sceLibcHeapMemoryLock :',@p^.sceLibcHeapMemoryLock ,obj);
|
|
if (Pointer(@p^.sceKernelInternalMemorySize )+SizeOf(p^.sceKernelInternalMemorySize )<=e) then WOfsDwr(' sceKernelInternalMemorySize :',@p^.sceKernelInternalMemorySize ,obj);
|
|
|
|
if (Pointer(@p^._sceLibcMallocReplaceForTls )+SizeOf(p^._sceLibcMallocReplaceForTls )<=e) then W_sceLibcMallocReplaceForTls(@p^._sceLibcMallocReplaceForTls,obj);
|
|
|
|
if (Pointer(@p^.sceLibcMaxSystemSize )+SizeOf(p^.sceLibcMaxSystemSize )<=e) then WOfsQwr(' sceLibcMaxSystemSize :',@p^.sceLibcMaxSystemSize ,obj);
|
|
if (Pointer(@p^.sceLibcHeapDebugFlags )+SizeOf(p^.sceLibcHeapDebugFlags )<=e) then WOfsQwr(' sceLibcHeapDebugFlags :',@p^.sceLibcHeapDebugFlags ,obj);
|
|
if (Pointer(@p^.sceLibcStdThreadStackSize )+SizeOf(p^.sceLibcStdThreadStackSize )<=e) then WOfsDwr(' sceLibcStdThreadStackSize :',@p^.sceLibcStdThreadStackSize ,obj);
|
|
|
|
|
|
if (Pointer(@p^.sceKernelInternalMemoryDebugFlags)+SizeOf(p^.sceKernelInternalMemoryDebugFlags)<=e) then WOfsDwr(' sceKernelInternalMemoryDebugFlags:',@p^.sceKernelInternalMemoryDebugFlags,obj);
|
|
if (Pointer(@p^.sceLibcWorkerThreadNum )+SizeOf(p^.sceLibcWorkerThreadNum )<=e) then WOfsDwr(' sceLibcWorkerThreadNum :',@p^.sceLibcWorkerThreadNum ,obj);
|
|
if (Pointer(@p^.sceLibcWorkerThreadPriority )+SizeOf(p^.sceLibcWorkerThreadPriority )<=e) then WOfsDwr(' sceLibcWorkerThreadPriority :',@p^.sceLibcWorkerThreadPriority ,obj);
|
|
if (Pointer(@p^.sceLibcThreadUnnamedObjects )+SizeOf(p^.sceLibcThreadUnnamedObjects )<=e) then WOfsDwr(' sceLibcThreadUnnamedObjects :',@p^.sceLibcThreadUnnamedObjects ,obj);
|
|
end;
|
|
|
|
procedure W_sceKernelMemParam(pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PSceKernelMemParam;
|
|
e:Pointer;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(' _sceKernelMemParam :','null');
|
|
Exit;
|
|
end;
|
|
|
|
e:=Pointer(p)+p^.Size;
|
|
|
|
Writeln(' _sceKernelMemParam :');
|
|
|
|
if (Pointer(@p^.Size )+SizeOf(p^.Size )<=e) then Writeln(' Size :0x',HexStr(p^.Size,8));
|
|
|
|
if (Pointer(@p^.sceKernelExtendedPageTable )+SizeOf(p^.sceKernelExtendedPageTable )<=e) then WOfsQwr(' sceKernelExtendedPageTable :',@p^.sceKernelExtendedPageTable ,obj);
|
|
if (Pointer(@p^.sceKernelFlexibleMemorySize )+SizeOf(p^.sceKernelFlexibleMemorySize )<=e) then WOfsQwr(' sceKernelFlexibleMemorySize :',@p^.sceKernelFlexibleMemorySize ,obj);
|
|
if (Pointer(@p^.sceKernelExtendedMemory1 )+SizeOf(p^.sceKernelExtendedMemory1 )<=e) then WOfsByt(' sceKernelExtendedMemory1 :',@p^.sceKernelExtendedMemory1 ,obj);
|
|
if (Pointer(@p^.sceKernelExtendedGpuPageTable)+SizeOf(p^.sceKernelExtendedGpuPageTable)<=e) then WOfsQwr(' sceKernelExtendedGpuPageTable :',@p^.sceKernelExtendedGpuPageTable,obj);
|
|
if (Pointer(@p^.sceKernelExtendedMemory2 )+SizeOf(p^.sceKernelExtendedMemory2 )<=e) then WOfsByt(' sceKernelExtendedMemory2 :',@p^.sceKernelExtendedMemory2 ,obj);
|
|
if (Pointer(@p^.sceKernelExtendedCpuPageTable)+SizeOf(p^.sceKernelExtendedCpuPageTable)<=e) then WOfsQwr(' sceKernelExtendedCpuPageTable :',@p^.sceKernelExtendedCpuPageTable,obj);
|
|
end;
|
|
|
|
procedure W_sceKernelFsParam(pp:PPointer;obj:p_elf_obj);
|
|
var
|
|
p:PSceKernelFsParam;
|
|
e:Pointer;
|
|
begin
|
|
p:=upgrade_ptr(pp,obj);
|
|
|
|
if (p=nil) then
|
|
begin
|
|
Writeln(' _sceKernelFsParam :','null');
|
|
Exit;
|
|
end;
|
|
|
|
e:=Pointer(p)+p^.Size;
|
|
|
|
Writeln(' _sceKernelFsParam :');
|
|
|
|
if (Pointer(@p^.Size )+SizeOf(p^.Size )<=e) then Writeln(' Size :0x',HexStr(p^.Size,8));
|
|
|
|
if (Pointer(@p^.sceKernelFsDupDent)+SizeOf(p^.sceKernelFsDupDent)<=e) then WOfsDwr(' sceKernelFsDupDent :',@p^.sceKernelFsDupDent,obj);
|
|
end;
|
|
|
|
procedure print_elf_sce_procparam(obj:p_elf_obj);
|
|
var
|
|
s,e:ptruint;
|
|
|
|
pa:PSceProcParam;
|
|
pe:Pointer;
|
|
begin
|
|
if (obj^.proc_param_addr<>nil) then
|
|
begin
|
|
pa:=obj^.proc_param_addr;
|
|
pe:=Pointer(pa)+obj^.proc_param_size;
|
|
|
|
s:=get_elf_hdr_offset(obj);
|
|
s:=s+(Pointer(pa)-Pointer(obj^.elf.hdr));
|
|
e:=s+obj^.proc_param_size;
|
|
|
|
Writeln('SCE proc param:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
if (Pointer(@pa^.Size )+SizeOf(pa^.Size )<=pe) then Writeln(' Size :0x',HexStr(pa^.Size ,8));
|
|
if (Pointer(@pa^.Magic )+SizeOf(pa^.Magic )<=pe) then Writeln(' Magic :0x',HexStr(pa^.Magic ,8));
|
|
if (Pointer(@pa^.Entry_count )+SizeOf(pa^.Entry_count )<=pe) then Writeln(' Entry_count :0x',HexStr(pa^.Entry_count ,8));
|
|
if (Pointer(@pa^.SDK_version )+SizeOf(pa^.SDK_version )<=pe) then Writeln(' SDK_version :0x',HexStr(pa^.SDK_version ,8),'(',get_sdk_version_str(pa^.SDK_version),')');
|
|
if (Pointer(@pa^.sceProcessName )+SizeOf(pa^.sceProcessName )<=pe) then WOfsstr(' sceProcessName :',@pa^.sceProcessName ,obj);
|
|
if (Pointer(@pa^.sceUserMainThreadName )+SizeOf(pa^.sceUserMainThreadName )<=pe) then WOfsstr(' sceUserMainThreadName :',@pa^.sceUserMainThreadName ,obj);
|
|
if (Pointer(@pa^.sceUserMainThreadPriority )+SizeOf(pa^.sceUserMainThreadPriority )<=pe) then WOfsDwr(' sceUserMainThreadPriority :',@pa^.sceUserMainThreadPriority ,obj);
|
|
if (Pointer(@pa^.sceUserMainThreadStackSize)+SizeOf(pa^.sceUserMainThreadStackSize)<=pe) then WOfsDwr(' sceUserMainThreadStackSize :',@pa^.sceUserMainThreadStackSize,obj);
|
|
|
|
if (Pointer(@pa^._sceLibcParam )+SizeOf(pa^._sceLibcParam )<=pe) then W_sceLibcParam (@pa^._sceLibcParam ,obj);
|
|
if (Pointer(@pa^._sceKernelMemParam )+SizeOf(pa^._sceKernelMemParam )<=pe) then W_sceKernelMemParam(@pa^._sceKernelMemParam,obj);
|
|
if (Pointer(@pa^._sceKernelFsParam )+SizeOf(pa^._sceKernelFsParam )<=pe) then W_sceKernelFsParam (@pa^._sceKernelFsParam ,obj);
|
|
|
|
if (Pointer(@pa^.sceProcessPreloadEnabled )+SizeOf(pa^.sceProcessPreloadEnabled )<=pe) then WOfsDwr(' sceProcessPreloadEnabled :',@pa^.sceProcessPreloadEnabled ,obj);
|
|
end else
|
|
begin
|
|
Writeln('SCE proc param:','not exist');
|
|
end;
|
|
Writeln;
|
|
end;
|
|
|
|
procedure print_elf_sce_moduleparam(obj:p_elf_obj);
|
|
var
|
|
s,e:ptruint;
|
|
|
|
pa:PsceModuleParam;
|
|
pe:Pointer;
|
|
begin
|
|
if (obj^.module_param_addr<>nil) then
|
|
begin
|
|
pa:=obj^.module_param_addr;
|
|
pe:=Pointer(pa)+obj^.module_param_size;
|
|
|
|
s:=get_elf_hdr_offset(obj);
|
|
s:=s+(Pointer(pa)-Pointer(obj^.elf.hdr));
|
|
e:=s+obj^.module_param_size;
|
|
|
|
Writeln('SCE module param:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
if (Pointer(@pa^.Size )+SizeOf(pa^.Size )<=pe) then Writeln(' Size :0x',HexStr(pa^.Size ,8));
|
|
if (Pointer(@pa^.Magic )+SizeOf(pa^.Magic )<=pe) then Writeln(' Magic :0x',HexStr(pa^.Magic ,8));
|
|
if (Pointer(@pa^.SDK_version)+SizeOf(pa^.SDK_version)<=pe) then Writeln(' SDK_version:',get_sdk_version_str(pa^.SDK_version));
|
|
end else
|
|
begin
|
|
Writeln('SCE module param:','not exist');
|
|
end;
|
|
Writeln;
|
|
end;
|
|
|
|
procedure print_elf_tls(obj:p_elf_obj);
|
|
label
|
|
_not_exist;
|
|
var
|
|
s,e:ptruint;
|
|
m:PBYTE;
|
|
begin
|
|
if (obj^.tls_addr<>nil) then
|
|
begin
|
|
s:=get_elf_hdr_offset(obj);
|
|
s:=s+(Pointer(obj^.tls_addr)-Pointer(obj^.elf.hdr));
|
|
e:=s+obj^.tls_size;
|
|
|
|
if (s>=e) then goto _not_exist;
|
|
|
|
Writeln('TLS data:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
|
|
|
|
m:=obj^.tls_addr;
|
|
|
|
print_hex(m,s,e);
|
|
end else
|
|
begin
|
|
_not_exist:
|
|
Writeln('TLS data:','not exist');
|
|
end;
|
|
Writeln;
|
|
end;
|
|
|
|
type
|
|
p_nid_info=^t_nid_info;
|
|
t_nid_info=record
|
|
sym:elf64_sym;
|
|
enc:RawByteString;
|
|
dst:RawByteString;
|
|
nid:QWORD;
|
|
mib:WORD;
|
|
lib:WORD;
|
|
end;
|
|
|
|
procedure convert_info_name(info:p_nid_info);
|
|
var
|
|
nModId,nLibId:WORD;
|
|
begin
|
|
nLibId:=0;
|
|
|
|
case ELF64_ST_TYPE(info^.sym.st_info) of
|
|
STT_NOTYPE: //original string
|
|
begin
|
|
info^.nid:=ps4_nid_hash(info^.enc);
|
|
info^.dst:=info^.enc;
|
|
info^.enc:=EncodeValue64(info^.nid);
|
|
end;
|
|
STT_SCE: //base64 string without specifying the module and library
|
|
begin
|
|
DecodeValue64(PChar(info^.enc),Length(info^.enc),info^.nid);
|
|
info^.dst:=GetFunctName(info^.nid);
|
|
end;
|
|
else //base64 string specifying the module and library
|
|
begin
|
|
DecodeEncName(PChar(info^.enc),nModId,nLibId,info^.nid);
|
|
info^.dst:=GetFunctName(info^.nid);
|
|
end;
|
|
end;
|
|
|
|
info^.mib:=nModId;
|
|
info^.lib:=nLibId;
|
|
end;
|
|
|
|
function get_st_type_short(st_type:Byte):RawByteString;
|
|
begin
|
|
Case st_type of
|
|
STT_NOTYPE :Result:='NTP';
|
|
STT_OBJECT :Result:='OBJ';
|
|
STT_FUN :Result:='FUN';
|
|
STT_SECTION:Result:='SEC';
|
|
STT_FILE :Result:='FIL';
|
|
STT_COMMON :Result:='CMN';
|
|
STT_TLS :Result:='TLS';
|
|
STT_SCE :Result:='SCE';
|
|
else
|
|
Result:=HexStr(st_type,3);
|
|
end;
|
|
end;
|
|
|
|
function get_st_bind_short(st_bind:Byte):RawByteString;
|
|
begin
|
|
Case st_bind of
|
|
STB_LOCAL :Result:='L';
|
|
STB_GLOBAL:Result:='G';
|
|
STB_WEAK :Result:='W';
|
|
else
|
|
Result:=HexStr(st_bind,1);
|
|
end;
|
|
end;
|
|
|
|
procedure print_string_dump(obj:p_elf_obj);
|
|
type
|
|
TLIBRARY=record
|
|
Name :RawByteString;
|
|
Import:Boolean;
|
|
end;
|
|
var
|
|
d_entry:p_elf64_dyn;
|
|
s_entry:p_elf64_sym;
|
|
i,count:Integer;
|
|
lu:TLibraryValue;
|
|
str:PAnsiChar;
|
|
|
|
lib:TLIBRARY;
|
|
|
|
lib_array:array of TLIBRARY;
|
|
mod_array:array of TLIBRARY;
|
|
|
|
nid_info:t_nid_info;
|
|
|
|
procedure set_lib(id:Word;lib:TLIBRARY); inline;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(lib_array);
|
|
if (i<=id) then
|
|
begin
|
|
i:=id+1;
|
|
SetLength(lib_array,i);
|
|
end;
|
|
lib_array[id]:=lib;
|
|
end;
|
|
|
|
procedure set_mod(id:Word;lib:TLIBRARY); inline;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(mod_array);
|
|
if (i<=id) then
|
|
begin
|
|
i:=id+1;
|
|
SetLength(mod_array,i);
|
|
end;
|
|
mod_array[id]:=lib;
|
|
end;
|
|
|
|
begin
|
|
SetLength(lib_array,0);
|
|
|
|
if (obj^.dyn_addr<>nil) then
|
|
begin
|
|
d_entry:=obj^.dyn_addr;
|
|
count:=obj^.dyn_size div sizeof(elf64_dyn);
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
case d_entry^.d_tag of
|
|
|
|
DT_SCE_IMPORT_LIB,
|
|
DT_SCE_EXPORT_LIB:
|
|
begin
|
|
lu.value:=d_entry^.d_un.d_val;
|
|
str:=@obj^.dt_strtab_addr[lu.name_offset];
|
|
|
|
lib.Name :=str;
|
|
lib.Import:=(d_entry^.d_tag=DT_SCE_IMPORT_LIB);
|
|
|
|
set_lib(lu.id,lib);
|
|
end;
|
|
|
|
DT_SCE_MODULE_INFO,
|
|
DT_SCE_NEEDED_MODULE:
|
|
begin
|
|
lu.value:=d_entry^.d_un.d_val;
|
|
str:=@obj^.dt_strtab_addr[lu.name_offset];
|
|
|
|
lib.Name :=str;
|
|
lib.Import:=(d_entry^.d_tag=DT_SCE_NEEDED_MODULE);
|
|
|
|
set_mod(lu.id,lib);
|
|
end;
|
|
|
|
else;
|
|
end;
|
|
|
|
Inc(d_entry);
|
|
end;
|
|
|
|
end;
|
|
|
|
if (obj^.dt_symtab_addr<>nil) then
|
|
begin
|
|
s_entry:=obj^.dt_symtab_addr;
|
|
count:=obj^.dt_symtab_size div sizeof(elf64_sym);
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
str:=@obj^.dt_strtab_addr[s_entry^.st_name];
|
|
|
|
if (Trim(str)<>'') then
|
|
begin
|
|
nid_info:=Default(t_nid_info);
|
|
nid_info.sym:=s_entry^;
|
|
nid_info.enc:=str;
|
|
|
|
convert_info_name(@nid_info);
|
|
|
|
Case lib_array[nid_info.lib].Import of
|
|
True :Write('I|');
|
|
False:Write('E|');
|
|
end;
|
|
|
|
Write(get_st_type_short(ELF64_ST_TYPE(s_entry^.st_info)),'|');
|
|
Write(get_st_bind_short(ELF64_ST_BIND(s_entry^.st_info)),'|');
|
|
|
|
Write('0x',HexStr(nid_info.nid,16),'|');
|
|
|
|
Write(BaseEncName(PChar(nid_info.enc)),'|');
|
|
|
|
Write(mod_array[nid_info.mib].Name,'|');
|
|
|
|
Write(lib_array[nid_info.lib].Name,'|');
|
|
|
|
Write(nid_info.dst);
|
|
|
|
writeln;
|
|
end;
|
|
|
|
Inc(s_entry);
|
|
end;
|
|
|
|
end;
|
|
|
|
Writeln();
|
|
end;
|
|
|
|
procedure print_libinfo_dump(obj:p_elf_obj);
|
|
type
|
|
TLIBRARY=record
|
|
Name :RawByteString;
|
|
vers :DWORD;
|
|
attr :DWORD;
|
|
Import:Boolean;
|
|
end;
|
|
var
|
|
d_entry:p_elf64_dyn;
|
|
i,count:Integer;
|
|
lu:TLibraryValue;
|
|
la:TLibraryAttr;
|
|
str:PAnsiChar;
|
|
|
|
lib:TLIBRARY;
|
|
|
|
lib_array:array of TLIBRARY;
|
|
mod_array:array of TLIBRARY;
|
|
|
|
procedure set_lib(id:Word;lib:TLIBRARY); inline;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(lib_array);
|
|
if (i<=id) then
|
|
begin
|
|
i:=id+1;
|
|
SetLength(lib_array,i);
|
|
end;
|
|
lib_array[id]:=lib;
|
|
end;
|
|
|
|
procedure set_lib_attr(id:Word;attr:DWORD); inline;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(lib_array);
|
|
if (i<=id) then
|
|
begin
|
|
i:=id+1;
|
|
SetLength(lib_array,i);
|
|
end;
|
|
lib_array[id].attr:=attr;
|
|
end;
|
|
|
|
procedure set_mod(id:Word;lib:TLIBRARY); inline;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(mod_array);
|
|
if (i<=id) then
|
|
begin
|
|
i:=id+1;
|
|
SetLength(mod_array,i);
|
|
end;
|
|
mod_array[id]:=lib;
|
|
end;
|
|
|
|
procedure set_mod_attr(id:Word;attr:DWORD); inline;
|
|
var
|
|
i:Integer;
|
|
begin
|
|
i:=Length(mod_array);
|
|
if (i<=id) then
|
|
begin
|
|
i:=id+1;
|
|
SetLength(mod_array,i);
|
|
end;
|
|
mod_array[id].attr:=attr;
|
|
end;
|
|
|
|
begin
|
|
SetLength(lib_array,0);
|
|
|
|
if (obj^.dyn_addr<>nil) then
|
|
begin
|
|
d_entry:=obj^.dyn_addr;
|
|
count:=obj^.dyn_size div sizeof(elf64_dyn);
|
|
|
|
if (count<>0) then
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
case d_entry^.d_tag of
|
|
|
|
DT_SCE_MODULE_INFO,
|
|
DT_SCE_NEEDED_MODULE:
|
|
begin
|
|
lu.value:=d_entry^.d_un.d_val;
|
|
str:=@obj^.dt_strtab_addr[lu.name_offset];
|
|
|
|
lib.Name :=str;
|
|
lib.vers :=lu.version;
|
|
lib.attr :=0;
|
|
lib.Import:=(d_entry^.d_tag=DT_SCE_NEEDED_MODULE);
|
|
|
|
set_mod(lu.id,lib);
|
|
end;
|
|
|
|
DT_SCE_IMPORT_LIB,
|
|
DT_SCE_EXPORT_LIB:
|
|
begin
|
|
lu.value:=d_entry^.d_un.d_val;
|
|
str:=@obj^.dt_strtab_addr[lu.name_offset];
|
|
|
|
lib.Name :=str;
|
|
lib.vers :=lu.version;
|
|
lib.attr :=0;
|
|
lib.Import:=(d_entry^.d_tag=DT_SCE_IMPORT_LIB);
|
|
|
|
set_lib(lu.id,lib);
|
|
end;
|
|
|
|
DT_SCE_MODULE_ATTR:
|
|
begin
|
|
la.value:=d_entry^.d_un.d_val;
|
|
set_mod_attr(la.id,la.attr);
|
|
end;
|
|
|
|
DT_SCE_EXPORT_LIB_ATTR,
|
|
DT_SCE_IMPORT_LIB_ATTR:
|
|
begin
|
|
la.value:=d_entry^.d_un.d_val;
|
|
set_lib_attr(la.id,la.attr);
|
|
end
|
|
|
|
else;
|
|
end;
|
|
|
|
Inc(d_entry);
|
|
end;
|
|
end;
|
|
|
|
count:=Length(mod_array);
|
|
if (count<>0) then
|
|
begin
|
|
Writeln('Modinfo table');
|
|
Writeln(' Id Type Ver Attr Name');
|
|
|
|
For i:=0 to count-1 do
|
|
if (mod_array[i].Name<>'') then
|
|
begin
|
|
Write(' ',i:3,' ');
|
|
|
|
Case mod_array[i].Import of
|
|
True :Write('Import ');
|
|
False:Write('Export ');
|
|
end;
|
|
|
|
Write(HexStr(mod_array[i].vers,4),' ');
|
|
|
|
Write(HexStr(mod_array[i].attr,4),' ');
|
|
|
|
Writeln(mod_array[i].Name);
|
|
end;
|
|
end;
|
|
|
|
Writeln();
|
|
|
|
count:=Length(lib_array);
|
|
if (count<>0) then
|
|
begin
|
|
Writeln('Libinfo table');
|
|
Writeln(' Id Type Ver Attr Name');
|
|
|
|
For i:=0 to count-1 do
|
|
if (lib_array[i].Name<>'') then
|
|
begin
|
|
Write(' ',i:3,' ');
|
|
|
|
Case lib_array[i].Import of
|
|
True :Write('Import ');
|
|
False:Write('Export ');
|
|
end;
|
|
|
|
Write(HexStr(lib_array[i].vers,4),' ');
|
|
|
|
Write(HexStr(lib_array[i].attr,4),' ');
|
|
|
|
Writeln(lib_array[i].Name);
|
|
end;
|
|
end;
|
|
|
|
Writeln();
|
|
end;
|
|
|
|
type
|
|
t_print_param=(
|
|
pp_file_size,
|
|
pp_self_header,
|
|
pp_self_segs,
|
|
pp_self_authinfo,
|
|
pp_self_metadata,
|
|
pp_file_header,
|
|
pp_program_headers,
|
|
pp_dynamic,
|
|
pp_relocs,
|
|
pp_symbols,
|
|
pp_sce_procparam,
|
|
pp_sce_moduleparam,
|
|
pp_tls,
|
|
pp_string_dump,
|
|
pp_authinfo_dump,
|
|
pp_libinfo_dump
|
|
);
|
|
t_print_param_set=Set of t_print_param;
|
|
|
|
var
|
|
print_param:t_print_param_set=[];
|
|
FileName:RawByteString;
|
|
|
|
procedure parse_param;
|
|
var
|
|
i:Integer;
|
|
S:RawByteString;
|
|
begin
|
|
print_param:=[];
|
|
For i:=1 to ParamCount do
|
|
begin
|
|
S:=Trim(ParamStr(i));
|
|
case S of
|
|
'-a','--all' :print_param:=[pp_file_size,
|
|
pp_self_header,
|
|
pp_self_segs,
|
|
pp_self_authinfo,
|
|
pp_file_header,
|
|
pp_program_headers,
|
|
pp_dynamic,
|
|
pp_relocs,
|
|
pp_symbols,
|
|
pp_sce_procparam,
|
|
pp_sce_moduleparam
|
|
];
|
|
|
|
'-F','--file_size' :print_param:=print_param+[pp_file_size ];
|
|
'-H','--self_header' :print_param:=print_param+[pp_self_header ];
|
|
'-S','--self_segs' :print_param:=print_param+[pp_self_segs ];
|
|
'-A','--self_authinfo' :print_param:=print_param+[pp_self_authinfo ];
|
|
'-M','--self_metadata' :print_param:=print_param+[pp_self_metadata ];
|
|
'-h','--file-header' :print_param:=print_param+[pp_file_header ];
|
|
'-l','--program-headers':print_param:=print_param+[pp_program_headers];
|
|
'-d','--dynamic' :print_param:=print_param+[pp_dynamic ];
|
|
'-r','--relocs' :print_param:=print_param+[pp_relocs ];
|
|
'-s','--symbols' :print_param:=print_param+[pp_symbols ];
|
|
'-P','--sce_procparam' :print_param:=print_param+[pp_sce_procparam ];
|
|
'-m','--sce_moduleparam':print_param:=print_param+[pp_sce_moduleparam];
|
|
'-t','--tls' :print_param:=print_param+[pp_tls ];
|
|
'-p','--string-dump' :print_param:=print_param+[pp_string_dump ];
|
|
'-i','--authinfo-dump' :print_param:=print_param+[pp_authinfo_dump ];
|
|
'-L','--libinfo-dump' :print_param:=print_param+[pp_libinfo_dump ];
|
|
else
|
|
FileName:=S;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
r:Integer;
|
|
obj:elf_obj;
|
|
|
|
begin
|
|
DefaultSystemCodePage:=CP_UTF8;
|
|
DefaultUnicodeCodePage:=CP_UTF8;
|
|
DefaultFileSystemCodePage:=CP_UTF8;
|
|
DefaultRTLFileSystemCodePage:=CP_UTF8;
|
|
UTF8CompareLocale:=CP_UTF8;
|
|
|
|
parse_param;
|
|
|
|
if (ParamCount<=1) or (FileName='') then
|
|
begin
|
|
Writeln('Usage: readself <option(s)> elf/self-file');
|
|
Writeln(' Display information about the contents of ELF/SELF format files');
|
|
Writeln(' Options are:');
|
|
Writeln(' -a --all Equivalent to: -F -H -S -A -h -l -d -r -s -P -m');
|
|
Writeln(' -F --file_size Display the file size');
|
|
Writeln(' -H --self_header Display the SELF file header');
|
|
Writeln(' -S --self_segs Display the segments header');
|
|
Writeln(' -A --self_authinfo Display the SELF authinfo');
|
|
Writeln(' -M --self_metadata Display the SELF metadata');
|
|
Writeln(' -h --file-header Display the ELF file header');
|
|
Writeln(' -l --program-headers Display the program headers');
|
|
Writeln(' -d --dynamic Display the dynamic section');
|
|
Writeln(' -r --relocs Display the relocations');
|
|
Writeln(' -s --symbols Display the symbol table');
|
|
Writeln(' -P --sce_procparam Display the sce proc param');
|
|
Writeln(' -m --sce_moduleparam Display the sce module param');
|
|
Writeln(' -t --tls Display the tls data');
|
|
Writeln(' -p --string-dump Dump the contents of symbols');
|
|
Writeln(' -i --authinfo-dump Dump the Program Identification Header');
|
|
Writeln(' -L --libinfo-dump Dump the names of libs');
|
|
Exit;
|
|
end;
|
|
|
|
r:=load_self(FileName,@obj);
|
|
|
|
if (r=0) then
|
|
begin
|
|
if (pp_file_size in print_param) then print_file_size (@obj);
|
|
if (pp_self_header in print_param) then print_self_header (@obj);
|
|
if (pp_self_segs in print_param) then print_self_segs (@obj);
|
|
if (pp_self_authinfo in print_param) then print_self_authinfo(@obj);
|
|
if (pp_self_metadata in print_param) then print_self_metadata(@obj);
|
|
|
|
if (pp_authinfo_dump in print_param) then dump_self_authinfo (@obj);
|
|
|
|
if (obj.is_encrypted<>0) then
|
|
begin
|
|
if ([pp_file_header,
|
|
pp_program_headers,
|
|
pp_dynamic,
|
|
pp_relocs,
|
|
pp_symbols,
|
|
pp_sce_procparam,
|
|
pp_sce_moduleparam,
|
|
pp_tls,
|
|
pp_string_dump]*print_param<>[]) then
|
|
begin
|
|
Writeln('Elf is_encrypted');
|
|
Writeln;
|
|
end;
|
|
end else
|
|
begin
|
|
if (pp_file_header in print_param) then print_elf_header (@obj);
|
|
if (pp_program_headers in print_param) then print_elf_phdr (@obj);
|
|
|
|
scan_phdr(@obj);
|
|
scan_dynamic(@obj);
|
|
|
|
if (pp_dynamic in print_param) then print_elf_dynamic (@obj);
|
|
if (pp_relocs in print_param) then print_elf_rela (@obj);
|
|
if (pp_symbols in print_param) then print_elf_symtab (@obj);
|
|
if (pp_sce_procparam in print_param) then print_elf_sce_procparam (@obj);
|
|
if (pp_sce_moduleparam in print_param) then print_elf_sce_moduleparam(@obj);
|
|
if (pp_tls in print_param) then print_elf_tls (@obj);
|
|
if (pp_string_dump in print_param) then print_string_dump (@obj);
|
|
if (pp_libinfo_dump in print_param) then print_libinfo_dump (@obj);
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
Writeln('Error(',r,') load file:',FileName);
|
|
end;
|
|
|
|
free_elf_obj(@obj);
|
|
|
|
//readln;
|
|
end.
|
|
|