t_fbsd.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Peter Vreman (original Linux)
  4. (c) 2000 by Marco van de Voort (FreeBSD mods)
  5. This unit implements support import,export,link routines
  6. for the (i386)FreeBSD target
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. unit t_fbsd;
  21. {$i fpcdefs.inc}
  22. interface
  23. implementation
  24. uses
  25. cutils,cclasses,
  26. verbose,systems,globtype,globals,
  27. symconst,script,
  28. fmodule,aasmbase,aasmtai,aasmcpu,cpubase,symsym,
  29. import,export,link,i_fbsd;
  30. type
  31. timportlibfreebsd=class(timportlib)
  32. procedure preparelib(const s:string);override;
  33. procedure importprocedure(const func,module:string;index:longint;const name:string);override;
  34. procedure importvariable(vs:tvarsym;const name,module:string);override;
  35. procedure generatelib;override;
  36. end;
  37. texportlibfreebsd=class(texportlib)
  38. procedure preparelib(const s : string);override;
  39. procedure exportprocedure(hp : texported_item);override;
  40. procedure exportvar(hp : texported_item);override;
  41. procedure generatelib;override;
  42. end;
  43. tlinkerfreebsd=class(texternallinker)
  44. private
  45. Glibc2,
  46. Glibc21,
  47. LdSupportsNoResponseFile : boolean;
  48. Function WriteResponseFile(isdll:boolean) : Boolean;
  49. public
  50. constructor Create;override;
  51. procedure SetDefaultInfo;override;
  52. function MakeExecutable:boolean;override;
  53. function MakeSharedLibrary:boolean;override;
  54. end;
  55. {*****************************************************************************
  56. TIMPORTLIBLINUX
  57. *****************************************************************************}
  58. procedure timportlibfreebsd.preparelib(const s : string);
  59. begin
  60. end;
  61. procedure timportlibfreebsd.importprocedure(const func,module : string;index : longint;const name : string);
  62. begin
  63. { insert sharedlibrary }
  64. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  65. { do nothing with the procedure, only set the mangledname }
  66. if name<>'' then
  67. aktprocdef.setmangledname(name)
  68. else
  69. message(parser_e_empty_import_name);
  70. end;
  71. procedure timportlibfreebsd.importvariable(vs:tvarsym;const name,module:string);
  72. begin
  73. { insert sharedlibrary }
  74. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  75. { reset the mangledname and turn off the dll_var option }
  76. vs.set_mangledname(name);
  77. exclude(vs.varoptions,vo_is_dll_var);
  78. end;
  79. procedure timportlibfreebsd.generatelib;
  80. begin
  81. end;
  82. {*****************************************************************************
  83. TEXPORTLIBLINUX
  84. *****************************************************************************}
  85. procedure texportlibfreebsd.preparelib(const s:string);
  86. begin
  87. end;
  88. procedure texportlibfreebsd.exportprocedure(hp : texported_item);
  89. var
  90. hp2 : texported_item;
  91. begin
  92. { first test the index value }
  93. if (hp.options and eo_index)<>0 then
  94. begin
  95. Message1(parser_e_no_export_with_index_for_target,'freebsd');
  96. exit;
  97. end;
  98. { now place in correct order }
  99. hp2:=texported_item(current_module._exports.first);
  100. while assigned(hp2) and
  101. (hp.name^>hp2.name^) do
  102. hp2:=texported_item(hp2.next);
  103. { insert hp there !! }
  104. if assigned(hp2) and (hp2.name^=hp.name^) then
  105. begin
  106. { this is not allowed !! }
  107. Message1(parser_e_export_name_double,hp.name^);
  108. exit;
  109. end;
  110. if hp2=texported_item(current_module._exports.first) then
  111. current_module._exports.concat(hp)
  112. else if assigned(hp2) then
  113. begin
  114. hp.next:=hp2;
  115. hp.previous:=hp2.previous;
  116. if assigned(hp2.previous) then
  117. hp2.previous.next:=hp;
  118. hp2.previous:=hp;
  119. end
  120. else
  121. current_module._exports.concat(hp);
  122. end;
  123. procedure texportlibfreebsd.exportvar(hp : texported_item);
  124. begin
  125. hp.is_var:=true;
  126. exportprocedure(hp);
  127. end;
  128. procedure texportlibfreebsd.generatelib;
  129. var
  130. hp2 : texported_item;
  131. begin
  132. hp2:=texported_item(current_module._exports.first);
  133. while assigned(hp2) do
  134. begin
  135. if (not hp2.is_var) and
  136. (hp2.sym.typ=procsym) then
  137. begin
  138. { the manglednames can already be the same when the procedure
  139. is declared with cdecl }
  140. if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
  141. begin
  142. {$ifdef i386}
  143. { place jump in codesegment }
  144. codesegment.concat(Tai_align.Create_op(4,$90));
  145. codeSegment.concat(Tai_symbol.Createname_global(hp2.name^,0));
  146. codeSegment.concat(Taicpu.Op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(tprocsym(hp2.sym).first_procdef.mangledname)));
  147. codeSegment.concat(Tai_symbol_end.Createname(hp2.name^));
  148. {$endif i386}
  149. end;
  150. end
  151. else
  152. Message1(parser_e_no_export_of_variables_for_target,'freebsd');
  153. hp2:=texported_item(hp2.next);
  154. end;
  155. end;
  156. {*****************************************************************************
  157. TLINKERLINUX
  158. *****************************************************************************}
  159. Constructor TLinkerFreeBSD.Create;
  160. begin
  161. Inherited Create;
  162. LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
  163. end;
  164. procedure TLinkerFreeBSD.SetDefaultInfo;
  165. {
  166. This will also detect which libc version will be used
  167. }
  168. begin
  169. Glibc2:=false;
  170. Glibc21:=false;
  171. {$ifdef NETBSD}
  172. {$ifdef M68K}
  173. LdSupportsNoResponseFile:=true;
  174. {$else : not M68K}
  175. LdSupportsNoResponseFile:=false;
  176. {$endif M68K}
  177. {$else : not NETBSD}
  178. LdSupportsNoResponseFile:=false;
  179. {$endif NETBSD}
  180. with Info do
  181. begin
  182. if LdSupportsNoResponseFile then
  183. begin
  184. ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE `cat $RES`';
  185. { We need external linking to interpret the `cat $RES` PM }
  186. include(aktglobalswitches,cs_link_extern);
  187. end
  188. else
  189. ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
  190. DllCmd[1]:='ld $OPT -shared -L. -o $EXE $RES';
  191. DllCmd[2]:='strip --strip-unneeded $EXE';
  192. { first try glibc2 }
  193. {$ifdef GLIBC2} {Keep linux code in place. FBSD might go to a different
  194. glibc too once}
  195. DynamicLinker:='/lib/ld-linux.so.2';
  196. if FileExists(DynamicLinker) then
  197. begin
  198. Glibc2:=true;
  199. { Check for 2.0 files, else use the glibc 2.1 stub }
  200. if FileExists('/lib/ld-2.0.*') then
  201. Glibc21:=false
  202. else
  203. Glibc21:=true;
  204. end
  205. else
  206. DynamicLinker:='/lib/ld-linux.so.1';
  207. {$else}
  208. DynamicLinker:='';
  209. {$endif}
  210. end;
  211. end;
  212. Function TLinkerFreeBSD.WriteResponseFile(isdll:boolean) : Boolean;
  213. Var
  214. linkres : TLinkRes;
  215. i : longint;
  216. cprtobj,
  217. gprtobj,
  218. prtobj : string[80];
  219. HPath : TStringListItem;
  220. s,s1,s2 : string;
  221. linkdynamic,
  222. linklibc : boolean;
  223. Fl1,Fl2 : Boolean;
  224. begin
  225. WriteResponseFile:=False;
  226. { set special options for some targets }
  227. linkdynamic:=not(SharedLibFiles.empty);
  228. linklibc:=(SharedLibFiles.Find('c')<>nil);
  229. prtobj:='prt0';
  230. cprtobj:='cprt0';
  231. gprtobj:='gprt0';
  232. if glibc21 then
  233. begin
  234. cprtobj:='cprt21';
  235. gprtobj:='gprt21';
  236. end;
  237. if cs_profile in aktmoduleswitches then
  238. begin
  239. prtobj:=gprtobj;
  240. if not glibc2 then
  241. AddSharedLibrary('gmon');
  242. AddSharedLibrary('c');
  243. linklibc:=true;
  244. end
  245. else
  246. begin
  247. if linklibc then
  248. prtobj:=cprtobj;
  249. end;
  250. { Open link.res file }
  251. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  252. { Write path to search libraries }
  253. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  254. while assigned(HPath) do
  255. begin
  256. if LdSupportsNoResponseFile then
  257. LinkRes.Add('-L'+HPath.Str)
  258. else
  259. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  260. HPath:=TStringListItem(HPath.Next);
  261. end;
  262. HPath:=TStringListItem(LibrarySearchPath.First);
  263. while assigned(HPath) do
  264. begin
  265. if LdSupportsNoResponseFile then
  266. LinkRes.Add('-L'+HPath.Str)
  267. else
  268. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  269. HPath:=TStringListItem(HPath.Next);
  270. end;
  271. if not LdSupportsNoResponseFile then
  272. LinkRes.Add('INPUT(');
  273. { add objectfiles, start with prt0 always }
  274. if prtobj<>'' then
  275. LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
  276. { try to add crti and crtbegin if linking to C }
  277. if linklibc then
  278. begin
  279. if librarysearchpath.FindFile('crtbegin.o',s) then
  280. LinkRes.AddFileName(s);
  281. if librarysearchpath.FindFile('crti.o',s) then
  282. LinkRes.AddFileName(s);
  283. end;
  284. { main objectfiles }
  285. while not ObjectFiles.Empty do
  286. begin
  287. s:=ObjectFiles.GetFirst;
  288. if s<>'' then
  289. LinkRes.AddFileName(s);
  290. end;
  291. if not LdSupportsNoResponseFile then
  292. LinkRes.Add(')');
  293. { Write staticlibraries }
  294. if not StaticLibFiles.Empty then
  295. begin
  296. if not LdSupportsNoResponseFile then
  297. LinkRes.Add('GROUP(');
  298. While not StaticLibFiles.Empty do
  299. begin
  300. S:=StaticLibFiles.GetFirst;
  301. LinkRes.AddFileName(s)
  302. end;
  303. if not LdSupportsNoResponseFile then
  304. LinkRes.Add(')');
  305. end;
  306. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  307. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  308. if not SharedLibFiles.Empty then
  309. begin
  310. if not LdSupportsNoResponseFile then
  311. LinkRes.Add('INPUT(');
  312. While not SharedLibFiles.Empty do
  313. begin
  314. S:=SharedLibFiles.GetFirst;
  315. if s<>'c' then
  316. begin
  317. i:=Pos(target_info.sharedlibext,S);
  318. if i>0 then
  319. Delete(S,i,255);
  320. LinkRes.Add('-l'+s);
  321. end
  322. else
  323. begin
  324. linklibc:=true;
  325. linkdynamic:=false; { libc will include the ld-linux for us }
  326. end;
  327. end;
  328. { be sure that libc is the last lib }
  329. if linklibc then
  330. LinkRes.Add('-lc');
  331. { when we have -static for the linker the we also need libgcc }
  332. if (cs_link_staticflag in aktglobalswitches) then
  333. LinkRes.Add('-lgcc');
  334. if linkdynamic and (Info.DynamicLinker<>'') then
  335. LinkRes.AddFileName(Info.DynamicLinker);
  336. if not LdSupportsNoResponseFile then
  337. LinkRes.Add(')');
  338. end;
  339. { objects which must be at the end }
  340. if linklibc then
  341. begin
  342. Fl1:=librarysearchpath.FindFile('crtend.o',s1);
  343. Fl2:=librarysearchpath.FindFile('crtn.o',s2);
  344. if Fl1 or Fl2 then
  345. begin
  346. LinkRes.Add('INPUT(');
  347. If Fl1 Then
  348. LinkRes.AddFileName(s1);
  349. If Fl2 Then
  350. LinkRes.AddFileName(s2);
  351. LinkRes.Add(')');
  352. end;
  353. end;
  354. { Write and Close response }
  355. linkres.writetodisk;
  356. linkres.Free;
  357. WriteResponseFile:=True;
  358. end;
  359. function TLinkerFreeBSD.MakeExecutable:boolean;
  360. var
  361. binstr,
  362. cmdstr : string;
  363. success : boolean;
  364. DynLinkStr : string[60];
  365. StaticStr,
  366. StripStr : string[40];
  367. begin
  368. if not(cs_link_extern in aktglobalswitches) then
  369. Message1(exec_i_linking,current_module.exefilename^);
  370. { Create some replacements }
  371. StaticStr:='';
  372. StripStr:='';
  373. DynLinkStr:='';
  374. if (cs_link_staticflag in aktglobalswitches) then
  375. begin
  376. if (target_info.system=system_m68k_netbsd) and
  377. ((cs_link_on_target in aktglobalswitches) or
  378. (target_info.system=source_info.system)) then
  379. StaticStr:='-Bstatic'
  380. else
  381. StaticStr:='-static';
  382. end;
  383. if (cs_link_strip in aktglobalswitches) then
  384. StripStr:='-s';
  385. If (cs_profile in aktmoduleswitches) or
  386. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  387. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  388. { Write used files and libraries }
  389. WriteResponseFile(false);
  390. { Call linker }
  391. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  392. Replace(cmdstr,'$EXE',current_module.exefilename^);
  393. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  394. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  395. Replace(cmdstr,'$STATIC',StaticStr);
  396. Replace(cmdstr,'$STRIP',StripStr);
  397. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  398. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  399. { Remove ReponseFile }
  400. if (success) and not(cs_link_extern in aktglobalswitches) then
  401. RemoveFile(outputexedir+Info.ResName);
  402. MakeExecutable:=success; { otherwise a recursive call to link method }
  403. end;
  404. Function TLinkerFreeBSD.MakeSharedLibrary:boolean;
  405. var
  406. binstr,
  407. cmdstr : string;
  408. success : boolean;
  409. begin
  410. MakeSharedLibrary:=false;
  411. if not(cs_link_extern in aktglobalswitches) then
  412. Message1(exec_i_linking,current_module.sharedlibfilename^);
  413. { Write used files and libraries }
  414. WriteResponseFile(true);
  415. { Call linker }
  416. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  417. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  418. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  419. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  420. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  421. { Strip the library ? }
  422. if success and (cs_link_strip in aktglobalswitches) then
  423. begin
  424. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  425. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  426. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  427. end;
  428. { Remove ReponseFile }
  429. if (success) and not(cs_link_extern in aktglobalswitches) then
  430. RemoveFile(outputexedir+Info.ResName);
  431. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  432. end;
  433. {*****************************************************************************
  434. Initialize
  435. *****************************************************************************}
  436. initialization
  437. {$ifdef i386}
  438. RegisterExternalLinker(system_i386_FreeBSD_info,TLinkerFreeBSD);
  439. RegisterExternalLinker(system_i386_NetBSD_info,TLinkerFreeBSD);
  440. RegisterImport(system_i386_freebsd,timportlibfreebsd);
  441. RegisterExport(system_i386_freebsd,texportlibfreebsd);
  442. RegisterTarget(system_i386_freebsd_info);
  443. RegisterImport(system_i386_netbsd,timportlibfreebsd);
  444. RegisterExport(system_i386_netbsd,texportlibfreebsd);
  445. RegisterTarget(system_i386_netbsd_info);
  446. {$endif i386}
  447. {$ifdef m68k}
  448. // RegisterExternalLinker(system_m68k_FreeBSD_info,TLinkerFreeBSD);
  449. RegisterExternalLinker(system_m68k_NetBSD_info,TLinkerFreeBSD);
  450. RegisterImport(system_m68k_netbsd,timportlibfreebsd);
  451. RegisterExport(system_m68k_netbsd,texportlibfreebsd);
  452. RegisterTarget(system_m68k_netbsd_info);
  453. {$endif m68k}
  454. end.
  455. {
  456. $Log$
  457. Revision 1.4 2003-04-26 09:16:08 peter
  458. * .o files belonging to the unit are first searched in the same dir
  459. as the .ppu
  460. Revision 1.3 2003/01/18 16:16:13 marco
  461. * Small fix for netbsd
  462. Revision 1.2 2002/09/09 17:34:17 peter
  463. * tdicationary.replace added to replace and item in a dictionary. This
  464. is only allowed for the same name
  465. * varsyms are inserted in symtable before the types are parsed. This
  466. fixes the long standing "var longint : longint" bug
  467. - consume_idlist and idstringlist removed. The loops are inserted
  468. at the callers place and uses the symtable for duplicate id checking
  469. Revision 1.1 2002/09/06 15:03:51 carl
  470. * moved files to systems directory
  471. Revision 1.29 2002/09/03 16:26:28 daniel
  472. * Make Tprocdef.defs protected
  473. Revision 1.28 2002/08/12 15:08:44 carl
  474. + stab register indexes for powerpc (moved from gdb to cpubase)
  475. + tprocessor enumeration moved to cpuinfo
  476. + linker in target_info is now a class
  477. * many many updates for m68k (will soon start to compile)
  478. - removed some ifdef or correct them for correct cpu
  479. Revision 1.27 2002/08/11 14:32:32 peter
  480. * renamed current_library to objectlibrary
  481. Revision 1.26 2002/08/11 13:24:19 peter
  482. * saving of asmsymbols in ppu supported
  483. * asmsymbollist global is removed and moved into a new class
  484. tasmlibrarydata that will hold the info of a .a file which
  485. corresponds with a single module. Added librarydata to tmodule
  486. to keep the library info stored for the module. In the future the
  487. objectfiles will also be stored to the tasmlibrarydata class
  488. * all getlabel/newasmsymbol and friends are moved to the new class
  489. Revision 1.25 2002/07/26 21:15:45 florian
  490. * rewrote the system handling
  491. Revision 1.24 2002/07/24 13:51:34 marco
  492. * Fixed small error
  493. Revision 1.23 2002/07/24 13:10:22 marco
  494. * urgent fix.
  495. Revision 1.22 2002/07/01 18:46:34 peter
  496. * internal linker
  497. * reorganized aasm layer
  498. Revision 1.21 2002/05/18 13:34:26 peter
  499. * readded missing revisions
  500. Revision 1.20 2002/05/16 19:46:53 carl
  501. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  502. + try to fix temp allocation (still in ifdef)
  503. + generic constructor calls
  504. + start of tassembler / tmodulebase class cleanup
  505. Revision 1.18 2002/04/22 18:19:22 carl
  506. - remove use_bound_instruction field
  507. Revision 1.17 2002/04/20 21:43:18 carl
  508. * fix stack size for some targets
  509. + add offset to parameters from frame pointer info.
  510. - remove some unused stuff
  511. Revision 1.16 2002/04/19 15:46:04 peter
  512. * mangledname rewrite, tprocdef.mangledname is now created dynamicly
  513. in most cases and not written to the ppu
  514. * add mangeledname_prefix() routine to generate the prefix of
  515. manglednames depending on the current procedure, object and module
  516. * removed static procprefix since the mangledname is now build only
  517. on demand from tprocdef.mangledname
  518. Revision 1.15 2002/04/15 19:16:57 carl
  519. - remove size_of_pointer field
  520. Revision 1.14 2002/01/29 21:27:34 peter
  521. * default alignment changed to 4 bytes for locals and static const,var
  522. }