t_bsd.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. {
  2. Copyright (c) 1998-2002 by Peter Vreman (original Linux)
  3. (c) 2000 by Marco van de Voort (FreeBSD mods)
  4. This unit implements support import,export,link routines
  5. for the (i386)FreeBSD target
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit t_bsd;
  20. {$i fpcdefs.inc}
  21. interface
  22. implementation
  23. uses
  24. sysutils,
  25. cutils,cfileutl,cclasses,
  26. verbose,systems,globtype,globals,
  27. symconst,cscript,
  28. fmodule,aasmbase,aasmtai,aasmdata,aasmcpu,cpubase,symsym,symdef,
  29. import,export,link,comprsrc,rescmn,i_bsd,expunix,
  30. cgutils,cgbase,cgobj,cpuinfo,ogbase;
  31. type
  32. timportlibbsd=class(timportlib)
  33. procedure generatelib;override;
  34. end;
  35. texportlibbsd=class(texportlibunix)
  36. end;
  37. tlinkerbsd=class(texternallinker)
  38. private
  39. LdSupportsNoResponseFile : boolean;
  40. LibrarySuffix : Char;
  41. prtobj : string[80];
  42. ReOrder : Boolean;
  43. linklibc : boolean;
  44. Function WriteResponseFile(isdll:boolean) : Boolean;
  45. public
  46. constructor Create;override;
  47. procedure SetDefaultInfo;override;
  48. function MakeExecutable:boolean;override;
  49. function MakeSharedLibrary:boolean;override;
  50. procedure LoadPredefinedLibraryOrder; override;
  51. procedure InitSysInitUnitName; override;
  52. end;
  53. function ModulesLinkToLibc:boolean;
  54. var
  55. hp: tmodule;
  56. begin
  57. { This is called very early, ImportLibraryList is not yet merged into linkothersharedlibs.
  58. The former contains library names qualified with prefix and suffix (coming from
  59. "external 'c' name 'foo' declarations), the latter contains raw names (from "$linklib c"
  60. directives). }
  61. hp:=tmodule(loaded_units.first);
  62. while assigned(hp) do
  63. begin
  64. result:=Assigned(hp.ImportLibraryList.find(target_info.sharedClibprefix+'c'+target_info.sharedClibext));
  65. if result then break;
  66. result:=hp.linkothersharedlibs.find(target_info.sharedClibprefix+'c'+target_info.sharedClibext);
  67. if result then break;
  68. result:=hp.linkothersharedlibs.find('c');
  69. if result then break;
  70. hp:=tmodule(hp.next);
  71. end;
  72. end;
  73. {*****************************************************************************
  74. TIMPORTLIBBSD
  75. *****************************************************************************}
  76. procedure timportlibbsd.generatelib;
  77. var
  78. i : longint;
  79. ImportLibrary : TImportLibrary;
  80. begin
  81. for i:=0 to current_module.ImportLibraryList.Count-1 do
  82. begin
  83. ImportLibrary:=TImportLibrary(current_module.ImportLibraryList[i]);
  84. current_module.linkothersharedlibs.add(ImportLibrary.Name,link_always);
  85. end;
  86. end;
  87. {*****************************************************************************
  88. TLINKERBSD
  89. *****************************************************************************}
  90. Constructor TLinkerBSD.Create;
  91. begin
  92. Inherited Create;
  93. if not Dontlinkstdlibpath Then
  94. if target_info.system in systems_openbsd then
  95. LibrarySearchPath.AddLibraryPath(sysrootpath,'=/usr/lib;=$OPENBSD_X11BASE/lib;=$OPENBSD_LOCALBASE/lib',true)
  96. else
  97. LibrarySearchPath.AddLibraryPath(sysrootpath,'=/lib;=/usr/lib;=/usr/X11R6/lib',true);
  98. end;
  99. procedure TLinkerBSD.SetDefaultInfo;
  100. {
  101. This will also detect which libc version will be used
  102. }
  103. var
  104. LdProgram: string='ld';
  105. begin
  106. { Force ld.lld usage for x86_64 openbsd system,
  107. because GNU linker generates wrong executable's on x86_64 OpenBSD 7.5 }
  108. if (cs_link_lld in current_settings.globalswitches) or (target_info.system = system_x86_64_openbsd) then
  109. LdProgram:='ld.lld'
  110. else if target_info.system in (systems_openbsd+systems_freebsd+[system_x86_64_dragonfly]) then
  111. LdProgram:='ld.bfd';
  112. LibrarySuffix:=' ';
  113. LdSupportsNoResponseFile := (target_info.system in ([system_m68k_netbsd]+systems_darwin));
  114. with Info do
  115. begin
  116. if LdSupportsNoResponseFile then
  117. begin
  118. ExeCmd[1]:=LdProgram+' $TARGET $EMUL $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP $LTO $ORDERSYMS -L. -o $EXE $CATRES $FILELIST';
  119. DllCmd[1]:=LdProgram+' $TARGET $EMUL $OPT $MAP $LTO $ORDERSYMS -shared -L. -o $EXE $CATRES $FILELIST'
  120. end
  121. else
  122. begin
  123. ExeCmd[1]:=LdProgram+' $TARGET $EMUL $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP $MAP $ORDERSYMS -L. -o $EXE $RES';
  124. DllCmd[1]:=LdProgram+' $TARGET $EMUL $OPT $INIT $FINI $SONAME $MAP $ORDERSYMS -shared -L. -o $EXE $RES';
  125. end;
  126. DllCmd[2]:='strip --strip-unneeded $EXE';
  127. { OpenBSD seems to use a wrong dynamic linker by default }
  128. if target_info.system in systems_openbsd then
  129. DynamicLinker:='/usr/libexec/ld.so'
  130. else if target_info.system in systems_netbsd then
  131. DynamicLinker:='/usr/libexec/ld.elf_so'
  132. else if target_info.system=system_x86_64_dragonfly then
  133. DynamicLinker:='/libexec/ld-elf.so.2'
  134. else
  135. DynamicLinker:='';
  136. end;
  137. end;
  138. procedure TLinkerBSD.LoadPredefinedLibraryOrder;
  139. // put your linkorder/linkalias overrides here.
  140. // Note: assumes only called when reordering/aliasing is used.
  141. Begin
  142. if (target_info.system =system_i386_freebsd) and
  143. not (cs_link_no_default_lib_order in current_settings.globalswitches) Then
  144. Begin
  145. LinkLibraryOrder.add('gcc','',15);
  146. LinkLibraryOrder.add('c','',50); // c and c_p mutual. excl?
  147. LinkLibraryOrder.add('c_p','',55);
  148. LinkLibraryOrder.add('pthread','',75); // pthread and c_r should be mutually exclusive
  149. LinkLibraryOrder.add('c_r','',76);
  150. LinkLibraryOrder.add('kvm','',80); // must be before ncurses
  151. if (cs_link_pthread in current_settings.globalswitches) Then // convert libpthread to libc_r.
  152. LinkLibraryAliases.add('pthread','c_r');
  153. end;
  154. End;
  155. procedure TLinkerBSD.InitSysInitUnitName;
  156. var
  157. cprtobj,
  158. gprtobj,
  159. si_cprt,
  160. si_gprt : string[80];
  161. begin
  162. linklibc:=ModulesLinkToLibc;
  163. if current_module.islibrary and
  164. (target_info.system in systems_bsd) then
  165. begin
  166. prtobj:='dllprt0';
  167. cprtobj:='dllprt0';
  168. gprtobj:='dllprt0';
  169. SysInitUnit:='si_dll';
  170. si_cprt:='si_dll';
  171. si_gprt:='si_dll';
  172. end
  173. else
  174. begin
  175. prtobj:='prt0';
  176. cprtobj:='cprt0';
  177. gprtobj:='gprt0';
  178. SysInitUnit:='si_prc';
  179. si_cprt:='si_c';
  180. si_gprt:='si_g';
  181. end;
  182. // this one is a bit complex.
  183. // Only reorder for now if -XL or -XO params are given
  184. // or when -Xf.
  185. reorder:= linklibc and
  186. (
  187. ReorderEntries
  188. or
  189. (cs_link_pthread in current_settings.globalswitches));
  190. if cs_profile in current_settings.moduleswitches then
  191. begin
  192. prtobj:=gprtobj;
  193. SysInitUnit:=si_gprt;
  194. AddSharedLibrary('c');
  195. LibrarySuffix:='p';
  196. linklibc:=true;
  197. end
  198. else
  199. begin
  200. if linklibc then
  201. begin
  202. prtobj:=cprtobj;
  203. SysInitUnit:=si_cprt;
  204. end;
  205. end;
  206. end;
  207. Function TLinkerBSD.WriteResponseFile(isdll:boolean) : Boolean;
  208. Var
  209. linkres : TLinkRes;
  210. FilesList : TLinkRes;
  211. i : longint;
  212. HPath : TCmdStrListItem;
  213. s,s1,s2 : TCmdStr;
  214. linkdynamic : boolean;
  215. Fl1,Fl2 : Boolean;
  216. begin
  217. WriteResponseFile:=False;
  218. ReOrder:=False;
  219. linkdynamic:=False;
  220. { set special options for some targets }
  221. linkdynamic:=not(SharedLibFiles.empty);
  222. // after this point addition of shared libs not allowed.
  223. if reorder Then
  224. ExpandAndApplyOrder(SharedLibFiles);
  225. { Open link.res file }
  226. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName,not LdSupportsNoResponseFile);
  227. { Write path to search libraries }
  228. HPath:=TCmdStrListItem(current_module.locallibrarysearchpath.First);
  229. while assigned(HPath) do
  230. begin
  231. if LdSupportsNoResponseFile then
  232. LinkRes.Add('-L'+HPath.Str)
  233. else
  234. LinkRes.Add('SEARCH_DIR("'+HPath.Str+'")');
  235. HPath:=TCmdStrListItem(HPath.Next);
  236. end;
  237. HPath:=TCmdStrListItem(LibrarySearchPath.First);
  238. while assigned(HPath) do
  239. begin
  240. if LdSupportsNoResponseFile then
  241. LinkRes.Add('-L'+HPath.Str)
  242. else
  243. LinkRes.Add('SEARCH_DIR("'+HPath.Str+'")');
  244. HPath:=TCmdStrListItem(HPath.Next);
  245. end;
  246. { force local symbol resolution (i.e., inside the shared }
  247. { library itself) for all non-exorted symbols, otherwise }
  248. { several RTL symbols of FPC-compiled shared libraries }
  249. { will be bound to those of a single shared library or }
  250. { to the main program }
  251. if (isdll) and (target_info.system in systems_bsd) then
  252. begin
  253. LinkRes.add('VERSION');
  254. LinkRes.add('{');
  255. LinkRes.add(' {');
  256. if not texportlibunix(exportlib).exportedsymnames.empty then
  257. begin
  258. LinkRes.add(' global:');
  259. repeat
  260. LinkRes.add(' '+texportlibunix(exportlib).exportedsymnames.getfirst+';');
  261. until texportlibunix(exportlib).exportedsymnames.empty;
  262. end;
  263. LinkRes.add(' local:');
  264. LinkRes.add(' *;');
  265. LinkRes.add(' };');
  266. LinkRes.add('}');
  267. end;
  268. if not LdSupportsNoResponseFile then
  269. LinkRes.Add('INPUT(');
  270. { add objectfiles, start with prt0 always }
  271. if not (target_info.system in systems_internal_sysinit) and (prtobj<>'') then
  272. LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
  273. { try to add crti and crtbegin if linking to C }
  274. if linklibc then
  275. begin
  276. if librarysearchpath.FindFile('crti.o',false,s) then
  277. LinkRes.AddFileName(s);
  278. if ((cs_create_pic in current_settings.moduleswitches) and
  279. not (target_info.system in systems_openbsd)) or
  280. (current_module.islibrary and
  281. (target_info.system in systems_openbsd)) then
  282. begin
  283. if librarysearchpath.FindFile('crtbeginS.o',false,s) then
  284. LinkRes.AddFileName(s);
  285. end
  286. else
  287. if (cs_link_staticflag in current_settings.globalswitches) and
  288. librarysearchpath.FindFile('crtbeginT.o',false,s) then
  289. LinkRes.AddFileName(s)
  290. else if librarysearchpath.FindFile('crtbegin.o',false,s) then
  291. LinkRes.AddFileName(s);
  292. end;
  293. { main objectfiles }
  294. while not ObjectFiles.Empty do
  295. begin
  296. s:=ObjectFiles.GetFirst;
  297. if s<>'' then
  298. if LdSupportsNoResponseFile then
  299. LinkRes.AddFileName(s)
  300. else
  301. LinkRes.AddFileName(maybequoted(s));
  302. end;
  303. if not LdSupportsNoResponseFile then
  304. LinkRes.Add(')');
  305. { Write staticlibraries }
  306. if not StaticLibFiles.Empty then
  307. begin
  308. if not LdSupportsNoResponseFile then
  309. LinkRes.Add('GROUP(');
  310. While not StaticLibFiles.Empty do
  311. begin
  312. S:=StaticLibFiles.GetFirst;
  313. if LdSupportsNoResponseFile then
  314. LinkRes.AddFileName(s)
  315. else
  316. LinkRes.AddFileName(maybequoted(s))
  317. end;
  318. if not LdSupportsNoResponseFile then
  319. LinkRes.Add(')');
  320. end;
  321. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  322. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  323. if not SharedLibFiles.Empty then
  324. begin
  325. if not LdSupportsNoResponseFile then
  326. LinkRes.Add('INPUT(');
  327. While not SharedLibFiles.Empty do
  328. begin
  329. S:=SharedLibFiles.GetFirst;
  330. if (s<>'c') or reorder then
  331. begin
  332. i:=Pos(target_info.sharedlibext,S);
  333. if i>0 then
  334. Delete(S,i,255);
  335. LinkRes.Add('-l'+s);
  336. end
  337. else
  338. begin
  339. linklibc:=true;
  340. linkdynamic:=false; { libc will include the ld-* for us }
  341. end;
  342. end;
  343. { be sure that libc is the last lib }
  344. if linklibc and not reorder then
  345. Begin
  346. If LibrarySuffix=' ' Then
  347. LinkRes.Add('-lc')
  348. else
  349. LinkRes.Add('-lc_'+LibrarySuffix);
  350. If LibrarySuffix='r' Then
  351. LinkRes.Add('-lc');
  352. end;
  353. { when we have -static for the linker the we also need libgcc }
  354. if (cs_link_staticflag in current_settings.globalswitches) then
  355. LinkRes.Add('-lgcc');
  356. if linkdynamic and (Info.DynamicLinker<>'') and
  357. not(target_info.system in systems_openbsd) then
  358. LinkRes.AddFileName(Info.DynamicLinker);
  359. if not LdSupportsNoResponseFile then
  360. LinkRes.Add(')');
  361. end;
  362. { objects which must be at the end }
  363. if linklibc then
  364. begin
  365. if ((cs_create_pic in current_settings.moduleswitches) and
  366. not (target_info.system in systems_openbsd)) or
  367. (current_module.islibrary and
  368. (target_info.system in systems_openbsd)) then
  369. Fl1:=librarysearchpath.FindFile('crtendS.o',false,s1)
  370. else
  371. Fl1:=librarysearchpath.FindFile('crtend.o',false,s1);
  372. Fl2:=librarysearchpath.FindFile('crtn.o',false,s2);
  373. if Fl1 or Fl2 then
  374. begin
  375. LinkRes.Add('INPUT(');
  376. If Fl1 Then
  377. LinkRes.AddFileName(s1);
  378. If Fl2 Then
  379. LinkRes.AddFileName(s2);
  380. LinkRes.Add(')');
  381. end;
  382. end;
  383. { Write and Close response }
  384. linkres.writetodisk;
  385. linkres.Free;
  386. WriteResponseFile:=True;
  387. end;
  388. function TLinkerBSD.MakeExecutable:boolean;
  389. var
  390. binstr,
  391. cmdstr,
  392. mapstr,
  393. targetstr,
  394. emulstr,
  395. ordersymfile: TCmdStr;
  396. linkscript: TAsmScript;
  397. DynLinkStr : string[60];
  398. GCSectionsStr,
  399. StaticStr,
  400. StripStr : string[63];
  401. success,
  402. useshell : boolean;
  403. begin
  404. if not(cs_link_nolink in current_settings.globalswitches) then
  405. Message1(exec_i_linking,current_module.exefilename);
  406. { Create some replacements }
  407. StaticStr:='';
  408. StripStr:='';
  409. DynLinkStr:='';
  410. GCSectionsStr:='';
  411. linkscript:=nil;
  412. mapstr:='';
  413. if (cs_link_map in current_settings.globalswitches) then
  414. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.exefilename,'.map'));
  415. { i386_freebsd needs -b elf32-i386-freebsd and -m elf_i386_fbsd
  416. to avoid creation of a i386:x86_64 arch binary }
  417. if target_info.system=system_i386_freebsd then
  418. begin
  419. targetstr:='-b elf32-i386-freebsd';
  420. emulstr:='-m elf_i386_fbsd';
  421. end
  422. else
  423. begin
  424. targetstr:='';
  425. emulstr:='';
  426. end;
  427. if (cs_link_staticflag in current_settings.globalswitches) then
  428. begin
  429. if (target_info.system=system_m68k_netbsd) and
  430. ((cs_link_on_target in current_settings.globalswitches) or
  431. (target_info.system=source_info.system)) then
  432. StaticStr:='-Bstatic'
  433. else
  434. StaticStr:='-static';
  435. end;
  436. if (cs_link_strip in current_settings.globalswitches) then
  437. StripStr:='-s';
  438. if (cs_link_smart in current_settings.globalswitches) and
  439. (tf_smartlink_sections in target_info.flags) then
  440. GCSectionsStr:='--gc-sections';
  441. if(cs_profile in current_settings.moduleswitches) or
  442. ((Info.DynamicLinker<>'') and
  443. ((not SharedLibFiles.Empty) or
  444. (target_info.system in systems_openbsd))) then
  445. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  446. if CShared Then
  447. begin
  448. DynLinKStr:=DynLinkStr+' --shared'
  449. end;
  450. { Use -nopie on OpenBSD if PIC support is turned off }
  451. if (target_info.system in systems_openbsd) and
  452. not(cs_create_pic in current_settings.moduleswitches) then
  453. Info.ExtraOptions:=Info.ExtraOptions+' -nopie';
  454. { -N seems to be needed on NetBSD/earm }
  455. if (target_info.system in [system_arm_netbsd]) then
  456. Info.ExtraOptions:=Info.ExtraOptions+' -N';
  457. { Write used files and libraries }
  458. WriteResponseFile(false);
  459. { Write symbol order file }
  460. ordersymfile:=WriteSymbolOrderFile;
  461. { Call linker }
  462. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  463. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename));
  464. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  465. Replace(cmdstr,'$TARGET',targetstr);
  466. Replace(cmdstr,'$EMUL',EmulStr);
  467. Replace(cmdstr,'$MAP',mapstr);
  468. Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
  469. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  470. if ordersymfile<>'' then
  471. Replace(cmdstr,'$ORDERSYMS','--symbol-ordering-file '+maybequoted(ordersymfile))
  472. else
  473. Replace(cmdstr,'$ORDERSYMS','');
  474. Replace(cmdstr,'$FILELIST','');
  475. Replace(cmdstr,'$STATIC',StaticStr);
  476. Replace(cmdstr,'$STRIP',StripStr);
  477. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  478. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  479. BinStr:=FindUtil(utilsprefix+BinStr);
  480. if (LdSupportsNoResponseFile) and
  481. not(cs_link_nolink in current_settings.globalswitches) then
  482. begin
  483. { we have to use a script to use the IFS hack }
  484. linkscript:=GenerateScript(outputexedir+'ppaslink');
  485. linkscript.AddLinkCommand(BinStr,CmdStr,'');
  486. linkscript.WriteToDisk;
  487. BinStr:=linkscript.fn;
  488. if not path_absolute(BinStr) then
  489. if cs_link_on_target in current_settings.globalswitches then
  490. BinStr:='.'+target_info.dirsep+BinStr
  491. else
  492. BinStr:='.'+source_info.dirsep+BinStr;
  493. CmdStr:='';
  494. end;
  495. useshell:=not (tf_no_backquote_support in source_info.flags);
  496. success:=DoExec(BinStr,CmdStr,true,LdSupportsNoResponseFile or useshell);
  497. { Remove ReponseFile }
  498. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  499. begin
  500. DeleteFile(outputexedir+Info.ResName);
  501. if ordersymfile<>'' then
  502. DeleteFile(ordersymfile);
  503. if LdSupportsNoResponseFile Then
  504. begin
  505. DeleteFile(linkscript.fn);
  506. linkscript.free
  507. end;
  508. end;
  509. MakeExecutable:=success; { otherwise a recursive call to link method }
  510. end;
  511. Function TLinkerBSD.MakeSharedLibrary:boolean;
  512. var
  513. InitStr,
  514. FiniStr,
  515. SoNameStr : string[80];
  516. linkscript: TAsmScript;
  517. binstr,
  518. cmdstr,
  519. mapstr,
  520. ordersymfile,
  521. targetstr,
  522. emulstr : TCmdStr;
  523. GCSectionsStr : string[63];
  524. exportedsyms: text;
  525. success : boolean;
  526. begin
  527. MakeSharedLibrary:=false;
  528. GCSectionsStr:='';
  529. mapstr:='';
  530. linkscript:=nil;
  531. if not(cs_link_nolink in current_settings.globalswitches) then
  532. Message1(exec_i_linking,current_module.sharedlibfilename);
  533. { Write used files and libraries }
  534. WriteResponseFile(true);
  535. { Write symbol order file }
  536. ordersymfile:=WriteSymbolOrderFile;
  537. if (cs_link_smart in current_settings.globalswitches) and
  538. (tf_smartlink_sections in target_info.flags) then
  539. { disabled because not tested
  540. GCSectionsStr:='--gc-sections' }
  541. ;
  542. if (cs_link_map in current_settings.globalswitches) then
  543. mapstr:='-Map '+maybequoted(ChangeFileExt(current_module.sharedlibfilename,'.map'));
  544. { i386_freebsd needs -b elf32-i386-freebsd and -m elf_i386_fbsd
  545. to avoid creation of a i386:x86_64 arch binary }
  546. if target_info.system=system_i386_freebsd then
  547. begin
  548. targetstr:='-b elf32-i386-freebsd';
  549. emulstr:='-m elf_i386_fbsd';
  550. end
  551. else
  552. begin
  553. targetstr:='';
  554. emulstr:='';
  555. end;
  556. InitStr:='-init FPC_LIB_START';
  557. FiniStr:='-fini FPC_LIB_EXIT';
  558. SoNameStr:='-soname '+ExtractFileName(current_module.sharedlibfilename);
  559. { Call linker }
  560. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  561. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
  562. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  563. Replace(cmdstr,'$TARGET',targetstr);
  564. Replace(cmdstr,'$EMUL',EmulStr);
  565. Replace(cmdstr,'$CATRES',CatFileContent(outputexedir+Info.ResName));
  566. Replace(cmdstr,'$FILELIST','');
  567. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  568. Replace(cmdstr,'$INIT',InitStr);
  569. Replace(cmdstr,'$FINI',FiniStr);
  570. Replace(cmdstr,'$GCSECTIONS',GCSectionsStr);
  571. Replace(cmdstr,'$SONAME',SoNameStr);
  572. Replace(cmdstr,'$MAP',mapstr);
  573. if ordersymfile<>'' then
  574. Replace(cmdstr,'$ORDERSYMS','--symbol-ordering-file '+maybequoted(ordersymfile))
  575. else
  576. Replace(cmdstr,'$ORDERSYMS','');
  577. BinStr:=FindUtil(utilsprefix+BinStr);
  578. if (LdSupportsNoResponseFile) and
  579. not(cs_link_nolink in current_settings.globalswitches) then
  580. begin
  581. { we have to use a script to use the IFS hack }
  582. linkscript:=GenerateScript(outputexedir+'ppaslink');
  583. linkscript.AddLinkCommand(BinStr,CmdStr,'');
  584. linkscript.WriteToDisk;
  585. BinStr:=linkscript.fn;
  586. if not path_absolute(BinStr) then
  587. if cs_link_on_target in current_settings.globalswitches then
  588. BinStr:='.'+target_info.dirsep+BinStr
  589. else
  590. BinStr:='.'+source_info.dirsep+BinStr;
  591. CmdStr:='';
  592. end;
  593. success:=DoExec(BinStr,cmdstr,true,LdSupportsNoResponseFile);
  594. { Strip the library ? }
  595. if success and (cs_link_strip in current_settings.globalswitches) then
  596. begin
  597. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  598. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename));
  599. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,false,false);
  600. end;
  601. { Remove ReponseFile }
  602. if (success) and not(cs_link_nolink in current_settings.globalswitches) then
  603. begin
  604. DeleteFile(outputexedir+Info.ResName);
  605. if ordersymfile<>'' then
  606. DeleteFile(ordersymfile);
  607. if LdSupportsNoResponseFile Then
  608. begin
  609. DeleteFile(linkscript.fn);
  610. linkscript.free
  611. end;
  612. end;
  613. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  614. end;
  615. {*****************************************************************************
  616. Initialize
  617. *****************************************************************************}
  618. initialization
  619. RegisterLinker(ld_bsd,TLinkerBSD);
  620. {$ifdef x86_64}
  621. RegisterImport(system_x86_64_dragonfly,timportlibbsd);
  622. RegisterExport(system_x86_64_dragonfly,texportlibbsd);
  623. RegisterTarget(system_x86_64_dragonfly_info);
  624. RegisterImport(system_x86_64_freebsd,timportlibbsd);
  625. RegisterExport(system_x86_64_freebsd,texportlibbsd);
  626. RegisterTarget(system_x86_64_freebsd_info);
  627. RegisterImport(system_x86_64_openbsd,timportlibbsd);
  628. RegisterExport(system_x86_64_openbsd,texportlibbsd);
  629. RegisterTarget(system_x86_64_openbsd_info);
  630. RegisterImport(system_x86_64_netbsd,timportlibbsd);
  631. RegisterExport(system_x86_64_netbsd,texportlibbsd);
  632. RegisterTarget(system_x86_64_netbsd_info);
  633. {$endif}
  634. {$ifdef i386}
  635. RegisterImport(system_i386_freebsd,timportlibbsd);
  636. RegisterExport(system_i386_freebsd,texportlibbsd);
  637. RegisterTarget(system_i386_freebsd_info);
  638. RegisterImport(system_i386_netbsd,timportlibbsd);
  639. RegisterExport(system_i386_netbsd,texportlibbsd);
  640. RegisterTarget(system_i386_netbsd_info);
  641. RegisterImport(system_i386_openbsd,timportlibbsd);
  642. RegisterExport(system_i386_openbsd,texportlibbsd);
  643. RegisterTarget(system_i386_openbsd_info);
  644. {$endif i386}
  645. {$ifdef m68k}
  646. RegisterImport(system_m68k_netbsd,timportlibbsd);
  647. RegisterExport(system_m68k_netbsd,texportlibbsd);
  648. RegisterTarget(system_m68k_netbsd_info);
  649. {$endif m68k}
  650. {$ifdef powerpc}
  651. RegisterImport(system_powerpc_netbsd,timportlibbsd);
  652. RegisterExport(system_powerpc_netbsd,texportlibbsd);
  653. RegisterTarget(system_powerpc_netbsd_info);
  654. {$endif powerpc}
  655. {$ifdef arm}
  656. RegisterImport(system_arm_netbsd,timportlibbsd);
  657. RegisterExport(system_arm_netbsd,texportlibbsd);
  658. RegisterTarget(system_arm_netbsd_info);
  659. {$endif arm}
  660. RegisterRes(res_elf_info,TWinLikeResourceFile);
  661. end.