t_fbsd.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  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. uses
  24. import,export,link;
  25. type
  26. timportlibfreebsd=class(timportlib)
  27. procedure preparelib(const s:string);override;
  28. procedure importprocedure(const func,module:string;index:longint;const name:string);override;
  29. procedure importvariable(const varname,module:string;const name:string);override;
  30. procedure generatelib;override;
  31. end;
  32. texportlibfreebsd=class(texportlib)
  33. procedure preparelib(const s : string);override;
  34. procedure exportprocedure(hp : texported_item);override;
  35. procedure exportvar(hp : texported_item);override;
  36. procedure generatelib;override;
  37. end;
  38. tlinkerfreebsd=class(tlinker)
  39. private
  40. Glibc2,
  41. Glibc21 : boolean;
  42. Function WriteResponseFile(isdll:boolean) : Boolean;
  43. public
  44. constructor Create;
  45. procedure SetDefaultInfo;override;
  46. function MakeExecutable:boolean;override;
  47. function MakeSharedLibrary:boolean;override;
  48. end;
  49. implementation
  50. uses
  51. cutils,cclasses,
  52. verbose,systems,globtype,globals,
  53. symconst,script,
  54. fmodule,aasm,cpuasm,cpubase,symsym;
  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. aktprocsym^.definition^.setmangledname(name)
  68. else
  69. message(parser_e_empty_import_name);
  70. end;
  71. procedure timportlibfreebsd.importvariable(const varname,module:string;const name: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. aktvarsym^.setmangledname(name);
  77. exclude(aktvarsym^.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 then
  136. begin
  137. {$ifdef i386}
  138. { place jump in codesegment }
  139. codeSegment.concat(Tai_align.Create_op(4,$90));
  140. codeSegment.concat(Tai_symbol.Createname_global(hp2.name^,0));
  141. codeSegment.concat(Taicpu.Op_sym(A_JMP,S_NO,newasmsymbol(hp2.sym^.mangledname)));
  142. codeSegment.concat(Tai_symbol_end.Createname(hp2.name^));
  143. {$endif i386}
  144. end
  145. else
  146. Message1(parser_e_no_export_of_variables_for_target,'freebsd');
  147. hp2:=texported_item(hp2.next);
  148. end;
  149. end;
  150. {*****************************************************************************
  151. TLINKERLINUX
  152. *****************************************************************************}
  153. Constructor TLinkerFreeBSD.Create;
  154. begin
  155. Inherited Create;
  156. LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
  157. end;
  158. procedure TLinkerFreeBSD.SetDefaultInfo;
  159. {
  160. This will also detect which libc version will be used
  161. }
  162. begin
  163. Glibc2:=false;
  164. Glibc21:=false;
  165. with Info do
  166. begin
  167. ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
  168. DllCmd[1]:='ld $OPT -shared -L. -o $EXE $RES';
  169. DllCmd[2]:='strip --strip-unneeded $EXE';
  170. { first try glibc2 }
  171. {$ifndef BSD} {Keep linux code in place. FBSD might go to a different
  172. glibc too once}
  173. DynamicLinker:='/lib/ld-linux.so.2';
  174. if FileExists(DynamicLinker) then
  175. begin
  176. Glibc2:=true;
  177. { Check for 2.0 files, else use the glibc 2.1 stub }
  178. if FileExists('/lib/ld-2.0.*') then
  179. Glibc21:=false
  180. else
  181. Glibc21:=true;
  182. end
  183. else
  184. DynamicLinker:='/lib/ld-linux.so.1';
  185. {$ELSE}
  186. DynamicLinker:='';
  187. {$endif}
  188. end;
  189. end;
  190. Function TLinkerFreeBSD.WriteResponseFile(isdll:boolean) : Boolean;
  191. Var
  192. linkres : TLinkRes;
  193. i : longint;
  194. cprtobj,
  195. gprtobj,
  196. prtobj : string[80];
  197. HPath : TStringListItem;
  198. s : string;
  199. linkdynamic,
  200. linklibc : boolean;
  201. begin
  202. WriteResponseFile:=False;
  203. { set special options for some targets }
  204. linkdynamic:=not(SharedLibFiles.empty);
  205. linklibc:=(SharedLibFiles.Find('c')<>nil);
  206. prtobj:='prt0';
  207. cprtobj:='cprt0';
  208. gprtobj:='gprt0';
  209. if glibc21 then
  210. begin
  211. cprtobj:='cprt21';
  212. gprtobj:='gprt21';
  213. end;
  214. if cs_profile in aktmoduleswitches then
  215. begin
  216. prtobj:=gprtobj;
  217. if not glibc2 then
  218. AddSharedLibrary('gmon');
  219. AddSharedLibrary('c');
  220. linklibc:=true;
  221. end
  222. else
  223. begin
  224. if linklibc then
  225. prtobj:=cprtobj;
  226. end;
  227. { Open link.res file }
  228. LinkRes.Init(outputexedir+Info.ResName);
  229. { Write path to search libraries }
  230. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  231. while assigned(HPath) do
  232. begin
  233. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  234. HPath:=TStringListItem(HPath.Next);
  235. end;
  236. HPath:=TStringListItem(LibrarySearchPath.First);
  237. while assigned(HPath) do
  238. begin
  239. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  240. HPath:=TStringListItem(HPath.Next);
  241. end;
  242. LinkRes.Add('INPUT(');
  243. { add objectfiles, start with prt0 always }
  244. if prtobj<>'' then
  245. LinkRes.AddFileName(FindObjectFile(prtobj,''));
  246. { try to add crti and crtbegin if linking to C }
  247. if linklibc then
  248. begin
  249. if librarysearchpath.FindFile('crtbegin.o',s) then
  250. LinkRes.AddFileName(s);
  251. if librarysearchpath.FindFile('crti.o',s) then
  252. LinkRes.AddFileName(s);
  253. end;
  254. { main objectfiles }
  255. while not ObjectFiles.Empty do
  256. begin
  257. s:=ObjectFiles.GetFirst;
  258. if s<>'' then
  259. LinkRes.AddFileName(s);
  260. end;
  261. { objects which must be at the end }
  262. if linklibc then
  263. begin
  264. if librarysearchpath.FindFile('crtend.o',s) then
  265. LinkRes.AddFileName(s);
  266. if librarysearchpath.FindFile('crtn.o',s) then
  267. LinkRes.AddFileName(s);
  268. end;
  269. LinkRes.Add(')');
  270. { Write staticlibraries }
  271. if not StaticLibFiles.Empty then
  272. begin
  273. LinkRes.Add('GROUP(');
  274. While not StaticLibFiles.Empty do
  275. begin
  276. S:=StaticLibFiles.GetFirst;
  277. LinkRes.AddFileName(s)
  278. end;
  279. LinkRes.Add(')');
  280. end;
  281. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  282. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  283. if not SharedLibFiles.Empty then
  284. begin
  285. LinkRes.Add('INPUT(');
  286. While not SharedLibFiles.Empty do
  287. begin
  288. S:=SharedLibFiles.GetFirst;
  289. if s<>'c' then
  290. begin
  291. i:=Pos(target_os.sharedlibext,S);
  292. if i>0 then
  293. Delete(S,i,255);
  294. LinkRes.Add('-l'+s);
  295. end
  296. else
  297. begin
  298. linklibc:=true;
  299. linkdynamic:=false; { libc will include the ld-linux for us }
  300. end;
  301. end;
  302. { be sure that libc is the last lib }
  303. if linklibc then
  304. LinkRes.Add('-lc');
  305. { when we have -static for the linker the we also need libgcc }
  306. if (cs_link_staticflag in aktglobalswitches) then
  307. LinkRes.Add('-lgcc');
  308. if linkdynamic and (Info.DynamicLinker<>'') then
  309. LinkRes.AddFileName(Info.DynamicLinker);
  310. LinkRes.Add(')');
  311. end;
  312. { Write and Close response }
  313. linkres.writetodisk;
  314. linkres.done;
  315. WriteResponseFile:=True;
  316. end;
  317. function TLinkerFreeBSD.MakeExecutable:boolean;
  318. var
  319. binstr,
  320. cmdstr : string;
  321. success : boolean;
  322. DynLinkStr : string[60];
  323. StaticStr,
  324. StripStr : string[40];
  325. begin
  326. if not(cs_link_extern in aktglobalswitches) then
  327. Message1(exec_i_linking,current_module.exefilename^);
  328. { Create some replacements }
  329. StaticStr:='';
  330. StripStr:='';
  331. DynLinkStr:='';
  332. if (cs_link_staticflag in aktglobalswitches) then
  333. StaticStr:='-static';
  334. if (cs_link_strip in aktglobalswitches) then
  335. StripStr:='-s';
  336. If (cs_profile in aktmoduleswitches) or
  337. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  338. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  339. { Write used files and libraries }
  340. WriteResponseFile(false);
  341. { Call linker }
  342. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  343. Replace(cmdstr,'$EXE',current_module.exefilename^);
  344. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  345. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  346. Replace(cmdstr,'$STATIC',StaticStr);
  347. Replace(cmdstr,'$STRIP',StripStr);
  348. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  349. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  350. { Remove ReponseFile }
  351. if (success) and not(cs_link_extern in aktglobalswitches) then
  352. RemoveFile(outputexedir+Info.ResName);
  353. MakeExecutable:=success; { otherwise a recursive call to link method }
  354. end;
  355. Function TLinkerFreeBSD.MakeSharedLibrary:boolean;
  356. var
  357. binstr,
  358. cmdstr : string;
  359. success : boolean;
  360. begin
  361. MakeSharedLibrary:=false;
  362. if not(cs_link_extern in aktglobalswitches) then
  363. Message1(exec_i_linking,current_module.sharedlibfilename^);
  364. { Write used files and libraries }
  365. WriteResponseFile(true);
  366. { Call linker }
  367. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  368. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  369. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  370. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  371. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  372. { Strip the library ? }
  373. if success and (cs_link_strip in aktglobalswitches) then
  374. begin
  375. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  376. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  377. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  378. end;
  379. { Remove ReponseFile }
  380. if (success) and not(cs_link_extern in aktglobalswitches) then
  381. RemoveFile(outputexedir+Info.ResName);
  382. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  383. end;
  384. end.
  385. {
  386. $Log$
  387. Revision 1.1 2001-02-26 19:43:11 peter
  388. * moved target units to subdir
  389. Revision 1.7 2001/02/20 21:41:17 peter
  390. * new fixfilename, findfile for unix. Look first for lowercase, then
  391. NormalCase and last for UPPERCASE names.
  392. Revision 1.6 2000/12/30 22:53:25 peter
  393. * export with the case provided in the exports section
  394. Revision 1.5 2000/12/25 00:07:30 peter
  395. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  396. tlinkedlist objects)
  397. Revision 1.4 2000/10/31 22:02:53 peter
  398. * symtable splitted, no real code changes
  399. Revision 1.3 2000/09/24 21:33:47 peter
  400. * message updates merges
  401. Revision 1.2 2000/09/24 15:12:12 peter
  402. * renamed to be 8.3
  403. Revision 1.2 2000/09/16 12:24:00 peter
  404. * freebsd support routines
  405. }