{ $Id$ Copyright (c) 1998-2000 by Peter Vreman This unit implements support import,export,link routines for the (i386) Go32v2 target This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **************************************************************************** } unit t_go32v2; interface uses link; type plinkergo32v2=^tlinkergo32v2; tlinkergo32v2=object(tlinker) private Function WriteResponseFile(isdll:boolean) : Boolean; public constructor Init; procedure SetDefaultInfo;virtual; function MakeExecutable:boolean;virtual; end; implementation uses strings,globtype,globals,cobjects,systems,verbose,script,files; {**************************************************************************** TLinkerGo32v2 ****************************************************************************} Constructor TLinkerGo32v2.Init; begin Inherited Init; { allow duplicated libs (PM) } SharedLibFiles.doubles:=true; StaticLibFiles.doubles:=true; end; procedure TLinkerGo32v2.SetDefaultInfo; begin with Info do begin ExeCmd[1]:='ld -oformat coff-go32-exe $OPT $STRIP -o $EXE @$RES'; end; end; Function TLinkerGo32v2.WriteResponseFile(isdll:boolean) : Boolean; Var linkres : TLinkRes; i : longint; {$IFDEF NEWST} HPath : PStringItem; {$ELSE} HPath : PStringQueueItem; {$ENDIF NEWST} s : string; linklibc : boolean; begin WriteResponseFile:=False; { Open link.res file } LinkRes.Init(outputexedir+Info.ResName); { Write path to search libraries } HPath:=current_module^.locallibrarysearchpath.First; while assigned(HPath) do begin LinkRes.Add('-L'+GetShortName(HPath^.Data^)); HPath:=HPath^.Next; end; HPath:=LibrarySearchPath.First; while assigned(HPath) do begin LinkRes.Add('-L'+GetShortName(HPath^.Data^)); HPath:=HPath^.Next; end; { add objectfiles, start with prt0 always } LinkRes.AddFileName(GetShortName(FindObjectFile('prt0'))); while not ObjectFiles.Empty do begin s:=ObjectFiles.Get; if s<>'' then LinkRes.AddFileName(GetShortName(s)); end; { Write staticlibraries } if not StaticLibFiles.Empty then begin LinkRes.Add('-('); While not StaticLibFiles.Empty do begin S:=StaticLibFiles.Get; LinkRes.AddFileName(GetShortName(s)) end; LinkRes.Add('-)'); end; { Write sharedlibraries like -l, also add the needed dynamic linker here to be sure that it gets linked this is needed for glibc2 systems (PFV) } linklibc:=false; While not SharedLibFiles.Empty do begin S:=SharedLibFiles.Get; if s<>'c' then begin i:=Pos(target_os.sharedlibext,S); if i>0 then Delete(S,i,255); LinkRes.Add('-l'+s); end else begin LinkRes.Add('-l'+s); linklibc:=true; end; end; { be sure that libc&libgcc is the last lib } if linklibc then begin LinkRes.Add('-lc'); LinkRes.Add('-lgcc'); end; { Write and Close response } linkres.writetodisk; linkres.done; WriteResponseFile:=True; end; function TLinkerGo32v2.MakeExecutable:boolean; var binstr, cmdstr : string; success : boolean; StripStr : string[40]; begin if not(cs_link_extern in aktglobalswitches) then Message1(exec_i_linking,current_module^.exefilename^); { Create some replacements } StripStr:=''; if (cs_link_strip in aktglobalswitches) then StripStr:='-s'; { Write used files and libraries } WriteResponseFile(false); { Call linker } SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr); Replace(cmdstr,'$EXE',current_module^.exefilename^); Replace(cmdstr,'$OPT',Info.ExtraOptions); Replace(cmdstr,'$RES',outputexedir+Info.ResName); Replace(cmdstr,'$STRIP',StripStr); success:=DoExec(FindUtil(BinStr),cmdstr,true,false); { Remove ReponseFile } if (success) and not(cs_link_extern in aktglobalswitches) then RemoveFile(outputexedir+Info.ResName); MakeExecutable:=success; { otherwise a recursive call to link method } end; {$ifdef notnecessary} procedure tlinkergo32v2.postprocessexecutable(const n : string); type tcoffheader=packed record mach : word; nsects : word; time : longint; sympos : longint; syms : longint; opthdr : word; flag : word; end; tcoffsechdr=packed record name : array[0..7] of char; vsize : longint; rvaofs : longint; datalen : longint; datapos : longint; relocpos : longint; lineno1 : longint; nrelocs : word; lineno2 : word; flags : longint; end; psecfill=^tsecfill; tsecfill=record fillpos, fillsize : longint; next : psecfill; end; var f : file; coffheader : tcoffheader; firstsecpos, maxfillsize, l : longint; coffsec : tcoffsechdr; secroot,hsecroot : psecfill; zerobuf : pointer; begin { when -s is used quit, because there is no .exe } if cs_link_extern in aktglobalswitches then exit; { open file } assign(f,n); {$I-} reset(f,1); if ioresult<>0 then Message1(execinfo_f_cant_open_executable,n); { read headers } seek(f,2048); blockread(f,coffheader,sizeof(tcoffheader)); { read section info } maxfillsize:=0; firstsecpos:=0; secroot:=nil; for l:=1to coffheader.nSects do begin blockread(f,coffsec,sizeof(tcoffsechdr)); if coffsec.datapos>0 then begin if secroot=nil then firstsecpos:=coffsec.datapos; new(hsecroot); hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize; hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize; hsecroot^.next:=secroot; secroot:=hsecroot; if secroot^.fillsize>maxfillsize then maxfillsize:=secroot^.fillsize; end; end; if firstsecpos>0 then begin l:=firstsecpos-filepos(f); if l>maxfillsize then maxfillsize:=l; end else l:=0; { get zero buffer } getmem(zerobuf,maxfillsize); fillchar(zerobuf^,maxfillsize,0); { zero from sectioninfo until first section } blockwrite(f,zerobuf^,l); { zero section alignments } while assigned(secroot) do begin seek(f,secroot^.fillpos); blockwrite(f,zerobuf^,secroot^.fillsize); hsecroot:=secroot; secroot:=secroot^.next; dispose(hsecroot); end; freemem(zerobuf,maxfillsize); close(f); {$I+} i:=ioresult; postprocessexecutable:=true; end; {$endif} end. { $Log$ Revision 1.10 2000-02-28 17:23:57 daniel * Current work of symtable integration committed. The symtable can be activated by defining 'newst', but doesn't compile yet. Changes in type checking and oop are completed. What is left is to write a new symtablestack and adapt the parser to use it. Revision 1.9 2000/02/09 13:23:06 peter * log truncated Revision 1.8 2000/01/09 00:55:51 pierre * GROUP of smartlink units put before the C libraries to allow for smartlinking code that uses C code. Revision 1.7 2000/01/07 01:14:42 peter * updated copyright to 2000 Revision 1.6 1999/12/06 18:21:04 peter * support !ENVVAR for long commandlines * win32/go32v2 write short pathnames to link.res so c:\Program Files\ is finally supported as installdir. Revision 1.5 1999/11/16 23:39:04 peter * use outputexedir for link.res location Revision 1.4 1999/11/12 11:03:50 peter * searchpaths changed to stringqueue object Revision 1.3 1999/11/04 10:55:31 peter * TSearchPathString for the string type of the searchpaths, which is ansistring under FPC/Delphi Revision 1.2 1999/10/22 14:42:40 peter * reset linklibc Revision 1.1 1999/10/21 14:29:38 peter * redesigned linker object + library support for linux (only procedures can be exported) }