3 Copyright (c) 1998-2000 by Peter Vreman
5 This unit implements support import,export,link routines
6 for the (i386) Linux target
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 ****************************************************************************
31 pimportliblinux
=^timportliblinux
;
32 timportliblinux
=object(timportlib
)
33 procedure preparelib(const s
:string);virtual;
34 procedure importprocedure(const func
,module
:string;index
:longint;const name
:string);virtual;
35 procedure importvariable(const varname
,module
:string;const name
:string);virtual;
36 procedure generatelib
;virtual;
39 pexportliblinux
=^texportliblinux
;
40 texportliblinux
=object(texportlib
)
41 procedure preparelib(const s
: string);virtual;
42 procedure exportprocedure(hp
: pexported_item
);virtual;
43 procedure exportvar(hp
: pexported_item
);virtual;
44 procedure generatelib
;virtual;
47 plinkerlinux
=^tlinkerlinux
;
48 tlinkerlinux
=object(tlinker
)
52 Function WriteResponseFile(isdll
:boolean) : Boolean;
55 procedure SetDefaultInfo
;virtual;
56 function MakeExecutable
:boolean;virtual;
57 function MakeSharedLibrary
:boolean;virtual;
64 verbose
,strings
,cobjects
,systems
,globtype
,globals
,
66 files
,aasm
,cpuasm
,cpubase
,symtable
{$IFDEF NEWST},symbols
{$ENDIF NEWST};
68 {*****************************************************************************
70 *****************************************************************************}
72 procedure timportliblinux
.preparelib(const s
: string);
77 procedure timportliblinux
.importprocedure(const func
,module
: string;index
: longint;const name
: string);
79 { insert sharedlibrary }
81 current_module
^.linkothersharedlibs
.
82 insert(new(Plinkitem
,init(SplitName(module
),link_allways
)));
83 { do nothing with the procedure, only set the mangledname }
85 aktprocdef
^.setmangledname(name
)
87 message(parser_e_empty_import_name
);
89 current_module
^.linkothersharedlibs
.
90 insert(SplitName(module
),link_allways
);
91 { do nothing with the procedure, only set the mangledname }
93 aktprocsym
^.definition
^.setmangledname(name
)
95 message(parser_e_empty_import_name
);
100 procedure timportliblinux
.importvariable(const varname
,module
:string;const name
:string);
102 { insert sharedlibrary }
104 current_module
^.linkothersharedlibs
.
105 insert(new(Plinkitem
,init(SplitName(module
),link_allways
)));
107 current_module
^.linkothersharedlibs
.
108 insert(SplitName(module
),link_allways
);
110 { reset the mangledname and turn off the dll_var option }
111 aktvarsym
^.setmangledname(name
);
113 exclude(aktvarsym
^.properties
,vo_is_dll_var
);
116 exclude(aktvarsym
^.varoptions
,vo_is_dll_var
);
118 aktvarsym
^.varoptions
:=aktvarsym
^.varoptions
-[vo_is_dll_var
];
124 procedure timportliblinux
.generatelib
;
129 {*****************************************************************************
131 *****************************************************************************}
133 procedure texportliblinux
.preparelib(const s
:string);
138 procedure texportliblinux
.exportprocedure(hp
: pexported_item
);
140 hp2
: pexported_item
;
142 { first test the index value }
143 if (hp
^.options
and eo_index
)<>0 then
145 Message1(parser_e_no_export_with_index_for_target
,'linux');
148 { use pascal name is none specified }
149 if (hp
^.options
and eo_name
)=0 then
151 hp
^.name
:=stringdup(hp
^.sym
^.name
);
152 hp
^.options
:=hp
^.options
or eo_name
;
154 { now place in correct order }
155 hp2
:=pexported_item(current_module
^._exports
^.first
);
156 while assigned(hp2
) and
157 (hp
^.name
^>hp2
^.name
^) do
158 hp2
:=pexported_item(hp2
^.next
);
159 { insert hp there !! }
160 if assigned(hp2
) and (hp2
^.name
^=hp
^.name
^) then
162 { this is not allowed !! }
163 Message1(parser_e_export_name_double
,hp
^.name
^);
166 if hp2
=pexported_item(current_module
^._exports
^.first
) then
167 current_module
^._exports
^.insert(hp
)
168 else if assigned(hp2
) then
171 hp
^.previous
:=hp2
^.previous
;
172 if assigned(hp2
^.previous
) then
173 hp2
^.previous
^.next
:=hp
;
177 current_module
^._exports
^.concat(hp
);
181 procedure texportliblinux
.exportvar(hp
: pexported_item
);
188 procedure texportliblinux
.generatelib
;
190 hp2
: pexported_item
;
192 hp2
:=pexported_item(current_module
^._exports
^.first
);
193 while assigned(hp2
) do
195 if not hp2
^.is_var
then
198 { place jump in codesegment }
199 codesegment
^.concat(new(pai_align
,init_op(4,$90)));
200 codesegment
^.concat(new(pai_symbol
,initname_global(hp2
^.name
^,0)));
201 codesegment
^.concat(new(paicpu
,op_sym(A_JMP
,S_NO
,newasmsymbol(hp2
^.sym
^.mangledname
))));
202 codesegment
^.concat(new(pai_symbol_end
,initname(hp2
^.name
^)));
206 Message1(parser_e_no_export_of_variables_for_target
,'linux');
207 hp2
:=pexported_item(hp2
^.next
);
212 {*****************************************************************************
214 *****************************************************************************}
216 Constructor TLinkerLinux
.Init
;
219 LibrarySearchPath
.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
223 procedure TLinkerLinux
.SetDefaultInfo
;
225 This will also detect which libc version will be used
232 ExeCmd
[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
233 DllCmd
[1]:='ld $OPT -shared -L. -o $EXE $RES';
234 DllCmd
[2]:='strip --strip-unneeded $EXE';
236 DynamicLinker
:='/lib/ld-linux.so.2';
237 if FileExists(DynamicLinker
) then
240 { Check for 2.0 files, else use the glibc 2.1 stub }
241 if FileExists('/lib/ld-2.0.*') then
247 DynamicLinker
:='/lib/ld-linux.so.1';
256 Function TLinkerLinux
.WriteResponseFile(isdll
:boolean) : Boolean;
266 HPath
: PStringQueueItem
;
273 WriteResponseFile
:=False;
274 { set special options for some targets }
275 linkdynamic
:=not(SharedLibFiles
.empty
);
276 linklibc
:=SharedLibFiles
.Find('c');
285 if cs_profile
in aktmoduleswitches
then
289 AddSharedLibrary('gmon');
290 AddSharedLibrary('c');
299 { Open link.res file }
300 LinkRes
.Init(outputexedir
+Info
.ResName
);
302 { Write path to search libraries }
303 HPath
:=current_module
^.locallibrarysearchpath
.First
;
304 while assigned(HPath
) do
306 LinkRes
.Add('SEARCH_DIR('+HPath
^.Data
^+')');
309 HPath
:=LibrarySearchPath
.First
;
310 while assigned(HPath
) do
312 LinkRes
.Add('SEARCH_DIR('+HPath
^.Data
^+')');
316 LinkRes
.Add('INPUT(');
317 { add objectfiles, start with prt0 always }
319 LinkRes
.AddFileName(FindObjectFile(prtobj
,''));
320 { try to add crti and crtbegin if linking to C }
323 s
:=librarysearchpath
.FindFile('crtbegin.o',found
)+'crtbegin.o';
325 LinkRes
.AddFileName(s
);
326 s
:=librarysearchpath
.FindFile('crti.o',found
)+'crti.o';
328 LinkRes
.AddFileName(s
);
331 while not ObjectFiles
.Empty
do
335 LinkRes
.AddFileName(s
);
337 { objects which must be at the end }
340 s
:=librarysearchpath
.FindFile('crtend.o',found
)+'crtend.o';
342 LinkRes
.AddFileName(s
);
343 s
:=librarysearchpath
.FindFile('crtn.o',found
)+'crtn.o';
345 LinkRes
.AddFileName(s
);
349 { Write staticlibraries }
350 if not StaticLibFiles
.Empty
then
352 LinkRes
.Add('GROUP(');
353 While not StaticLibFiles
.Empty
do
355 S
:=StaticLibFiles
.Get
;
356 LinkRes
.AddFileName(s
)
361 { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
362 here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
363 if not SharedLibFiles
.Empty
then
365 LinkRes
.Add('INPUT(');
366 While not SharedLibFiles
.Empty
do
368 S
:=SharedLibFiles
.Get
;
371 i
:=Pos(target_os
.sharedlibext
,S
);
379 linkdynamic
:=false; { libc will include the ld-linux for us }
382 { be sure that libc is the last lib }
385 { when we have -static for the linker the we also need libgcc }
386 if (cs_link_staticflag
in aktglobalswitches
) then
387 LinkRes
.Add('-lgcc');
388 if linkdynamic
and (Info
.DynamicLinker
<>'') then
389 LinkRes
.AddFileName(Info
.DynamicLinker
);
392 { Write and Close response }
396 WriteResponseFile
:=True;
400 function TLinkerLinux
.MakeExecutable
:boolean;
405 DynLinkStr
: string[60];
407 StripStr
: string[40];
409 if not(cs_link_extern
in aktglobalswitches
) then
410 Message1(exec_i_linking
,current_module
^.exefilename
^);
412 { Create some replacements }
416 if (cs_link_staticflag
in aktglobalswitches
) then
417 StaticStr
:='-static';
418 if (cs_link_strip
in aktglobalswitches
) then
420 If (cs_profile
in aktmoduleswitches
) or
421 ((Info
.DynamicLinker
<>'') and (not SharedLibFiles
.Empty
)) then
422 DynLinkStr
:='-dynamic-linker='+Info
.DynamicLinker
;
424 { Write used files and libraries }
425 WriteResponseFile(false);
428 SplitBinCmd(Info
.ExeCmd
[1],binstr
,cmdstr
);
429 Replace(cmdstr
,'$EXE',current_module
^.exefilename
^);
430 Replace(cmdstr
,'$OPT',Info
.ExtraOptions
);
431 Replace(cmdstr
,'$RES',outputexedir
+Info
.ResName
);
432 Replace(cmdstr
,'$STATIC',StaticStr
);
433 Replace(cmdstr
,'$STRIP',StripStr
);
434 Replace(cmdstr
,'$DYNLINK',DynLinkStr
);
435 success
:=DoExec(FindUtil(BinStr
),CmdStr
,true,false);
437 { Remove ReponseFile }
438 if (success
) and not(cs_link_extern
in aktglobalswitches
) then
439 RemoveFile(outputexedir
+Info
.ResName
);
441 MakeExecutable
:=success
; { otherwise a recursive call to link method }
445 Function TLinkerLinux
.MakeSharedLibrary
:boolean;
451 MakeSharedLibrary
:=false;
452 if not(cs_link_extern
in aktglobalswitches
) then
453 Message1(exec_i_linking
,current_module
^.sharedlibfilename
^);
455 { Write used files and libraries }
456 WriteResponseFile(true);
459 SplitBinCmd(Info
.DllCmd
[1],binstr
,cmdstr
);
460 Replace(cmdstr
,'$EXE',current_module
^.sharedlibfilename
^);
461 Replace(cmdstr
,'$OPT',Info
.ExtraOptions
);
462 Replace(cmdstr
,'$RES',outputexedir
+Info
.ResName
);
463 success
:=DoExec(FindUtil(binstr
),cmdstr
,true,false);
465 { Strip the library ? }
466 if success
and (cs_link_strip
in aktglobalswitches
) then
468 SplitBinCmd(Info
.DllCmd
[2],binstr
,cmdstr
);
469 Replace(cmdstr
,'$EXE',current_module
^.sharedlibfilename
^);
470 success
:=DoExec(FindUtil(binstr
),cmdstr
,true,false);
473 { Remove ReponseFile }
474 if (success
) and not(cs_link_extern
in aktglobalswitches
) then
475 RemoveFile(outputexedir
+Info
.ResName
);
477 MakeSharedLibrary
:=success
; { otherwise a recursive call to link method }
484 Revision 1.1 2002/02/19 08:24:12 sasu
487 Revision 1.1.2.2 2000/09/24 21:40:19 peter
488 * error messages updated
489 * if messages not available in message file fallback to the internal
491 * message prefixes (like Note:) can now also be set in the msg file
493 Revision 1.1.2.1 2000/09/10 16:11:59 marco
494 Dynamic linker name is always empty for BSD
496 Revision 1.1 2000/07/13 06:29:57 michael
499 Revision 1.15 2000/07/08 20:43:38 peter
500 * findobjectfile gets extra arg with directory where the unit is found
501 and the .o should be looked first
503 Revision 1.14 2000/03/21 21:36:52 peter
504 * only include crtbegin when linking to libc
506 Revision 1.13 2000/03/12 08:24:03 daniel
507 * Modification for new symtable
509 Revision 1.12 2000/03/02 13:12:37 daniel
510 * Removed a comment to fix gtk.
512 Revision 1.11 2000/02/28 17:23:57 daniel
513 * Current work of symtable integration committed. The symtable can be
514 activated by defining 'newst', but doesn't compile yet. Changes in type
515 checking and oop are completed. What is left is to write a new
516 symtablestack and adapt the parser to use it.
518 Revision 1.10 2000/02/27 14:46:04 peter
519 * check for ld-so.2.0.* then no glibc21 is used, else glibc21 is used
521 Revision 1.9 2000/02/09 10:35:48 peter
522 * -Xt option to link staticly against c libs
524 Revision 1.8 2000/01/11 09:52:07 peter
525 * fixed placing of .sl directories
526 * use -b again for base-file selection
527 * fixed group writing for linux with smartlinking
529 Revision 1.7 2000/01/09 00:55:51 pierre
530 * GROUP of smartlink units put before the C libraries
531 to allow for smartlinking code that uses C code.
533 Revision 1.6 2000/01/07 01:14:42 peter
534 * updated copyright to 2000
536 Revision 1.5 1999/11/16 23:39:04 peter
537 * use outputexedir for link.res location
539 Revision 1.4 1999/11/12 11:03:50 peter
540 * searchpaths changed to stringqueue object
542 Revision 1.3 1999/11/05 13:15:00 florian
543 * some fixes to get the new cg compiling again
545 Revision 1.2 1999/11/04 10:55:31 peter
546 * TSearchPathString for the string type of the searchpaths, which is
547 ansistring under FPC/Delphi
549 Revision 1.1 1999/10/21 14:29:38 peter
550 * redesigned linker object
551 + library support for linux (only procedures can be exported)