View Issue Details

IDProjectCategoryView StatusLast Update
0035326FPCCompilerpublic2019-05-10 15:00
ReporterCyraxAssigned ToSven Barth 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product Version3.3.1Product Buildr41823 
Target VersionFixed in Version3.3.1 
Summary0035326: For some reason objcopy --add-gnu-debuglink=<file> doesn't support full path with spaces to file.
DescriptionLike summary says, --add-gnu-debuglink=<file> doesn't support full path with spaces to file so passing one will cause objcopy to exit with error and thus fail whole compilation process. The path is quoted properly. Other calls to objcopy are successful.

Compiler executes objcopy utility when running compilation process with -Xg option.

Attached patch will remedy this.
Steps To Reproduce0. Make a quite deep directory structure with spaces.
1. Create a simple test project and compile it with -Xg option.
Additional InformationLoosely related to bug report https://bugs.freepascal.org/view.php?id=35323
TagsNo tags attached.
Fixed in Revision42025
FPCOldBugId
FPCTarget-
Attached Files
  • fix_objcopy_execution.diff (9,335 bytes)
    diff --git compiler/cfileutl.pas compiler/cfileutl.pas
    index de6991e73e..012b536b5c 100644
    --- compiler/cfileutl.pas
    +++ compiler/cfileutl.pas
    @@ -133,7 +133,7 @@ interface
         procedure DoneFileUtils;
     
         function UnixRequoteWithDoubleQuotes(const QuotedStr: TCmdStr): TCmdStr;
    -    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; Flags: TExecuteFlags = []): Longint;
    +    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; const WorkDir: AnsiString = ''; Flags: TExecuteFlags = []): Longint;
         function RequotedExecuteProcess(const Path: AnsiString; const ComLine: array of AnsiString; Flags: TExecuteFlags = []): Longint;
         function Shell(const command:ansistring): longint;
     
    @@ -574,7 +574,7 @@ end;
     {$endif unix}
          end;
     
    -    Function FileExists ( Const F : TCmdStr;allowcache:boolean) : Boolean;
    +    function FileExists(const F: TCmdStr; allowcache: boolean): Boolean;
           begin
     {$ifdef usedircache}
             if allowcache then
    @@ -676,7 +676,7 @@ end;
           end;
     
     
    -    Function PathExists (const F : TCmdStr;allowcache:boolean) : Boolean;
    +    function PathExists(const F: TCmdStr; allowcache: boolean): Boolean;
           Var
             i: longint;
             hs : TCmdStr;
    @@ -700,7 +700,7 @@ end;
           end;
     
     
    -    Function RemoveDir(d:TCmdStr):boolean;
    +    function RemoveDir(d: TCmdStr): boolean;
           begin
             if d[length(d)]=source_info.DirSep then
              Delete(d,length(d),1);
    @@ -711,7 +711,7 @@ end;
           end;
     
     
    -    Function FixPath(const s:TCmdStr;allowdot:boolean):TCmdStr;
    +    function FixPath(const s: TCmdStr; allowdot: boolean): TCmdStr;
           var
             i, L : longint;
             P: PChar;
    @@ -912,7 +912,7 @@ end;
          end;
     
     
    -    Function TargetFixPath(s:TCmdStr;allowdot:boolean):TCmdStr;
    +    function TargetFixPath(s: TCmdStr; allowdot: boolean): TCmdStr;
           var
             i : longint;
           begin
    @@ -1525,7 +1525,7 @@ end;
           end;
     
     
    -    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; Flags: TExecuteFlags): Longint;
    +    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; const WorkDir: AnsiString; Flags: TExecuteFlags): Longint;
           var
             quote_script: tscripttype;
           begin
    @@ -1538,9 +1538,9 @@ end;
             else
               quote_script:=source_info.script;
             if quote_script=script_unix then
    -          result:=sysutils.ExecuteProcess(Path,UnixRequoteWithDoubleQuotes(ComLine),Flags)
    +          result:=sysutils.ExecuteProcess(Path,UnixRequoteWithDoubleQuotes(ComLine), WorkDir,Flags)
             else
    -          result:=sysutils.ExecuteProcess(Path,ComLine,Flags)
    +          result:=sysutils.ExecuteProcess(Path,ComLine, WorkDir,Flags)
           end;
     
     
    diff --git compiler/link.pas compiler/link.pas
    index 887a5f1ebd..82666fe2d7 100644
    --- compiler/link.pas
    +++ compiler/link.pas
    @@ -75,6 +75,8 @@ interface
              function  ReOrderEntries : boolean;
            end;
     
    +      { TExternalLinker }
    +
           TExternalLinker = class(TLinker)
           public
              Info : TLinkerInfo;
    @@ -82,7 +84,7 @@ interface
              Destructor Destroy;override;
              Function  FindUtil(const s:TCmdStr):TCmdStr;
              Function  CatFileContent(para:TCmdStr):TCmdStr;
    -         Function  DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
    +         Function  DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean;workdir:TCmdStr=''):boolean;
              procedure SetDefaultInfo;virtual;
              Function  MakeStaticLibrary:boolean;override;
            end;
    @@ -619,7 +621,7 @@ Implementation
                                   TEXTERNALLINKER
     *****************************************************************************}
     
    -    Constructor TExternalLinker.Create;
    +    constructor TExternalLinker.Create;
           begin
             inherited Create;
             { set generic defaults }
    @@ -647,18 +649,18 @@ Implementation
           end;
     
     
    -    Destructor TExternalLinker.Destroy;
    +    destructor TExternalLinker.Destroy;
           begin
             inherited destroy;
           end;
     
     
    -    Procedure TExternalLinker.SetDefaultInfo;
    +    procedure TExternalLinker.SetDefaultInfo;
           begin
           end;
     
     
    -    Function TExternalLinker.FindUtil(const s:TCmdStr):TCmdStr;
    +    function TExternalLinker.FindUtil(const s: TCmdStr): TCmdStr;
           var
             Found    : boolean;
             FoundBin : TCmdStr;
    @@ -688,7 +690,7 @@ Implementation
           end;
     
     
    -    Function TExternalLinker.CatFileContent(para : TCmdStr) : TCmdStr;
    +    function TExternalLinker.CatFileContent(para: TCmdStr): TCmdStr;
           var
             filecontent : TCmdStr;
             f : text;
    @@ -722,7 +724,7 @@ Implementation
             CatFileContent:=filecontent;
           end;
     
    -    Function TExternalLinker.DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
    +    function TExternalLinker.DoExec(const command: TCmdStr; para: TCmdStr; showinfo, useshell: boolean; workdir: TCmdStr): boolean;
           var
             exitcode: longint;
           begin
    @@ -734,7 +736,7 @@ Implementation
                  exitcode:=shell(maybequoted(command)+' '+para)
                else
                  try
    -               exitcode:=RequotedExecuteProcess(command,para);
    +               exitcode:=RequotedExecuteProcess(command,para, workdir);
                  except on E:EOSError do
                    begin
                      Message(exec_e_cant_call_linker);
    @@ -765,7 +767,7 @@ Implementation
           end;
     
     
    -    Function TExternalLinker.MakeStaticLibrary:boolean;
    +    function TExternalLinker.MakeStaticLibrary: boolean;
     
             function GetNextFiles(const maxCmdLength : Longint; var item : TCmdStrListItem; const addfilecmd : string) : TCmdStr;
               begin
    diff --git compiler/systems/t_linux.pas compiler/systems/t_linux.pas
    index 105a4ba82e..e9d42432f8 100644
    --- compiler/systems/t_linux.pas
    +++ compiler/systems/t_linux.pas
    @@ -389,7 +389,7 @@ begin
          DllCmd[1]:=DllCmd[1]+' $RES';
          DllCmd[2]:='strip --strip-unneeded $EXE';
          ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
    -     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
    +     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBGFN $EXE';
          ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
     
          SetupDynlinker(DynamicLinker,libctype);
    @@ -1376,7 +1376,8 @@ var
       i : longint;
       binstr,
       cmdstr,
    -  mapstr : TCmdStr;
    +  mapstr,
    +  workdir : TCmdStr;
       success : boolean;
       DynLinkStr : string;
       GCSectionsStr,
    @@ -1435,13 +1436,14 @@ begin
       { Create external .dbg file with debuginfo }
       if success and (cs_link_separate_dbg_file in current_settings.globalswitches) then
         begin
    +      workdir:=ExtractFilePath(current_module.exefilename);
           for i:=1 to 3 do
             begin
               SplitBinCmd(Info.ExtDbgCmd[i],binstr,cmdstr);
               Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
               Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename)));
               Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename));
    -          success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
    +          success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false,workdir);
               if not success then
                 break;
             end;
    diff --git rtl/objpas/sysutils/osutilsh.inc rtl/objpas/sysutils/osutilsh.inc
    index f7d6bcacca..6bd7228791 100644
    --- rtl/objpas/sysutils/osutilsh.inc
    +++ rtl/objpas/sysutils/osutilsh.inc
    @@ -30,7 +30,7 @@ Function GetEnvironmentVariableCount : Integer;
     {$IFDEF HAS_SLEEP}
     procedure Sleep(milliseconds: Cardinal);
     {$ENDIF}
    -function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
    +function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Const WorkDir: RawByteString = '';Flags:TExecuteFlags=[]):integer;
     function ExecuteProcess(Const Path: RawByteString; Const ComLine: Array of RawByteString;Flags:TExecuteFlags=[]):integer;
     function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
     function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
    diff --git rtl/unix/sysutils.pp rtl/unix/sysutils.pp
    index 29d64d081f..9b81f9ad77 100644
    --- rtl/unix/sysutils.pp
    +++ rtl/unix/sysutils.pp
    @@ -1325,7 +1325,7 @@ begin
     end;
     
     
    -function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
    +function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Const WorkDir: RawByteString;Flags:TExecuteFlags=[]):integer;
     var
       pid    : longint;
       e      : EOSError;
    @@ -1370,6 +1370,7 @@ Begin
       if pid=0 then
        begin
        {The child does the actual exec, and then exits}
    +      if Length(WorkDir) > 0 then fpChdir(WorkDir);
           fpexecv(pchar(pointer(LPath)),Cmdline2);
          { If the execve fails, we return an exitvalue of 127, to let it be known}
          fpExit(127);
    @@ -1385,8 +1386,7 @@ Begin
       { We're in the parent, let's wait. }
       result:=WaitProcess(pid); // WaitPid and result-convert
     
    -  if Comline<>'' Then
    -    freemem(cmdline2);
    +  freemem(cmdline2);
     
       if (result<0) or (result=127) then
         begin
    
  • fix_objcopy_execution2.diff (11,965 bytes)
    diff --git compiler/cfileutl.pas compiler/cfileutl.pas
    index de6991e73e..2104c1dca6 100644
    --- compiler/cfileutl.pas
    +++ compiler/cfileutl.pas
    @@ -133,7 +133,7 @@ interface
         procedure DoneFileUtils;
     
         function UnixRequoteWithDoubleQuotes(const QuotedStr: TCmdStr): TCmdStr;
    -    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; Flags: TExecuteFlags = []): Longint;
    +    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; const WorkDir: AnsiString = ''; Flags: TExecuteFlags = []): Longint;
         function RequotedExecuteProcess(const Path: AnsiString; const ComLine: array of AnsiString; Flags: TExecuteFlags = []): Longint;
         function Shell(const command:ansistring): longint;
     
    @@ -574,7 +574,7 @@ end;
     {$endif unix}
          end;
     
    -    Function FileExists ( Const F : TCmdStr;allowcache:boolean) : Boolean;
    +    function FileExists(const F: TCmdStr; allowcache: boolean): Boolean;
           begin
     {$ifdef usedircache}
             if allowcache then
    @@ -676,7 +676,7 @@ end;
           end;
     
     
    -    Function PathExists (const F : TCmdStr;allowcache:boolean) : Boolean;
    +    function PathExists(const F: TCmdStr; allowcache: boolean): Boolean;
           Var
             i: longint;
             hs : TCmdStr;
    @@ -700,7 +700,7 @@ end;
           end;
     
     
    -    Function RemoveDir(d:TCmdStr):boolean;
    +    function RemoveDir(d: TCmdStr): boolean;
           begin
             if d[length(d)]=source_info.DirSep then
              Delete(d,length(d),1);
    @@ -711,7 +711,7 @@ end;
           end;
     
     
    -    Function FixPath(const s:TCmdStr;allowdot:boolean):TCmdStr;
    +    function FixPath(const s: TCmdStr; allowdot: boolean): TCmdStr;
           var
             i, L : longint;
             P: PChar;
    @@ -912,7 +912,7 @@ end;
          end;
     
     
    -    Function TargetFixPath(s:TCmdStr;allowdot:boolean):TCmdStr;
    +    function TargetFixPath(s: TCmdStr; allowdot: boolean): TCmdStr;
           var
             i : longint;
           begin
    @@ -1525,7 +1525,7 @@ end;
           end;
     
     
    -    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; Flags: TExecuteFlags): Longint;
    +    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; const WorkDir: AnsiString; Flags: TExecuteFlags): Longint;
           var
             quote_script: tscripttype;
           begin
    @@ -1538,9 +1538,9 @@ end;
             else
               quote_script:=source_info.script;
             if quote_script=script_unix then
    -          result:=sysutils.ExecuteProcess(Path,UnixRequoteWithDoubleQuotes(ComLine),Flags)
    +          result:=sysutils.ExecuteProcess(Path,UnixRequoteWithDoubleQuotes(ComLine), Flags, WorkDir)
             else
    -          result:=sysutils.ExecuteProcess(Path,ComLine,Flags)
    +          result:=sysutils.ExecuteProcess(Path,ComLine,Flags,WorkDir)
           end;
     
     
    diff --git compiler/link.pas compiler/link.pas
    index 03432fdf18..094e1e401f 100644
    --- compiler/link.pas
    +++ compiler/link.pas
    @@ -75,6 +75,8 @@ interface
              function  ReOrderEntries : boolean;
            end;
     
    +      { TExternalLinker }
    +
           TExternalLinker = class(TLinker)
           public
              Info : TLinkerInfo;
    @@ -82,7 +84,7 @@ interface
              Destructor Destroy;override;
              Function  FindUtil(const s:TCmdStr):TCmdStr;
              Function  CatFileContent(para:TCmdStr):TCmdStr;
    -         Function  DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
    +         Function  DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean;workdir:TCmdStr=''):boolean;
              procedure SetDefaultInfo;virtual;
              Function  MakeStaticLibrary:boolean;override;
            end;
    @@ -619,7 +621,7 @@ Implementation
                                   TEXTERNALLINKER
     *****************************************************************************}
     
    -    Constructor TExternalLinker.Create;
    +    constructor TExternalLinker.Create;
           begin
             inherited Create;
             { set generic defaults }
    @@ -647,18 +649,18 @@ Implementation
           end;
     
     
    -    Destructor TExternalLinker.Destroy;
    +    destructor TExternalLinker.Destroy;
           begin
             inherited destroy;
           end;
     
     
    -    Procedure TExternalLinker.SetDefaultInfo;
    +    procedure TExternalLinker.SetDefaultInfo;
           begin
           end;
     
     
    -    Function TExternalLinker.FindUtil(const s:TCmdStr):TCmdStr;
    +    function TExternalLinker.FindUtil(const s: TCmdStr): TCmdStr;
           var
             Found    : boolean;
             FoundBin : TCmdStr;
    @@ -688,7 +690,7 @@ Implementation
           end;
     
     
    -    Function TExternalLinker.CatFileContent(para : TCmdStr) : TCmdStr;
    +    function TExternalLinker.CatFileContent(para: TCmdStr): TCmdStr;
           var
             filecontent : TCmdStr;
             f : text;
    @@ -722,7 +724,7 @@ Implementation
             CatFileContent:=filecontent;
           end;
     
    -    Function TExternalLinker.DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
    +    function TExternalLinker.DoExec(const command: TCmdStr; para: TCmdStr; showinfo, useshell: boolean; workdir: TCmdStr): boolean;
           var
             exitcode: longint;
           begin
    @@ -734,7 +736,7 @@ Implementation
                  exitcode:=shell(maybequoted(command)+' '+para)
                else
                  try
    -               exitcode:=RequotedExecuteProcess(command,para);
    +               exitcode:=RequotedExecuteProcess(command,para, workdir);
                  except on E:EOSError do
                    begin
                      Message(exec_e_cant_call_linker);
    @@ -765,7 +767,7 @@ Implementation
           end;
     
     
    -    Function TExternalLinker.MakeStaticLibrary:boolean;
    +    function TExternalLinker.MakeStaticLibrary: boolean;
     
             function GetNextFiles(const maxCmdLength : Longint; var item : TCmdStrListItem; const addfilecmd : string) : TCmdStr;
               begin
    diff --git compiler/systems/t_linux.pas compiler/systems/t_linux.pas
    index 105a4ba82e..e9d42432f8 100644
    --- compiler/systems/t_linux.pas
    +++ compiler/systems/t_linux.pas
    @@ -389,7 +389,7 @@ begin
          DllCmd[1]:=DllCmd[1]+' $RES';
          DllCmd[2]:='strip --strip-unneeded $EXE';
          ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
    -     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
    +     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBGFN $EXE';
          ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
     
          SetupDynlinker(DynamicLinker,libctype);
    @@ -1376,7 +1376,8 @@ var
       i : longint;
       binstr,
       cmdstr,
    -  mapstr : TCmdStr;
    +  mapstr,
    +  workdir : TCmdStr;
       success : boolean;
       DynLinkStr : string;
       GCSectionsStr,
    @@ -1435,13 +1436,14 @@ begin
       { Create external .dbg file with debuginfo }
       if success and (cs_link_separate_dbg_file in current_settings.globalswitches) then
         begin
    +      workdir:=ExtractFilePath(current_module.exefilename);
           for i:=1 to 3 do
             begin
               SplitBinCmd(Info.ExtDbgCmd[i],binstr,cmdstr);
               Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
               Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename)));
               Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename));
    -          success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
    +          success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false,workdir);
               if not success then
                 break;
             end;
    diff --git rtl/objpas/sysutils/osutilsh.inc rtl/objpas/sysutils/osutilsh.inc
    index f7d6bcacca..edf6c49567 100644
    --- rtl/objpas/sysutils/osutilsh.inc
    +++ rtl/objpas/sysutils/osutilsh.inc
    @@ -30,9 +30,9 @@ Function GetEnvironmentVariableCount : Integer;
     {$IFDEF HAS_SLEEP}
     procedure Sleep(milliseconds: Cardinal);
     {$ENDIF}
    -function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
    +function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[];Const WorkDir: RawByteString = ''):integer;
     function ExecuteProcess(Const Path: RawByteString; Const ComLine: Array of RawByteString;Flags:TExecuteFlags=[]):integer;
    -function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
    +function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[];Const WorkDir: UnicodeString = ''):integer;
     function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
     
     Function GetTempDir(Global : Boolean) : String;
    diff --git rtl/objpas/sysutils/sysutils.inc rtl/objpas/sysutils/sysutils.inc
    index 1a687ae97a..7a601a485f 100644
    --- rtl/objpas/sysutils/sysutils.inc
    +++ rtl/objpas/sysutils/sysutils.inc
    @@ -783,9 +783,9 @@ end;
     
     // OSes that only provide 1 byte versions can enable the following define
     {$ifdef executeprocuni}
    -function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
    +function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[];Const WorkDir: UnicodeString = ''):integer;
     begin
    -  result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ToSingleByteFileSystemEncodedFileName(ComLine));
    +  result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ToSingleByteFileSystemEncodedFileName(ComLine), Flags, ToSingleByteFileSystemEncodedFileName(WorkDir));
     end;
     
     function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
    diff --git rtl/unix/sysutils.pp rtl/unix/sysutils.pp
    index 29d64d081f..c54cf8046a 100644
    --- rtl/unix/sysutils.pp
    +++ rtl/unix/sysutils.pp
    @@ -1325,7 +1325,7 @@ begin
     end;
     
     
    -function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
    +function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[];Const WorkDir: RawByteString = ''):integer;
     var
       pid    : longint;
       e      : EOSError;
    @@ -1370,6 +1370,7 @@ Begin
       if pid=0 then
        begin
        {The child does the actual exec, and then exits}
    +      if Length(WorkDir) > 0 then fpChdir(WorkDir);
           fpexecv(pchar(pointer(LPath)),Cmdline2);
          { If the execve fails, we return an exitvalue of 127, to let it be known}
          fpExit(127);
    @@ -1385,8 +1386,7 @@ Begin
       { We're in the parent, let's wait. }
       result:=WaitProcess(pid); // WaitPid and result-convert
     
    -  if Comline<>'' Then
    -    freemem(cmdline2);
    +  freemem(cmdline2);
     
       if (result<0) or (result=127) then
         begin
    diff --git rtl/win/sysutils.pp rtl/win/sysutils.pp
    index e7e8979f05..7c2d53355a 100644
    --- rtl/win/sysutils.pp
    +++ rtl/win/sysutils.pp
    @@ -1256,13 +1256,13 @@ end;
     
     {$pop}
     
    -function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
    +function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[];Const WorkDir: RawByteString = ''):integer;
     begin
    -  result:=ExecuteProcess(Unicodestring(Path),UnicodeString(ComLine),Flags);
    +  result:=ExecuteProcess(Unicodestring(Path),UnicodeString(ComLine),Flags,UnicodeString(WorkDir));
     end;
     
     
    -function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
    +function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[];Const WorkDir: UnicodeString = ''):integer;
     // win specific  function
     var
       SI: TStartupInfoW;
    @@ -1272,7 +1272,9 @@ var
       CommandLine : unicodestring;
       e : EOSError;
       ExecInherits : longbool;
    +  pWorkDir : pwidechar;
     begin
    +  pWorkDir:=NIL;
       FillChar(SI, SizeOf(SI), 0);
       SI.cb:=SizeOf(SI);
       SI.wShowWindow:=1;
    @@ -1289,6 +1291,9 @@ begin
         CommandLine:=Commandline+' '+ComLine+#0
       else
         CommandLine := CommandLine + #0;
    +    
    +  if Length(WorkDir) > 0 then
    +    pWorkDir:=pwidechar(WorkDir);
     
       ExecInherits:=ExecInheritsHandles in Flags;
     
    
  • t_linux.pas.diff (1,026 bytes)
    diff --git compiler/systems/t_linux.pas compiler/systems/t_linux.pas
    index 105a4ba82e..56fee55dbd 100644
    --- compiler/systems/t_linux.pas
    +++ compiler/systems/t_linux.pas
    @@ -389,7 +389,7 @@ begin
          DllCmd[1]:=DllCmd[1]+' $RES';
          DllCmd[2]:='strip --strip-unneeded $EXE';
          ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
    -     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
    +     ExtDbgCmd[2]:='objcopy "--add-gnu-debuglink=$DBG2" $EXE';
          ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
     
          SetupDynlinker(DynamicLinker,libctype);
    @@ -1441,6 +1441,7 @@ begin
               Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
               Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename)));
               Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename));
    +          Replace(cmdstr,'$DBG2',current_module.dbgfilename);
               success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
               if not success then
                 break;
    
    t_linux.pas.diff (1,026 bytes)
  • full output.txt.zip (18,341 bytes)
  • t_linux2.pas.diff (1,063 bytes)
    diff --git compiler/systems/t_linux.pas compiler/systems/t_linux.pas
    index 105a4ba82e..0d3e111d6d 100644
    --- compiler/systems/t_linux.pas
    +++ compiler/systems/t_linux.pas
    @@ -389,7 +389,7 @@ begin
          DllCmd[1]:=DllCmd[1]+' $RES';
          DllCmd[2]:='strip --strip-unneeded $EXE';
          ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
    -     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
    +     ExtDbgCmd[2]:='objcopy "--add-gnu-debuglink=$DBGX" $EXE';
          ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
     
          SetupDynlinker(DynamicLinker,libctype);
    @@ -1440,6 +1440,7 @@ begin
               SplitBinCmd(Info.ExtDbgCmd[i],binstr,cmdstr);
               Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
               Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename)));
    +          Replace(cmdstr,'$DBGX',current_module.dbgfilename);
               Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename));
               success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
               if not success then
    
    t_linux2.pas.diff (1,063 bytes)

Activities

Cyrax

2019-04-05 17:08

reporter  

fix_objcopy_execution.diff (9,335 bytes)
diff --git compiler/cfileutl.pas compiler/cfileutl.pas
index de6991e73e..012b536b5c 100644
--- compiler/cfileutl.pas
+++ compiler/cfileutl.pas
@@ -133,7 +133,7 @@ interface
     procedure DoneFileUtils;
 
     function UnixRequoteWithDoubleQuotes(const QuotedStr: TCmdStr): TCmdStr;
-    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; Flags: TExecuteFlags = []): Longint;
+    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; const WorkDir: AnsiString = ''; Flags: TExecuteFlags = []): Longint;
     function RequotedExecuteProcess(const Path: AnsiString; const ComLine: array of AnsiString; Flags: TExecuteFlags = []): Longint;
     function Shell(const command:ansistring): longint;
 
@@ -574,7 +574,7 @@ end;
 {$endif unix}
      end;
 
-    Function FileExists ( Const F : TCmdStr;allowcache:boolean) : Boolean;
+    function FileExists(const F: TCmdStr; allowcache: boolean): Boolean;
       begin
 {$ifdef usedircache}
         if allowcache then
@@ -676,7 +676,7 @@ end;
       end;
 
 
-    Function PathExists (const F : TCmdStr;allowcache:boolean) : Boolean;
+    function PathExists(const F: TCmdStr; allowcache: boolean): Boolean;
       Var
         i: longint;
         hs : TCmdStr;
@@ -700,7 +700,7 @@ end;
       end;
 
 
-    Function RemoveDir(d:TCmdStr):boolean;
+    function RemoveDir(d: TCmdStr): boolean;
       begin
         if d[length(d)]=source_info.DirSep then
          Delete(d,length(d),1);
@@ -711,7 +711,7 @@ end;
       end;
 
 
-    Function FixPath(const s:TCmdStr;allowdot:boolean):TCmdStr;
+    function FixPath(const s: TCmdStr; allowdot: boolean): TCmdStr;
       var
         i, L : longint;
         P: PChar;
@@ -912,7 +912,7 @@ end;
      end;
 
 
-    Function TargetFixPath(s:TCmdStr;allowdot:boolean):TCmdStr;
+    function TargetFixPath(s: TCmdStr; allowdot: boolean): TCmdStr;
       var
         i : longint;
       begin
@@ -1525,7 +1525,7 @@ end;
       end;
 
 
-    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; Flags: TExecuteFlags): Longint;
+    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; const WorkDir: AnsiString; Flags: TExecuteFlags): Longint;
       var
         quote_script: tscripttype;
       begin
@@ -1538,9 +1538,9 @@ end;
         else
           quote_script:=source_info.script;
         if quote_script=script_unix then
-          result:=sysutils.ExecuteProcess(Path,UnixRequoteWithDoubleQuotes(ComLine),Flags)
+          result:=sysutils.ExecuteProcess(Path,UnixRequoteWithDoubleQuotes(ComLine), WorkDir,Flags)
         else
-          result:=sysutils.ExecuteProcess(Path,ComLine,Flags)
+          result:=sysutils.ExecuteProcess(Path,ComLine, WorkDir,Flags)
       end;
 
 
diff --git compiler/link.pas compiler/link.pas
index 887a5f1ebd..82666fe2d7 100644
--- compiler/link.pas
+++ compiler/link.pas
@@ -75,6 +75,8 @@ interface
          function  ReOrderEntries : boolean;
        end;
 
+      { TExternalLinker }
+
       TExternalLinker = class(TLinker)
       public
          Info : TLinkerInfo;
@@ -82,7 +84,7 @@ interface
          Destructor Destroy;override;
          Function  FindUtil(const s:TCmdStr):TCmdStr;
          Function  CatFileContent(para:TCmdStr):TCmdStr;
-         Function  DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
+         Function  DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean;workdir:TCmdStr=''):boolean;
          procedure SetDefaultInfo;virtual;
          Function  MakeStaticLibrary:boolean;override;
        end;
@@ -619,7 +621,7 @@ Implementation
                               TEXTERNALLINKER
 *****************************************************************************}
 
-    Constructor TExternalLinker.Create;
+    constructor TExternalLinker.Create;
       begin
         inherited Create;
         { set generic defaults }
@@ -647,18 +649,18 @@ Implementation
       end;
 
 
-    Destructor TExternalLinker.Destroy;
+    destructor TExternalLinker.Destroy;
       begin
         inherited destroy;
       end;
 
 
-    Procedure TExternalLinker.SetDefaultInfo;
+    procedure TExternalLinker.SetDefaultInfo;
       begin
       end;
 
 
-    Function TExternalLinker.FindUtil(const s:TCmdStr):TCmdStr;
+    function TExternalLinker.FindUtil(const s: TCmdStr): TCmdStr;
       var
         Found    : boolean;
         FoundBin : TCmdStr;
@@ -688,7 +690,7 @@ Implementation
       end;
 
 
-    Function TExternalLinker.CatFileContent(para : TCmdStr) : TCmdStr;
+    function TExternalLinker.CatFileContent(para: TCmdStr): TCmdStr;
       var
         filecontent : TCmdStr;
         f : text;
@@ -722,7 +724,7 @@ Implementation
         CatFileContent:=filecontent;
       end;
 
-    Function TExternalLinker.DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
+    function TExternalLinker.DoExec(const command: TCmdStr; para: TCmdStr; showinfo, useshell: boolean; workdir: TCmdStr): boolean;
       var
         exitcode: longint;
       begin
@@ -734,7 +736,7 @@ Implementation
              exitcode:=shell(maybequoted(command)+' '+para)
            else
              try
-               exitcode:=RequotedExecuteProcess(command,para);
+               exitcode:=RequotedExecuteProcess(command,para, workdir);
              except on E:EOSError do
                begin
                  Message(exec_e_cant_call_linker);
@@ -765,7 +767,7 @@ Implementation
       end;
 
 
-    Function TExternalLinker.MakeStaticLibrary:boolean;
+    function TExternalLinker.MakeStaticLibrary: boolean;
 
         function GetNextFiles(const maxCmdLength : Longint; var item : TCmdStrListItem; const addfilecmd : string) : TCmdStr;
           begin
diff --git compiler/systems/t_linux.pas compiler/systems/t_linux.pas
index 105a4ba82e..e9d42432f8 100644
--- compiler/systems/t_linux.pas
+++ compiler/systems/t_linux.pas
@@ -389,7 +389,7 @@ begin
      DllCmd[1]:=DllCmd[1]+' $RES';
      DllCmd[2]:='strip --strip-unneeded $EXE';
      ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
-     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
+     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBGFN $EXE';
      ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
 
      SetupDynlinker(DynamicLinker,libctype);
@@ -1376,7 +1376,8 @@ var
   i : longint;
   binstr,
   cmdstr,
-  mapstr : TCmdStr;
+  mapstr,
+  workdir : TCmdStr;
   success : boolean;
   DynLinkStr : string;
   GCSectionsStr,
@@ -1435,13 +1436,14 @@ begin
   { Create external .dbg file with debuginfo }
   if success and (cs_link_separate_dbg_file in current_settings.globalswitches) then
     begin
+      workdir:=ExtractFilePath(current_module.exefilename);
       for i:=1 to 3 do
         begin
           SplitBinCmd(Info.ExtDbgCmd[i],binstr,cmdstr);
           Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
           Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename)));
           Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename));
-          success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
+          success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false,workdir);
           if not success then
             break;
         end;
diff --git rtl/objpas/sysutils/osutilsh.inc rtl/objpas/sysutils/osutilsh.inc
index f7d6bcacca..6bd7228791 100644
--- rtl/objpas/sysutils/osutilsh.inc
+++ rtl/objpas/sysutils/osutilsh.inc
@@ -30,7 +30,7 @@ Function GetEnvironmentVariableCount : Integer;
 {$IFDEF HAS_SLEEP}
 procedure Sleep(milliseconds: Cardinal);
 {$ENDIF}
-function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
+function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Const WorkDir: RawByteString = '';Flags:TExecuteFlags=[]):integer;
 function ExecuteProcess(Const Path: RawByteString; Const ComLine: Array of RawByteString;Flags:TExecuteFlags=[]):integer;
 function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
 function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
diff --git rtl/unix/sysutils.pp rtl/unix/sysutils.pp
index 29d64d081f..9b81f9ad77 100644
--- rtl/unix/sysutils.pp
+++ rtl/unix/sysutils.pp
@@ -1325,7 +1325,7 @@ begin
 end;
 
 
-function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
+function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Const WorkDir: RawByteString;Flags:TExecuteFlags=[]):integer;
 var
   pid    : longint;
   e      : EOSError;
@@ -1370,6 +1370,7 @@ Begin
   if pid=0 then
    begin
    {The child does the actual exec, and then exits}
+      if Length(WorkDir) > 0 then fpChdir(WorkDir);
       fpexecv(pchar(pointer(LPath)),Cmdline2);
      { If the execve fails, we return an exitvalue of 127, to let it be known}
      fpExit(127);
@@ -1385,8 +1386,7 @@ Begin
   { We're in the parent, let's wait. }
   result:=WaitProcess(pid); // WaitPid and result-convert
 
-  if Comline<>'' Then
-    freemem(cmdline2);
+  freemem(cmdline2);
 
   if (result<0) or (result=127) then
     begin

Marco van de Voort

2019-04-11 14:18

manager   ~0115425

Last edited: 2019-04-11 14:18

View 2 revisions

Changing working dir is IMHO bad form. Procedures shouldn't change such global state.

Cyrax

2019-04-11 16:04

reporter   ~0115428

What I understand about fork and execv commands that parent process current (working) directory shouldn't change at all. Thus compiler should be safe.

Cyrax

2019-04-12 06:22

reporter  

fix_objcopy_execution2.diff (11,965 bytes)
diff --git compiler/cfileutl.pas compiler/cfileutl.pas
index de6991e73e..2104c1dca6 100644
--- compiler/cfileutl.pas
+++ compiler/cfileutl.pas
@@ -133,7 +133,7 @@ interface
     procedure DoneFileUtils;
 
     function UnixRequoteWithDoubleQuotes(const QuotedStr: TCmdStr): TCmdStr;
-    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; Flags: TExecuteFlags = []): Longint;
+    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; const WorkDir: AnsiString = ''; Flags: TExecuteFlags = []): Longint;
     function RequotedExecuteProcess(const Path: AnsiString; const ComLine: array of AnsiString; Flags: TExecuteFlags = []): Longint;
     function Shell(const command:ansistring): longint;
 
@@ -574,7 +574,7 @@ end;
 {$endif unix}
      end;
 
-    Function FileExists ( Const F : TCmdStr;allowcache:boolean) : Boolean;
+    function FileExists(const F: TCmdStr; allowcache: boolean): Boolean;
       begin
 {$ifdef usedircache}
         if allowcache then
@@ -676,7 +676,7 @@ end;
       end;
 
 
-    Function PathExists (const F : TCmdStr;allowcache:boolean) : Boolean;
+    function PathExists(const F: TCmdStr; allowcache: boolean): Boolean;
       Var
         i: longint;
         hs : TCmdStr;
@@ -700,7 +700,7 @@ end;
       end;
 
 
-    Function RemoveDir(d:TCmdStr):boolean;
+    function RemoveDir(d: TCmdStr): boolean;
       begin
         if d[length(d)]=source_info.DirSep then
          Delete(d,length(d),1);
@@ -711,7 +711,7 @@ end;
       end;
 
 
-    Function FixPath(const s:TCmdStr;allowdot:boolean):TCmdStr;
+    function FixPath(const s: TCmdStr; allowdot: boolean): TCmdStr;
       var
         i, L : longint;
         P: PChar;
@@ -912,7 +912,7 @@ end;
      end;
 
 
-    Function TargetFixPath(s:TCmdStr;allowdot:boolean):TCmdStr;
+    function TargetFixPath(s: TCmdStr; allowdot: boolean): TCmdStr;
       var
         i : longint;
       begin
@@ -1525,7 +1525,7 @@ end;
       end;
 
 
-    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; Flags: TExecuteFlags): Longint;
+    function RequotedExecuteProcess(const Path: AnsiString; const ComLine: AnsiString; const WorkDir: AnsiString; Flags: TExecuteFlags): Longint;
       var
         quote_script: tscripttype;
       begin
@@ -1538,9 +1538,9 @@ end;
         else
           quote_script:=source_info.script;
         if quote_script=script_unix then
-          result:=sysutils.ExecuteProcess(Path,UnixRequoteWithDoubleQuotes(ComLine),Flags)
+          result:=sysutils.ExecuteProcess(Path,UnixRequoteWithDoubleQuotes(ComLine), Flags, WorkDir)
         else
-          result:=sysutils.ExecuteProcess(Path,ComLine,Flags)
+          result:=sysutils.ExecuteProcess(Path,ComLine,Flags,WorkDir)
       end;
 
 
diff --git compiler/link.pas compiler/link.pas
index 03432fdf18..094e1e401f 100644
--- compiler/link.pas
+++ compiler/link.pas
@@ -75,6 +75,8 @@ interface
          function  ReOrderEntries : boolean;
        end;
 
+      { TExternalLinker }
+
       TExternalLinker = class(TLinker)
       public
          Info : TLinkerInfo;
@@ -82,7 +84,7 @@ interface
          Destructor Destroy;override;
          Function  FindUtil(const s:TCmdStr):TCmdStr;
          Function  CatFileContent(para:TCmdStr):TCmdStr;
-         Function  DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
+         Function  DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean;workdir:TCmdStr=''):boolean;
          procedure SetDefaultInfo;virtual;
          Function  MakeStaticLibrary:boolean;override;
        end;
@@ -619,7 +621,7 @@ Implementation
                               TEXTERNALLINKER
 *****************************************************************************}
 
-    Constructor TExternalLinker.Create;
+    constructor TExternalLinker.Create;
       begin
         inherited Create;
         { set generic defaults }
@@ -647,18 +649,18 @@ Implementation
       end;
 
 
-    Destructor TExternalLinker.Destroy;
+    destructor TExternalLinker.Destroy;
       begin
         inherited destroy;
       end;
 
 
-    Procedure TExternalLinker.SetDefaultInfo;
+    procedure TExternalLinker.SetDefaultInfo;
       begin
       end;
 
 
-    Function TExternalLinker.FindUtil(const s:TCmdStr):TCmdStr;
+    function TExternalLinker.FindUtil(const s: TCmdStr): TCmdStr;
       var
         Found    : boolean;
         FoundBin : TCmdStr;
@@ -688,7 +690,7 @@ Implementation
       end;
 
 
-    Function TExternalLinker.CatFileContent(para : TCmdStr) : TCmdStr;
+    function TExternalLinker.CatFileContent(para: TCmdStr): TCmdStr;
       var
         filecontent : TCmdStr;
         f : text;
@@ -722,7 +724,7 @@ Implementation
         CatFileContent:=filecontent;
       end;
 
-    Function TExternalLinker.DoExec(const command:TCmdStr; para:TCmdStr;showinfo,useshell:boolean):boolean;
+    function TExternalLinker.DoExec(const command: TCmdStr; para: TCmdStr; showinfo, useshell: boolean; workdir: TCmdStr): boolean;
       var
         exitcode: longint;
       begin
@@ -734,7 +736,7 @@ Implementation
              exitcode:=shell(maybequoted(command)+' '+para)
            else
              try
-               exitcode:=RequotedExecuteProcess(command,para);
+               exitcode:=RequotedExecuteProcess(command,para, workdir);
              except on E:EOSError do
                begin
                  Message(exec_e_cant_call_linker);
@@ -765,7 +767,7 @@ Implementation
       end;
 
 
-    Function TExternalLinker.MakeStaticLibrary:boolean;
+    function TExternalLinker.MakeStaticLibrary: boolean;
 
         function GetNextFiles(const maxCmdLength : Longint; var item : TCmdStrListItem; const addfilecmd : string) : TCmdStr;
           begin
diff --git compiler/systems/t_linux.pas compiler/systems/t_linux.pas
index 105a4ba82e..e9d42432f8 100644
--- compiler/systems/t_linux.pas
+++ compiler/systems/t_linux.pas
@@ -389,7 +389,7 @@ begin
      DllCmd[1]:=DllCmd[1]+' $RES';
      DllCmd[2]:='strip --strip-unneeded $EXE';
      ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
-     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
+     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBGFN $EXE';
      ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
 
      SetupDynlinker(DynamicLinker,libctype);
@@ -1376,7 +1376,8 @@ var
   i : longint;
   binstr,
   cmdstr,
-  mapstr : TCmdStr;
+  mapstr,
+  workdir : TCmdStr;
   success : boolean;
   DynLinkStr : string;
   GCSectionsStr,
@@ -1435,13 +1436,14 @@ begin
   { Create external .dbg file with debuginfo }
   if success and (cs_link_separate_dbg_file in current_settings.globalswitches) then
     begin
+      workdir:=ExtractFilePath(current_module.exefilename);
       for i:=1 to 3 do
         begin
           SplitBinCmd(Info.ExtDbgCmd[i],binstr,cmdstr);
           Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
           Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename)));
           Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename));
-          success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
+          success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false,workdir);
           if not success then
             break;
         end;
diff --git rtl/objpas/sysutils/osutilsh.inc rtl/objpas/sysutils/osutilsh.inc
index f7d6bcacca..edf6c49567 100644
--- rtl/objpas/sysutils/osutilsh.inc
+++ rtl/objpas/sysutils/osutilsh.inc
@@ -30,9 +30,9 @@ Function GetEnvironmentVariableCount : Integer;
 {$IFDEF HAS_SLEEP}
 procedure Sleep(milliseconds: Cardinal);
 {$ENDIF}
-function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
+function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[];Const WorkDir: RawByteString = ''):integer;
 function ExecuteProcess(Const Path: RawByteString; Const ComLine: Array of RawByteString;Flags:TExecuteFlags=[]):integer;
-function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
+function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[];Const WorkDir: UnicodeString = ''):integer;
 function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
 
 Function GetTempDir(Global : Boolean) : String;
diff --git rtl/objpas/sysutils/sysutils.inc rtl/objpas/sysutils/sysutils.inc
index 1a687ae97a..7a601a485f 100644
--- rtl/objpas/sysutils/sysutils.inc
+++ rtl/objpas/sysutils/sysutils.inc
@@ -783,9 +783,9 @@ end;
 
 // OSes that only provide 1 byte versions can enable the following define
 {$ifdef executeprocuni}
-function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
+function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[];Const WorkDir: UnicodeString = ''):integer;
 begin
-  result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ToSingleByteFileSystemEncodedFileName(ComLine));
+  result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ToSingleByteFileSystemEncodedFileName(ComLine), Flags, ToSingleByteFileSystemEncodedFileName(WorkDir));
 end;
 
 function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
diff --git rtl/unix/sysutils.pp rtl/unix/sysutils.pp
index 29d64d081f..c54cf8046a 100644
--- rtl/unix/sysutils.pp
+++ rtl/unix/sysutils.pp
@@ -1325,7 +1325,7 @@ begin
 end;
 
 
-function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
+function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[];Const WorkDir: RawByteString = ''):integer;
 var
   pid    : longint;
   e      : EOSError;
@@ -1370,6 +1370,7 @@ Begin
   if pid=0 then
    begin
    {The child does the actual exec, and then exits}
+      if Length(WorkDir) > 0 then fpChdir(WorkDir);
       fpexecv(pchar(pointer(LPath)),Cmdline2);
      { If the execve fails, we return an exitvalue of 127, to let it be known}
      fpExit(127);
@@ -1385,8 +1386,7 @@ Begin
   { We're in the parent, let's wait. }
   result:=WaitProcess(pid); // WaitPid and result-convert
 
-  if Comline<>'' Then
-    freemem(cmdline2);
+  freemem(cmdline2);
 
   if (result<0) or (result=127) then
     begin
diff --git rtl/win/sysutils.pp rtl/win/sysutils.pp
index e7e8979f05..7c2d53355a 100644
--- rtl/win/sysutils.pp
+++ rtl/win/sysutils.pp
@@ -1256,13 +1256,13 @@ end;
 
 {$pop}
 
-function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
+function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[];Const WorkDir: RawByteString = ''):integer;
 begin
-  result:=ExecuteProcess(Unicodestring(Path),UnicodeString(ComLine),Flags);
+  result:=ExecuteProcess(Unicodestring(Path),UnicodeString(ComLine),Flags,UnicodeString(WorkDir));
 end;
 
 
-function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
+function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[];Const WorkDir: UnicodeString = ''):integer;
 // win specific  function
 var
   SI: TStartupInfoW;
@@ -1272,7 +1272,9 @@ var
   CommandLine : unicodestring;
   e : EOSError;
   ExecInherits : longbool;
+  pWorkDir : pwidechar;
 begin
+  pWorkDir:=NIL;
   FillChar(SI, SizeOf(SI), 0);
   SI.cb:=SizeOf(SI);
   SI.wShowWindow:=1;
@@ -1289,6 +1291,9 @@ begin
     CommandLine:=Commandline+' '+ComLine+#0
   else
     CommandLine := CommandLine + #0;
+    
+  if Length(WorkDir) > 0 then
+    pWorkDir:=pwidechar(WorkDir);
 
   ExecInherits:=ExecInheritsHandles in Flags;
 

Cyrax

2019-04-12 06:23

reporter   ~0115434

Attached updated patch (fix_objcopy_execution2.diff).

Sven Barth

2019-04-14 20:25

manager   ~0115502

I don't agree with changing the working directory either.

I tested a bit with -sh and using 'objcopy "--add-gnu-debuglink=$DBG" $EXE' with DBG *not* being passed to maybequoted() should work correctly.

By the way: in the future please don't include unrelated changes in a patch.

Cyrax

2019-04-15 05:47

reporter   ~0115514

Sorry for the noise at the patch. I will try be more careful next time.

---

Changing compiler/systems/t_linux.pas back to original and then applying Sven's suggestion as slightly modified : 'objcopy "--add-gnu-debuglink=$DBG2" $EXE'

$DBG2 will be replaced with non quoted filename.

But it didn't work. :-(

See attached, updated patch for more info about

---

Output from Lazarus message window:

Hint: (11030) Start of reading config file /mnt/shares/ohjelmointi2/fpc/i386/trunk/3.3.1/binary/trunk/bin/i386-linux/fpc.cfg
Hint: (11031) End of reading config file /mnt/shares/ohjelmointi2/fpc/i386/trunk/3.3.1/binary/trunk/bin/i386-linux/fpc.cfg
Hint: (11030) Start of reading config file /mnt/shares/ohjelmointi2/fpc/i386/trunk/3.3.1/binary/trunk/bin/i386-linux/fpc_unit_locations.cfg
Hint: (11031) End of reading config file /mnt/shares/ohjelmointi2/fpc/i386/trunk/3.3.1/binary/trunk/bin/i386-linux/fpc_unit_locations.cfg
Free Pascal Compiler version 3.3.1-r41871 [2019/04/15] for i386
Copyright (c) 1993-2018 by Florian Klaempfl and others
Note: (11020) Switching assembler to default source writing assembler
(1002) Target OS: Linux for i386
(3104) Compiling project1.lpr
/mnt/shares/ohjelmointi/32-bit/kielet/pascal/free_pascal/lazarus/projects/research bugs/fpc/bugs 12/fpc objcopy bug 00/project1.lpr(15,1) Note: tgobj: (ResetTempGen) all temps freed
(9009) Assembling project1
(9015) Linking /mnt/shares/ohjelmointi/32-bit/kielet/pascal/free_pascal/lazarus/projects/research bugs/fpc/bugs 12/fpc objcopy bug 00/bin/i386-linux-Default_debug1-30301/project1
Usage: /usr/bin/objcopy [option(s)] in-file [out-file]
 Copies a binary file, possibly transforming it in the process
 The options are:
  -I --input-target <bfdname>      Assume input file is in format <bfdname>
  -O --output-target <bfdname>     Create an output file in format <bfdname>
  -B --binary-architecture <arch>  Set output arch, when input is arch-less
  -F --target <bfdname>            Set both input and output format to <bfdname>
     --debugging                   Convert debugging information, if possible
  -p --preserve-dates              Copy modified/access timestamps to the output
  -D --enable-deterministic-archives
                                   Produce deterministic output when stripping archives (default)
  -U --disable-deterministic-archives
                                   Disable -D behavior
  -j --only-section <name>         Only copy section <name> into the output
     --add-gnu-debuglink=<file>    Add section .gnu_debuglink linking to <file>
  -R --remove-section <name>       Remove section <name> from the output
     --remove-relocations <name>   Remove relocations from section <name>
  -S --strip-all                   Remove all symbol and relocation information
  -g --strip-debug                 Remove all debugging symbols & sections
     --strip-dwo                   Remove all DWO sections
     --strip-unneeded              Remove all symbols not needed by relocations
  -N --strip-symbol <name>         Do not copy symbol <name>
     --strip-unneeded-symbol <name>
                                   Do not copy symbol <name> unless needed by
                                     relocations
     --only-keep-debug             Strip everything but the debug information
     --extract-dwo                 Copy only DWO sections
     --extract-symbol              Remove section contents but keep symbols
  -K --keep-symbol <name>          Do not strip symbol <name>
     --keep-file-symbols           Do not strip file symbol(s)
     --localize-hidden             Turn all ELF hidden symbols into locals
  -L --localize-symbol <name>      Force symbol <name> to be marked as a local
     --globalize-symbol <name>     Force symbol <name> to be marked as a global
  -G --keep-global-symbol <name>   Localize all symbols except <name>
  -W --weaken-symbol <name>        Force symbol <name> to be marked as a weak
     --weaken                      Force all global symbols to be marked as weak
  -w --wildcard                    Permit wildcard in symbol comparison
  -x --discard-all                 Remove all non-global symbols
  -X --discard-locals              Remove any compiler-generated symbols
  -i --interleave[=<number>]       Only copy N out of every <number> bytes
     --interleave-width <number>   Set N for --interleave
  -b --byte <num>                  Select byte <num> in every interleaved block
     --gap-fill <val>              Fill gaps between sections with <val>
     --pad-to <addr>               Pad the last section up to address <addr>
     --set-start <addr>            Set the start address to <addr>
    {--change-start|--adjust-start} <incr>
                                   Add <incr> to the start address
    {--change-addresses|--adjust-vma} <incr>
                                   Add <incr> to LMA, VMA and start addresses
    {--change-section-address|--adjust-section-vma} <name>{=|+|-}<val>
                                   Change LMA and VMA of section <name> by <val>
     --change-section-lma <name>{=|+|-}<val>
                                   Change the LMA of section <name> by <val>
     --change-section-vma <name>{=|+|-}<val>
                                   Change the VMA of section <name> by <val>
    {--[no-]change-warnings|--[no-]adjust-warnings}
                                   Warn if a named section does not exist
     --set-section-flags <name>=<flags>
                                   Set section <name>'s properties to <flags>
     --add-section <name>=<file>   Add section <name> found in <file> to output
     --update-section <name>=<file>
                                   Update contents of section <name> with
                                   contents found in <file>
     --dump-section <name>=<file>  Dump the contents of section <name> into <file>
     --rename-section <old>=<new>[,<flags>] Rename section <old> to <new>
     --long-section-names {enable|disable|keep}
                                   Handle long section names in Coff objects.
     --change-leading-char         Force output format's leading character style
     --remove-leading-char         Remove leading character from global symbols
     --reverse-bytes=<num>         Reverse <num> bytes at a time, in output sections with content
     --redefine-sym <old>=<new>    Redefine symbol name <old> to <new>
     --redefine-syms <file>        --redefine-sym for all symbol pairs 
                                     listed in <file>
     --srec-len <number>           Restrict the length of generated Srecords
     --srec-forceS3                Restrict the type of generated Srecords to S3
     --strip-symbols <file>        -N for all symbols listed in <file>
     --strip-unneeded-symbols <file>
                                   --strip-unneeded-symbol for all symbols listed
                                     in <file>
     --keep-symbols <file>         -K for all symbols listed in <file>
     --localize-symbols <file>     -L for all symbols listed in <file>
     --globalize-symbols <file>    --globalize-symbol for all in <file>
     --keep-global-symbols <file>  -G for all symbols listed in <file>
     --weaken-symbols <file>       -W for all symbols listed in <file>
     --add-symbol <name>=[<section>:]<value>[,<flags>]  Add a symbol
     --alt-machine-code <index>    Use the target's <index>'th alternative machine
     --writable-text               Mark the output text as writable
     --readonly-text               Make the output text write protected
     --pure                        Mark the output file as demand paged
     --impure                      Mark the output file as impure
     --prefix-symbols <prefix>     Add <prefix> to start of every symbol name
     --prefix-sections <prefix>    Add <prefix> to start of every section name
     --prefix-alloc-sections <prefix>
                                   Add <prefix> to start of every allocatable
                                     section name
     --file-alignment <num>        Set PE file alignment to <num>
     --heap <reserve>[,<commit>]   Set PE reserve/commit heap to <reserve>/
                                   <commit>
     --image-base <address>        Set PE image base to <address>
     --section-alignment <num>     Set PE section alignment to <num>
     --stack <reserve>[,<commit>]  Set PE reserve/commit stack to <reserve>/
                                   <commit>
     --subsystem <name>[:<version>]
                                   Set PE subsystem to <name> [& <version>]
     --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]
                                   Compress DWARF debug sections using zlib
     --decompress-debug-sections   Decompress DWARF debug sections using zlib
     --elf-stt-common=[yes|no]     Generate ELF common symbols with STT_COMMON
                                     type
  -M  --merge-notes                Remove redundant entries in note sections
      --no-merge-notes             Do not attempt to remove redundant notes (default)
  -v --verbose                     List all object files modified
  @<file>                          Read options from <file>
  -V --version                     Display this program's version number
  -h --help                        Display this output
     --info                        List object formats & architectures supported
/usr/bin/objcopy: supported targets: elf32-i386 elf32-iamcu pei-i386 elf64-x86-64 elf32-x86-64 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 plugin srec symbolsrec verilog tekhex binary ihex trad-core
Error: (9013) Error while linking
Fatal: (10026) There were 1 errors compiling module, stopping
Fatal: (1018) Compilation aborted
Error: /mnt/shares/ohjelmointi2/fpc/i386/trunk/3.3.1/binary/trunk/bin/i386-linux/ppc386 returned an error exitcode


---

objcopy version:

GNU objcopy (GNU Binutils) 2.31.1
Copyright (C) 2018 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.

Cyrax

2019-04-15 05:49

reporter  

t_linux.pas.diff (1,026 bytes)
diff --git compiler/systems/t_linux.pas compiler/systems/t_linux.pas
index 105a4ba82e..56fee55dbd 100644
--- compiler/systems/t_linux.pas
+++ compiler/systems/t_linux.pas
@@ -389,7 +389,7 @@ begin
      DllCmd[1]:=DllCmd[1]+' $RES';
      DllCmd[2]:='strip --strip-unneeded $EXE';
      ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
-     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
+     ExtDbgCmd[2]:='objcopy "--add-gnu-debuglink=$DBG2" $EXE';
      ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
 
      SetupDynlinker(DynamicLinker,libctype);
@@ -1441,6 +1441,7 @@ begin
           Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
           Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename)));
           Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename));
+          Replace(cmdstr,'$DBG2',current_module.dbgfilename);
           success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
           if not success then
             break;
t_linux.pas.diff (1,026 bytes)

Cyrax

2019-04-15 05:55

reporter   ~0115515

Huh, Replace doesn't understand numbers.

Cyrax

2019-04-15 06:09

reporter  

full output.txt.zip (18,341 bytes)

Cyrax

2019-04-15 06:10

reporter   ~0115516

Attached compiler output by using -va option.

Cyrax

2019-04-15 06:40

reporter   ~0115517

Mystery solved, Replace just does what it is told to do and doesn't do any checks. Will attach updated patch later.

Cyrax

2019-04-15 10:30

reporter  

t_linux2.pas.diff (1,063 bytes)
diff --git compiler/systems/t_linux.pas compiler/systems/t_linux.pas
index 105a4ba82e..0d3e111d6d 100644
--- compiler/systems/t_linux.pas
+++ compiler/systems/t_linux.pas
@@ -389,7 +389,7 @@ begin
      DllCmd[1]:=DllCmd[1]+' $RES';
      DllCmd[2]:='strip --strip-unneeded $EXE';
      ExtDbgCmd[1]:='objcopy --only-keep-debug $EXE $DBG';
-     ExtDbgCmd[2]:='objcopy --add-gnu-debuglink=$DBG $EXE';
+     ExtDbgCmd[2]:='objcopy "--add-gnu-debuglink=$DBGX" $EXE';
      ExtDbgCmd[3]:='strip --strip-unneeded $EXE';
 
      SetupDynlinker(DynamicLinker,libctype);
@@ -1440,6 +1440,7 @@ begin
           SplitBinCmd(Info.ExtDbgCmd[i],binstr,cmdstr);
           Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
           Replace(cmdstr,'$DBGFN',maybequoted(extractfilename(current_module.dbgfilename)));
+          Replace(cmdstr,'$DBGX',current_module.dbgfilename);
           Replace(cmdstr,'$DBG',maybequoted(current_module.dbgfilename));
           success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,false);
           if not success then
t_linux2.pas.diff (1,063 bytes)

Cyrax

2019-04-15 10:30

reporter   ~0115518

Attached the updated patch.

Cyrax

2019-05-05 06:59

reporter   ~0116020

Bump.
Is new patch (t_linux2.pas.diff ) correct solution for this bug? If it's, please apply it.

Sven Barth

2019-05-10 15:00

manager   ~0116117

Patch applied. Thank you.

Please test and close if okay.

Issue History

Date Modified Username Field Change
2019-04-05 17:08 Cyrax New Issue
2019-04-05 17:08 Cyrax File Added: fix_objcopy_execution.diff
2019-04-11 14:18 Marco van de Voort Note Added: 0115425
2019-04-11 14:18 Marco van de Voort Note Edited: 0115425 View Revisions
2019-04-11 16:05 Cyrax Note Added: 0115428
2019-04-12 06:22 Cyrax File Added: fix_objcopy_execution2.diff
2019-04-12 06:23 Cyrax Note Added: 0115434
2019-04-14 20:25 Sven Barth Note Added: 0115502
2019-04-15 05:47 Cyrax Note Added: 0115514
2019-04-15 05:49 Cyrax File Added: t_linux.pas.diff
2019-04-15 05:55 Cyrax Note Added: 0115515
2019-04-15 06:09 Cyrax File Added: full output.txt.zip
2019-04-15 06:10 Cyrax Note Added: 0115516
2019-04-15 06:40 Cyrax Note Added: 0115517
2019-04-15 10:30 Cyrax File Added: t_linux2.pas.diff
2019-04-15 10:30 Cyrax Note Added: 0115518
2019-05-05 06:59 Cyrax Note Added: 0116020
2019-05-10 15:00 Sven Barth Assigned To => Sven Barth
2019-05-10 15:00 Sven Barth Status new => resolved
2019-05-10 15:00 Sven Barth Resolution open => fixed
2019-05-10 15:00 Sven Barth Fixed in Version => 3.3.1
2019-05-10 15:00 Sven Barth Fixed in Revision => 42025
2019-05-10 15:00 Sven Barth FPCTarget => -
2019-05-10 15:00 Sven Barth Note Added: 0116117