t_fbsd.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  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;
  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 : 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. { objects which must be at the end }
  261. if linklibc then
  262. begin
  263. if librarysearchpath.FindFile('crtend.o',s) then
  264. LinkRes.AddFileName(s);
  265. if librarysearchpath.FindFile('crtn.o',s) then
  266. LinkRes.AddFileName(s);
  267. end;
  268. LinkRes.Add(')');
  269. { Write staticlibraries }
  270. if not StaticLibFiles.Empty then
  271. begin
  272. LinkRes.Add('GROUP(');
  273. While not StaticLibFiles.Empty do
  274. begin
  275. S:=StaticLibFiles.GetFirst;
  276. LinkRes.AddFileName(s)
  277. end;
  278. LinkRes.Add(')');
  279. end;
  280. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  281. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  282. if not SharedLibFiles.Empty then
  283. begin
  284. LinkRes.Add('INPUT(');
  285. While not SharedLibFiles.Empty do
  286. begin
  287. S:=SharedLibFiles.GetFirst;
  288. if s<>'c' then
  289. begin
  290. i:=Pos(target_info.sharedlibext,S);
  291. if i>0 then
  292. Delete(S,i,255);
  293. LinkRes.Add('-l'+s);
  294. end
  295. else
  296. begin
  297. linklibc:=true;
  298. linkdynamic:=false; { libc will include the ld-linux for us }
  299. end;
  300. end;
  301. { be sure that libc is the last lib }
  302. if linklibc then
  303. LinkRes.Add('-lc');
  304. { when we have -static for the linker the we also need libgcc }
  305. if (cs_link_staticflag in aktglobalswitches) then
  306. LinkRes.Add('-lgcc');
  307. if linkdynamic and (Info.DynamicLinker<>'') then
  308. LinkRes.AddFileName(Info.DynamicLinker);
  309. LinkRes.Add(')');
  310. end;
  311. { Write and Close response }
  312. linkres.writetodisk;
  313. linkres.Free;
  314. WriteResponseFile:=True;
  315. end;
  316. function TLinkerFreeBSD.MakeExecutable:boolean;
  317. var
  318. binstr,
  319. cmdstr : string;
  320. success : boolean;
  321. DynLinkStr : string[60];
  322. StaticStr,
  323. StripStr : string[40];
  324. begin
  325. if not(cs_link_extern in aktglobalswitches) then
  326. Message1(exec_i_linking,current_module.exefilename^);
  327. { Create some replacements }
  328. StaticStr:='';
  329. StripStr:='';
  330. DynLinkStr:='';
  331. if (cs_link_staticflag in aktglobalswitches) then
  332. StaticStr:='-static';
  333. if (cs_link_strip in aktglobalswitches) then
  334. StripStr:='-s';
  335. If (cs_profile in aktmoduleswitches) or
  336. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  337. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  338. { Write used files and libraries }
  339. WriteResponseFile(false);
  340. { Call linker }
  341. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  342. Replace(cmdstr,'$EXE',current_module.exefilename^);
  343. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  344. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  345. Replace(cmdstr,'$STATIC',StaticStr);
  346. Replace(cmdstr,'$STRIP',StripStr);
  347. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  348. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  349. { Remove ReponseFile }
  350. if (success) and not(cs_link_extern in aktglobalswitches) then
  351. RemoveFile(outputexedir+Info.ResName);
  352. MakeExecutable:=success; { otherwise a recursive call to link method }
  353. end;
  354. Function TLinkerFreeBSD.MakeSharedLibrary:boolean;
  355. var
  356. binstr,
  357. cmdstr : string;
  358. success : boolean;
  359. begin
  360. MakeSharedLibrary:=false;
  361. if not(cs_link_extern in aktglobalswitches) then
  362. Message1(exec_i_linking,current_module.sharedlibfilename^);
  363. { Write used files and libraries }
  364. WriteResponseFile(true);
  365. { Call linker }
  366. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  367. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  368. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  369. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  370. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  371. { Strip the library ? }
  372. if success and (cs_link_strip in aktglobalswitches) then
  373. begin
  374. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  375. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  376. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  377. end;
  378. { Remove ReponseFile }
  379. if (success) and not(cs_link_extern in aktglobalswitches) then
  380. RemoveFile(outputexedir+Info.ResName);
  381. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  382. end;
  383. {*****************************************************************************
  384. Initialize
  385. *****************************************************************************}
  386. const
  387. target_i386_freebsd_info : ttargetinfo =
  388. (
  389. target : target_i386_FreeBSD;
  390. name : 'FreeBSD/ELF for i386';
  391. shortname : 'FreeBSD';
  392. flags : [];
  393. cpu : i386;
  394. unit_env : 'BSDUNITS';
  395. sharedlibext : '.so';
  396. staticlibext : '.a';
  397. sourceext : '.pp';
  398. pasext : '.pas';
  399. exeext : '';
  400. defext : '.def';
  401. scriptext : '.sh';
  402. smartext : '.sl';
  403. unitext : '.ppu';
  404. unitlibext : '.ppl';
  405. asmext : '.s';
  406. objext : '.o';
  407. resext : '.res';
  408. resobjext : '.or';
  409. libprefix : 'libp';
  410. Cprefix : '';
  411. newline : #10;
  412. assem : as_i386_elf32;
  413. assemextern : as_i386_as;
  414. link : ld_i386_freebsd;
  415. linkextern : ld_i386_freebsd;
  416. ar : ar_gnu_ar;
  417. res : res_none;
  418. endian : endian_little;
  419. stackalignment : 4;
  420. maxCrecordalignment : 4;
  421. size_of_pointer : 4;
  422. size_of_longint : 4;
  423. heapsize : 256*1024;
  424. maxheapsize : 32768*1024;
  425. stacksize : 8192;
  426. DllScanSupported:false;
  427. use_bound_instruction : false;
  428. use_function_relative_addresses : true
  429. );
  430. initialization
  431. RegisterLinker(ld_i386_freebsd,TLinkerFreeBSD);
  432. RegisterImport(target_i386_freebsd,timportlibfreebsd);
  433. RegisterExport(target_i386_freebsd,texportlibfreebsd);
  434. RegisterTarget(target_i386_freebsd_info);
  435. end.
  436. {
  437. $Log$
  438. Revision 1.3 2001-04-18 22:02:04 peter
  439. * registration of targets and assemblers
  440. Revision 1.2 2001/04/13 01:22:21 peter
  441. * symtable change to classes
  442. * range check generation and errors fixed, make cycle DEBUG=1 works
  443. * memory leaks fixed
  444. Revision 1.1 2001/02/26 19:43:11 peter
  445. * moved target units to subdir
  446. Revision 1.7 2001/02/20 21:41:17 peter
  447. * new fixfilename, findfile for unix. Look first for lowercase, then
  448. NormalCase and last for UPPERCASE names.
  449. Revision 1.6 2000/12/30 22:53:25 peter
  450. * export with the case provided in the exports section
  451. Revision 1.5 2000/12/25 00:07:30 peter
  452. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  453. tlinkedlist objects)
  454. Revision 1.4 2000/10/31 22:02:53 peter
  455. * symtable splitted, no real code changes
  456. Revision 1.3 2000/09/24 21:33:47 peter
  457. * message updates merges
  458. Revision 1.2 2000/09/24 15:12:12 peter
  459. * renamed to be 8.3
  460. Revision 1.2 2000/09/16 12:24:00 peter
  461. * freebsd support routines
  462. }