소스 검색

+ write code and data size for Mach-O files if possible

florian 3 년 전
부모
커밋
e657aa6431
2개의 변경된 파일120개의 추가작업 그리고 1개의 파일을 삭제
  1. 110 0
      compiler/link.pas
  2. 10 1
      compiler/systems/t_darwin.pas

+ 110 - 0
compiler/link.pas

@@ -24,6 +24,8 @@ unit link;
 
 {$i fpcdefs.inc}
 
+{ $define DEBUG_MACHO_INFO}
+
 interface
 
     uses
@@ -93,6 +95,7 @@ interface
          Function UniqueName(const str:TCmdStr): TCmdStr;
 
          function PostProcessELFExecutable(const fn: string; isdll: boolean): boolean;
+         function PostProcessMachExecutable(const fn: string; isdll: boolean): boolean;
        end;
 
       TBooleanArray = array [1..1024] of boolean;
@@ -1282,6 +1285,113 @@ Implementation
           ;
         Result:=true;
       end;
+
+
+    function TExternalLinker.PostProcessMachExecutable(const fn : string;isdll:boolean):boolean;
+      type
+        TMachHeader=record
+          magic       : longword;
+          cputype     : integer;
+          cpusubtype  : integer;
+          filetype    : longword;
+          ncmds       : longword;
+          sizeofcmds  : longword;
+          flags       : longword;
+          reserved    : longword;
+        end;
+
+        TMachLoadCommand = record
+          cmd : longword;
+          cmdsize : longword;
+        end;
+
+        TMachSegmentCommand64 = record
+          segname  : array[0..15] of char;
+          vmaddr   : qword;
+          vmsize   : qword;
+          fileoff  : qword;
+          filesize : qword;
+          maxprot  : integer;
+          initprot : integer;
+          nsects   : dword;
+          flags    : dword;
+        end;
+
+      var
+        f : file;
+        machheader : TMachHeader;
+        machloadcmd : TMachLoadCommand;
+        machsegmentcommand64 :TMachSegmentCommand64;
+        i : longint;
+      begin
+        Result:=false;
+        { open file }
+        assign(f,fn);
+        {$push}{$I-}
+        reset(f,1);
+        if ioresult<>0 then
+          Message1(execinfo_f_cant_open_executable,fn);
+
+{$ifdef DEBUG_MACHO_INFO}
+        writeln('Start reading Mach-O file');
+{$endif DEBUG_MACHO_INFO}
+        blockread(f,machheader,sizeof(TMachHeader));
+        if machheader.magic<>$feedfacf then
+          Exit;
+
+{$ifdef DEBUG_MACHO_INFO}
+        writeln('Magic header recognized (64 Bit, Little Endian)');
+        writeln('Reading ',machheader.ncmds,' commands');
+{$endif DEBUG_MACHO_INFO}
+
+        for i:=1 to machheader.ncmds do
+          begin
+            blockread(f,machloadcmd,sizeof(machloadcmd));
+            case machloadcmd.cmd of
+              $19:
+                begin
+                  blockread(f,machsegmentcommand64,sizeof(machsegmentcommand64));
+{$ifdef DEBUG_MACHO_INFO}
+                  writeln('Found SegmentCommand64: Name = ',StrPas(@machsegmentcommand64.segname),
+                    '; VMSize = $',hexstr(machsegmentcommand64.vmsize,8),
+                    '; FileSize = $',hexstr(machsegmentcommand64.filesize,8));
+{$endif DEBUG_MACHO_INFO}
+                  case StrPas(@machsegmentcommand64.segname) of
+                    '__TEXT':
+                      begin
+                        Message1(execinfo_x_codesize,tostr(machsegmentcommand64.vmsize));
+                        status.codesize:=machsegmentcommand64.vmsize;
+                      end;
+                    '__DATA_CONST':
+                      begin
+                        Message1(execinfo_x_initdatasize,tostr(machsegmentcommand64.vmsize));
+                        inc(status.datasize,machsegmentcommand64.vmsize);
+                      end;
+                    '__DATA':
+                      begin
+                        Message1(execinfo_x_uninitdatasize,tostr(machsegmentcommand64.vmsize));
+                        inc(status.datasize,machsegmentcommand64.vmsize);
+                      end;
+                  end;
+                  Seek(f,FilePos(f)+machloadcmd.cmdsize-sizeof(machloadcmd)-sizeof(machsegmentcommand64));
+                end;
+              else
+                begin
+{$ifdef DEBUG_MACHO_INFO}
+                  writeln('Found Load Command: $',hexstr(machloadcmd.cmd,4),', skipping');
+{$endif DEBUG_MACHO_INFO}
+                  Seek(f,FilePos(f)+machloadcmd.cmdsize-sizeof(machloadcmd));
+                end;
+            end;
+          end;
+        close(f);
+        {$pop}
+        if ioresult<>0 then
+          ;
+        Result:=true;
+      end;
+
+
 {*****************************************************************************
                               TINTERNALLINKER
 *****************************************************************************}

+ 10 - 1
compiler/systems/t_darwin.pas

@@ -67,6 +67,7 @@ implementation
       function  MakeSharedLibrary:boolean;override;
       procedure LoadPredefinedLibraryOrder; override;
       procedure InitSysInitUnitName; override;
+      function postprocessexecutable(const fn : string;isdll:boolean):boolean;
     end;
 
 {*****************************************************************************
@@ -564,7 +565,7 @@ implementation
          (extdbgbinstr<>'') then
         success:=DoExec(extdbgbinstr,extdbgcmdstr,false,false);
 
-    { Remove ReponseFile }
+      { Remove ReponseFile }
       if (success) and not(cs_link_nolink in current_settings.globalswitches) then
        begin
          DeleteFile(outputexedir+Info.ResName);
@@ -573,6 +574,10 @@ implementation
          DeleteFile(linkfiles);
        end;
 
+     { Post process }
+     if success then
+       success:=PostProcessExecutable(current_module.exefilename,false);
+
       MakeExecutable:=success;   { otherwise a recursive call to link method }
     end;
 
@@ -703,6 +708,10 @@ implementation
     end;
 
 
+  function TLinkerDarwin.postprocessexecutable(const fn : string;isdll:boolean):boolean;
+    begin
+      Result:=PostProcessMachExecutable(fn,isdll);
+    end;
 
 {*****************************************************************************
                                      Initialize