diff --git a/compiler/link.pas b/compiler/link.pas index c2823a380f..a685df5e39 100644 --- a/compiler/link.pas +++ b/compiler/link.pas @@ -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 diff --git a/compiler/systems/t_linux.pas b/compiler/systems/t_linux.pas index 355c970258..aab48cbcae 100644 --- a/compiler/systems/t_linux.pas +++ b/compiler/systems/t_linux.pas @@ -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;