t_fbsd.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.inc}
  22. interface
  23. implementation
  24. uses
  25. cutils,cclasses,
  26. verbose,systems,globtype,globals,
  27. symconst,script,
  28. fmodule,aasm,cpuasm,cpubase,symsym,
  29. import,export,link;
  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(const varname,module:string;const name: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(tlinker)
  44. private
  45. Glibc2,
  46. Glibc21 : boolean;
  47. Function WriteResponseFile(isdll:boolean) : Boolean;
  48. public
  49. constructor Create;override;
  50. procedure SetDefaultInfo;override;
  51. function MakeExecutable:boolean;override;
  52. function MakeSharedLibrary:boolean;override;
  53. end;
  54. {*****************************************************************************
  55. TIMPORTLIBLINUX
  56. *****************************************************************************}
  57. procedure timportlibfreebsd.preparelib(const s : string);
  58. begin
  59. end;
  60. procedure timportlibfreebsd.importprocedure(const func,module : string;index : longint;const name : string);
  61. begin
  62. { insert sharedlibrary }
  63. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  64. { do nothing with the procedure, only set the mangledname }
  65. if name<>'' then
  66. aktprocsym.definition.setmangledname(name)
  67. else
  68. message(parser_e_empty_import_name);
  69. end;
  70. procedure timportlibfreebsd.importvariable(const varname,module:string;const name:string);
  71. begin
  72. { insert sharedlibrary }
  73. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  74. { reset the mangledname and turn off the dll_var option }
  75. aktvarsym.setmangledname(name);
  76. exclude(aktvarsym.varoptions,vo_is_dll_var);
  77. end;
  78. procedure timportlibfreebsd.generatelib;
  79. begin
  80. end;
  81. {*****************************************************************************
  82. TEXPORTLIBLINUX
  83. *****************************************************************************}
  84. procedure texportlibfreebsd.preparelib(const s:string);
  85. begin
  86. end;
  87. procedure texportlibfreebsd.exportprocedure(hp : texported_item);
  88. var
  89. hp2 : texported_item;
  90. begin
  91. { first test the index value }
  92. if (hp.options and eo_index)<>0 then
  93. begin
  94. Message1(parser_e_no_export_with_index_for_target,'freebsd');
  95. exit;
  96. end;
  97. { now place in correct order }
  98. hp2:=texported_item(current_module._exports.first);
  99. while assigned(hp2) and
  100. (hp.name^>hp2.name^) do
  101. hp2:=texported_item(hp2.next);
  102. { insert hp there !! }
  103. if assigned(hp2) and (hp2.name^=hp.name^) then
  104. begin
  105. { this is not allowed !! }
  106. Message1(parser_e_export_name_double,hp.name^);
  107. exit;
  108. end;
  109. if hp2=texported_item(current_module._exports.first) then
  110. current_module._exports.concat(hp)
  111. else if assigned(hp2) then
  112. begin
  113. hp.next:=hp2;
  114. hp.previous:=hp2.previous;
  115. if assigned(hp2.previous) then
  116. hp2.previous.next:=hp;
  117. hp2.previous:=hp;
  118. end
  119. else
  120. current_module._exports.concat(hp);
  121. end;
  122. procedure texportlibfreebsd.exportvar(hp : texported_item);
  123. begin
  124. hp.is_var:=true;
  125. exportprocedure(hp);
  126. end;
  127. procedure texportlibfreebsd.generatelib;
  128. var
  129. hp2 : texported_item;
  130. begin
  131. hp2:=texported_item(current_module._exports.first);
  132. while assigned(hp2) do
  133. begin
  134. if not hp2.is_var then
  135. begin
  136. {$ifdef i386}
  137. { place jump in codesegment }
  138. codeSegment.concat(Tai_align.Create_op(4,$90));
  139. codeSegment.concat(Tai_symbol.Createname_global(hp2.name^,0));
  140. codeSegment.concat(Taicpu.Op_sym(A_JMP,S_NO,newasmsymbol(hp2.sym.mangledname)));
  141. codeSegment.concat(Tai_symbol_end.Createname(hp2.name^));
  142. {$endif i386}
  143. end
  144. else
  145. Message1(parser_e_no_export_of_variables_for_target,'freebsd');
  146. hp2:=texported_item(hp2.next);
  147. end;
  148. end;
  149. {*****************************************************************************
  150. TLINKERLINUX
  151. *****************************************************************************}
  152. Constructor TLinkerFreeBSD.Create;
  153. begin
  154. Inherited Create;
  155. LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
  156. end;
  157. procedure TLinkerFreeBSD.SetDefaultInfo;
  158. {
  159. This will also detect which libc version will be used
  160. }
  161. begin
  162. Glibc2:=false;
  163. Glibc21:=false;
  164. with Info do
  165. begin
  166. ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
  167. DllCmd[1]:='ld $OPT -shared -L. -o $EXE $RES';
  168. DllCmd[2]:='strip --strip-unneeded $EXE';
  169. { first try glibc2 }
  170. {$ifndef BSD} {Keep linux code in place. FBSD might go to a different
  171. glibc too once}
  172. DynamicLinker:='/lib/ld-linux.so.2';
  173. if FileExists(DynamicLinker) then
  174. begin
  175. Glibc2:=true;
  176. { Check for 2.0 files, else use the glibc 2.1 stub }
  177. if FileExists('/lib/ld-2.0.*') then
  178. Glibc21:=false
  179. else
  180. Glibc21:=true;
  181. end
  182. else
  183. DynamicLinker:='/lib/ld-linux.so.1';
  184. {$ELSE}
  185. DynamicLinker:='';
  186. {$endif}
  187. end;
  188. end;
  189. Function TLinkerFreeBSD.WriteResponseFile(isdll:boolean) : Boolean;
  190. Var
  191. linkres : TLinkRes;
  192. i : longint;
  193. cprtobj,
  194. gprtobj,
  195. prtobj : string[80];
  196. HPath : TStringListItem;
  197. s,s1,s2 : string;
  198. linkdynamic,
  199. linklibc : boolean;
  200. begin
  201. WriteResponseFile:=False;
  202. { set special options for some targets }
  203. linkdynamic:=not(SharedLibFiles.empty);
  204. linklibc:=(SharedLibFiles.Find('c')<>nil);
  205. prtobj:='prt0';
  206. cprtobj:='cprt0';
  207. gprtobj:='gprt0';
  208. if glibc21 then
  209. begin
  210. cprtobj:='cprt21';
  211. gprtobj:='gprt21';
  212. end;
  213. if cs_profile in aktmoduleswitches then
  214. begin
  215. prtobj:=gprtobj;
  216. if not glibc2 then
  217. AddSharedLibrary('gmon');
  218. AddSharedLibrary('c');
  219. linklibc:=true;
  220. end
  221. else
  222. begin
  223. if linklibc then
  224. prtobj:=cprtobj;
  225. end;
  226. { Open link.res file }
  227. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  228. { Write path to search libraries }
  229. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  230. while assigned(HPath) do
  231. begin
  232. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  233. HPath:=TStringListItem(HPath.Next);
  234. end;
  235. HPath:=TStringListItem(LibrarySearchPath.First);
  236. while assigned(HPath) do
  237. begin
  238. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  239. HPath:=TStringListItem(HPath.Next);
  240. end;
  241. LinkRes.Add('INPUT(');
  242. { add objectfiles, start with prt0 always }
  243. if prtobj<>'' then
  244. LinkRes.AddFileName(FindObjectFile(prtobj,''));
  245. { try to add crti and crtbegin if linking to C }
  246. if linklibc then
  247. begin
  248. if librarysearchpath.FindFile('crtbegin.o',s) then
  249. LinkRes.AddFileName(s);
  250. if librarysearchpath.FindFile('crti.o',s) then
  251. LinkRes.AddFileName(s);
  252. end;
  253. { main objectfiles }
  254. while not ObjectFiles.Empty do
  255. begin
  256. s:=ObjectFiles.GetFirst;
  257. if s<>'' then
  258. LinkRes.AddFileName(s);
  259. end;
  260. LinkRes.Add(')');
  261. { Write staticlibraries }
  262. if not StaticLibFiles.Empty then
  263. begin
  264. LinkRes.Add('GROUP(');
  265. While not StaticLibFiles.Empty do
  266. begin
  267. S:=StaticLibFiles.GetFirst;
  268. LinkRes.AddFileName(s)
  269. end;
  270. LinkRes.Add(')');
  271. end;
  272. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  273. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  274. if not SharedLibFiles.Empty then
  275. begin
  276. LinkRes.Add('INPUT(');
  277. While not SharedLibFiles.Empty do
  278. begin
  279. S:=SharedLibFiles.GetFirst;
  280. if s<>'c' then
  281. begin
  282. i:=Pos(target_info.sharedlibext,S);
  283. if i>0 then
  284. Delete(S,i,255);
  285. LinkRes.Add('-l'+s);
  286. end
  287. else
  288. begin
  289. linklibc:=true;
  290. linkdynamic:=false; { libc will include the ld-linux for us }
  291. end;
  292. end;
  293. { be sure that libc is the last lib }
  294. if linklibc then
  295. LinkRes.Add('-lc');
  296. { when we have -static for the linker the we also need libgcc }
  297. if (cs_link_staticflag in aktglobalswitches) then
  298. LinkRes.Add('-lgcc');
  299. if linkdynamic and (Info.DynamicLinker<>'') then
  300. LinkRes.AddFileName(Info.DynamicLinker);
  301. LinkRes.Add(')');
  302. end;
  303. { objects which must be at the end }
  304. if linklibc then
  305. begin
  306. if librarysearchpath.FindFile('crtend.o',s1) or
  307. librarysearchpath.FindFile('crtn.o',s2) then
  308. begin
  309. LinkRes.Add('INPUT(');
  310. LinkRes.AddFileName(s1);
  311. LinkRes.AddFileName(s2);
  312. LinkRes.Add(')');
  313. end;
  314. end;
  315. { Write and Close response }
  316. linkres.writetodisk;
  317. linkres.Free;
  318. WriteResponseFile:=True;
  319. end;
  320. function TLinkerFreeBSD.MakeExecutable:boolean;
  321. var
  322. binstr,
  323. cmdstr : string;
  324. success : boolean;
  325. DynLinkStr : string[60];
  326. StaticStr,
  327. StripStr : string[40];
  328. begin
  329. if not(cs_link_extern in aktglobalswitches) then
  330. Message1(exec_i_linking,current_module.exefilename^);
  331. { Create some replacements }
  332. StaticStr:='';
  333. StripStr:='';
  334. DynLinkStr:='';
  335. if (cs_link_staticflag in aktglobalswitches) then
  336. StaticStr:='-static';
  337. if (cs_link_strip in aktglobalswitches) then
  338. StripStr:='-s';
  339. If (cs_profile in aktmoduleswitches) or
  340. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  341. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  342. { Write used files and libraries }
  343. WriteResponseFile(false);
  344. { Call linker }
  345. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  346. Replace(cmdstr,'$EXE',current_module.exefilename^);
  347. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  348. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  349. Replace(cmdstr,'$STATIC',StaticStr);
  350. Replace(cmdstr,'$STRIP',StripStr);
  351. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  352. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  353. { Remove ReponseFile }
  354. if (success) and not(cs_link_extern in aktglobalswitches) then
  355. RemoveFile(outputexedir+Info.ResName);
  356. MakeExecutable:=success; { otherwise a recursive call to link method }
  357. end;
  358. Function TLinkerFreeBSD.MakeSharedLibrary:boolean;
  359. var
  360. binstr,
  361. cmdstr : string;
  362. success : boolean;
  363. begin
  364. MakeSharedLibrary:=false;
  365. if not(cs_link_extern in aktglobalswitches) then
  366. Message1(exec_i_linking,current_module.sharedlibfilename^);
  367. { Write used files and libraries }
  368. WriteResponseFile(true);
  369. { Call linker }
  370. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  371. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  372. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  373. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  374. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  375. { Strip the library ? }
  376. if success and (cs_link_strip in aktglobalswitches) then
  377. begin
  378. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  379. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  380. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  381. end;
  382. { Remove ReponseFile }
  383. if (success) and not(cs_link_extern in aktglobalswitches) then
  384. RemoveFile(outputexedir+Info.ResName);
  385. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  386. end;
  387. {*****************************************************************************
  388. Initialize
  389. *****************************************************************************}
  390. const
  391. target_i386_freebsd_info : ttargetinfo =
  392. (
  393. target : target_i386_FreeBSD;
  394. name : 'FreeBSD/ELF for i386';
  395. shortname : 'FreeBSD';
  396. flags : [];
  397. cpu : i386;
  398. unit_env : 'BSDUNITS';
  399. extradefines : 'UNIX;BSD';
  400. sharedlibext : '.so';
  401. staticlibext : '.a';
  402. sourceext : '.pp';
  403. pasext : '.pas';
  404. exeext : '';
  405. defext : '.def';
  406. scriptext : '.sh';
  407. smartext : '.sl';
  408. unitext : '.ppu';
  409. unitlibext : '.ppl';
  410. asmext : '.s';
  411. objext : '.o';
  412. resext : '.res';
  413. resobjext : '.or';
  414. staticlibprefix : 'libp';
  415. sharedlibprefix : 'lib';
  416. Cprefix : '';
  417. newline : #10;
  418. assem : as_i386_elf32;
  419. assemextern : as_i386_as;
  420. link : ld_i386_freebsd;
  421. linkextern : ld_i386_freebsd;
  422. ar : ar_gnu_ar;
  423. res : res_none;
  424. endian : endian_little;
  425. alignment :
  426. (
  427. procalign : 4;
  428. loopalign : 4;
  429. jumpalign : 0;
  430. constalignmin : 0;
  431. constalignmax : 1;
  432. varalignmin : 0;
  433. varalignmax : 1;
  434. localalignmin : 0;
  435. localalignmax : 1;
  436. paraalign : 4;
  437. recordalignmin : 0;
  438. recordalignmax : 2;
  439. maxCrecordalign : 4
  440. );
  441. size_of_pointer : 4;
  442. size_of_longint : 4;
  443. heapsize : 256*1024;
  444. maxheapsize : 32768*1024;
  445. stacksize : 8192;
  446. DllScanSupported:false;
  447. use_bound_instruction : false;
  448. use_function_relative_addresses : true
  449. );
  450. initialization
  451. RegisterLinker(ld_i386_freebsd,TLinkerFreeBSD);
  452. RegisterImport(target_i386_freebsd,timportlibfreebsd);
  453. RegisterExport(target_i386_freebsd,texportlibfreebsd);
  454. RegisterTarget(target_i386_freebsd_info);
  455. end.
  456. {
  457. $Log$
  458. Revision 1.8 2001-07-01 20:16:20 peter
  459. * alignmentinfo record added
  460. * -Oa argument supports more alignment settings that can be specified
  461. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  462. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  463. required alignment and the maximum usefull alignment. The final
  464. alignment will be choosen per variable size dependent on these
  465. settings
  466. Revision 1.7 2001/06/28 19:46:25 peter
  467. * added override and virtual for constructors
  468. Revision 1.6 2001/06/03 15:15:31 peter
  469. * dllprt0 stub for linux shared libs
  470. * pass -init and -fini for linux shared libs
  471. * libprefix splitted into staticlibprefix and sharedlibprefix
  472. Revision 1.5 2001/06/02 19:22:44 peter
  473. * extradefines field added
  474. Revision 1.4 2001/04/21 15:34:01 peter
  475. * fixed writing of end objects to not output an empty INPUT()
  476. Revision 1.3 2001/04/18 22:02:04 peter
  477. * registration of targets and assemblers
  478. Revision 1.2 2001/04/13 01:22:21 peter
  479. * symtable change to classes
  480. * range check generation and errors fixed, make cycle DEBUG=1 works
  481. * memory leaks fixed
  482. Revision 1.1 2001/02/26 19:43:11 peter
  483. * moved target units to subdir
  484. Revision 1.7 2001/02/20 21:41:17 peter
  485. * new fixfilename, findfile for unix. Look first for lowercase, then
  486. NormalCase and last for UPPERCASE names.
  487. Revision 1.6 2000/12/30 22:53:25 peter
  488. * export with the case provided in the exports section
  489. Revision 1.5 2000/12/25 00:07:30 peter
  490. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  491. tlinkedlist objects)
  492. Revision 1.4 2000/10/31 22:02:53 peter
  493. * symtable splitted, no real code changes
  494. Revision 1.3 2000/09/24 21:33:47 peter
  495. * message updates merges
  496. Revision 1.2 2000/09/24 15:12:12 peter
  497. * renamed to be 8.3
  498. Revision 1.2 2000/09/16 12:24:00 peter
  499. * freebsd support routines
  500. }