+ read 64-Bit ELF executable info correctly

git-svn-id: trunk@47695 -
This commit is contained in:
florian 2020-12-06 10:23:18 +00:00
parent e60a367f1b
commit 7da0284bfc
2 changed files with 173 additions and 35 deletions

View File

@ -993,7 +993,7 @@ Implementation
function TExternalLinker.PostProcessELFExecutable(const fn : string;isdll:boolean):boolean;
type
TElf32header=packed record
magic0123 : longint;
magic0123 : array[0..3] of char;
file_class : byte;
data_encoding : byte;
file_version : byte;
@ -1029,6 +1029,41 @@ Implementation
sh_entsize : longint;
end;
telf64header=packed record
magic0123 : array[0..3] of char;
file_class : byte;
data_encoding : byte;
file_version : byte;
padding : array[$07..$0f] of byte;
e_type : word;
e_machine : word;
e_version : longword;
e_entry : qword; { entrypoint }
e_phoff : qword; { program header offset }
e_shoff : qword; { sections header offset }
e_flags : longword;
e_ehsize : word; { elf header size in bytes }
e_phentsize : word; { size of an entry in the program header array }
e_phnum : word; { 0..e_phnum-1 of entrys }
e_shentsize : word; { size of an entry in sections header array }
e_shnum : word; { 0..e_shnum-1 of entrys }
e_shstrndx : word; { index of string section header }
end;
TElf64sechdr=packed record
sh_name : longword;
sh_type : longword;
sh_flags : qword;
sh_addr : qword;
sh_offset : qword;
sh_size : qword;
sh_link : longword;
sh_info : longword;
sh_addralign : qword;
sh_entsize : qword;
end;
function MayBeSwapHeader(h : telf32header) : telf32header;
begin
result:=h;
@ -1051,6 +1086,30 @@ Implementation
end;
end;
function MayBeSwapHeader(h : telf64header) : telf64header;
begin
result:=h;
if source_info.endian<>target_info.endian then
with h do
begin
result.e_type:=swapendian(e_type);
result.e_machine:=swapendian(e_machine);
result.e_version:=swapendian(e_version);
result.e_entry:=swapendian(e_entry);
result.e_phoff:=swapendian(e_phoff);
result.e_shoff:=swapendian(e_shoff);
result.e_flags:=swapendian(e_flags);
result.e_ehsize:=swapendian(e_ehsize);
result.e_phentsize:=swapendian(e_phentsize);
result.e_phnum:=swapendian(e_phnum);
result.e_shentsize:=swapendian(e_shentsize);
result.e_shnum:=swapendian(e_shnum);
result.e_shstrndx:=swapendian(e_shstrndx);
end;
end;
function MaybeSwapSecHeader(h : telf32sechdr) : telf32sechdr;
begin
result:=h;
@ -1070,6 +1129,26 @@ Implementation
end;
end;
function MaybeSwapSecHeader(h : telf64sechdr) : telf64sechdr;
begin
result:=h;
if source_info.endian<>target_info.endian then
with h do
begin
result.sh_name:=swapendian(sh_name);
result.sh_type:=swapendian(sh_type);
result.sh_flags:=swapendian(sh_flags);
result.sh_addr:=swapendian(sh_addr);
result.sh_offset:=swapendian(sh_offset);
result.sh_size:=swapendian(sh_size);
result.sh_link:=swapendian(sh_link);
result.sh_info:=swapendian(sh_info);
result.sh_addralign:=swapendian(sh_addralign);
result.sh_entsize:=swapendian(sh_entsize);
end;
end;
var
f : file;
@ -1092,8 +1171,10 @@ Implementation
end;
var
elfheader : TElf32header;
secheader : TElf32sechdr;
elfheader32 : TElf32header;
secheader32 : TElf32sechdr;
elfheader64 : TElf64header;
secheader64 : TElf64sechdr;
i : longint;
stringoffset : longint;
secname : string;
@ -1106,39 +1187,95 @@ Implementation
if ioresult<>0 then
Message1(execinfo_f_cant_open_executable,fn);
{ read header }
blockread(f,elfheader,sizeof(tElf32header));
elfheader:=MayBeSwapHeader(elfheader);
seek(f,elfheader.e_shoff);
{ read string section header }
seek(f,elfheader.e_shoff+sizeof(TElf32sechdr)*elfheader.e_shstrndx);
blockread(f,secheader,sizeof(secheader));
secheader:=MaybeSwapSecHeader(secheader);
stringoffset:=secheader.sh_offset;
blockread(f,elfheader32,sizeof(tElf32header));
with elfheader32 do
if not((magic0123[0]=#$7f) and (magic0123[1]='E') and (magic0123[2]='L') and (magic0123[3]='F')) then
Exit;
case elfheader32.file_class of
1:
begin
elfheader32:=MayBeSwapHeader(elfheader32);
seek(f,elfheader32.e_shoff);
{ read string section header }
seek(f,elfheader32.e_shoff+sizeof(TElf32sechdr)*elfheader32.e_shstrndx);
blockread(f,secheader32,sizeof(secheader32));
secheader32:=MaybeSwapSecHeader(secheader32);
stringoffset:=secheader32.sh_offset;
seek(f,elfheader.e_shoff);
status.datasize:=0;
for i:=0 to elfheader.e_shnum-1 do
begin
blockread(f,secheader,sizeof(secheader));
secheader:=MaybeSwapSecHeader(secheader);
secname:=ReadSectionName(stringoffset+secheader.sh_name);
if secname='.text' then
begin
Message1(execinfo_x_codesize,tostr(secheader.sh_size));
status.codesize:=secheader.sh_size;
end
else if secname='.data' then
begin
Message1(execinfo_x_initdatasize,tostr(secheader.sh_size));
inc(status.datasize,secheader.sh_size);
end
else if secname='.bss' then
begin
Message1(execinfo_x_uninitdatasize,tostr(secheader.sh_size));
inc(status.datasize,secheader.sh_size);
end;
seek(f,elfheader32.e_shoff);
status.datasize:=0;
for i:=0 to elfheader32.e_shnum-1 do
begin
blockread(f,secheader32,sizeof(secheader32));
secheader32:=MaybeSwapSecHeader(secheader32);
secname:=ReadSectionName(stringoffset+secheader32.sh_name);
case secname of
'.text':
begin
Message1(execinfo_x_codesize,tostr(secheader32.sh_size));
status.codesize:=secheader32.sh_size;
end;
'.fpcdata',
'.rodata',
'.data':
begin
Message1(execinfo_x_initdatasize,tostr(secheader32.sh_size));
inc(status.datasize,secheader32.sh_size);
end;
'.bss':
begin
Message1(execinfo_x_uninitdatasize,tostr(secheader32.sh_size));
inc(status.datasize,secheader32.sh_size);
end;
end;
end;
end;
2:
begin
seek(f,0);
blockread(f,elfheader64,sizeof(tElf64header));
with elfheader64 do
if not((magic0123[0]=#$7f) and (magic0123[1]='E') and (magic0123[2]='L') and (magic0123[3]='F')) then
Exit;
elfheader64:=MayBeSwapHeader(elfheader64);
seek(f,elfheader64.e_shoff);
{ read string section header }
seek(f,elfheader64.e_shoff+sizeof(TElf64sechdr)*elfheader64.e_shstrndx);
blockread(f,secheader64,sizeof(secheader64));
secheader64:=MaybeSwapSecHeader(secheader64);
stringoffset:=secheader64.sh_offset;
end;
seek(f,elfheader64.e_shoff);
status.datasize:=0;
for i:=0 to elfheader64.e_shnum-1 do
begin
blockread(f,secheader64,sizeof(secheader64));
secheader64:=MaybeSwapSecHeader(secheader64);
secname:=ReadSectionName(stringoffset+secheader64.sh_name);
case secname of
'.text':
begin
Message1(execinfo_x_codesize,tostr(secheader64.sh_size));
status.codesize:=secheader64.sh_size;
end;
'.fpcdata',
'.rodata',
'.data':
begin
Message1(execinfo_x_initdatasize,tostr(secheader64.sh_size));
inc(status.datasize,secheader64.sh_size);
end;
'.bss':
begin
Message1(execinfo_x_uninitdatasize,tostr(secheader64.sh_size));
inc(status.datasize,secheader64.sh_size);
end;
end;
end;
end;
else
exit;
end;
close(f);
{$pop}
if ioresult<>0 then

View File

@ -816,7 +816,8 @@ begin
{ Post process,
as it only writes sections sizes so far, do this only if V_Info is set }
if success and CheckVerbosity(V_Info) and not(cs_link_nolink in current_settings.globalswitches) then
success:=PostProcessExecutable(current_module.exefilename,false);
{ do not change success here as we are only writing some info, so if this fails, it does not matter }
{ success:= }PostProcessExecutable(current_module.exefilename,false);
MakeExecutable:=success; { otherwise a recursive call to link method }
end;