瀏覽代碼

+ read 64-Bit ELF executable info correctly

git-svn-id: trunk@47695 -
florian 4 年之前
父節點
當前提交
7da0284bfc
共有 2 個文件被更改,包括 175 次插入37 次删除
  1. 173 36
      compiler/link.pas
  2. 2 1
      compiler/systems/t_linux.pas

+ 173 - 36
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;
-
-        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;
-
-          end;
+        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,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;
+
+              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

+ 2 - 1
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;