t_bsd.pas 23 KB

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