t_fbsd.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  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. { use pascal name is none specified }
  99. if (hp.options and eo_name)=0 then
  100. begin
  101. hp.name:=stringdup(hp.sym^.name);
  102. hp.options:=hp.options or eo_name;
  103. end;
  104. { now place in correct order }
  105. hp2:=texported_item(current_module._exports.first);
  106. while assigned(hp2) and
  107. (hp.name^>hp2.name^) do
  108. hp2:=texported_item(hp2.next);
  109. { insert hp there !! }
  110. if assigned(hp2) and (hp2.name^=hp.name^) then
  111. begin
  112. { this is not allowed !! }
  113. Message1(parser_e_export_name_double,hp.name^);
  114. exit;
  115. end;
  116. if hp2=texported_item(current_module._exports.first) then
  117. current_module._exports.concat(hp)
  118. else if assigned(hp2) then
  119. begin
  120. hp.next:=hp2;
  121. hp.previous:=hp2.previous;
  122. if assigned(hp2.previous) then
  123. hp2.previous.next:=hp;
  124. hp2.previous:=hp;
  125. end
  126. else
  127. current_module._exports.concat(hp);
  128. end;
  129. procedure texportlibfreebsd.exportvar(hp : texported_item);
  130. begin
  131. hp.is_var:=true;
  132. exportprocedure(hp);
  133. end;
  134. procedure texportlibfreebsd.generatelib;
  135. var
  136. hp2 : texported_item;
  137. begin
  138. hp2:=texported_item(current_module._exports.first);
  139. while assigned(hp2) do
  140. begin
  141. if not hp2.is_var then
  142. begin
  143. {$ifdef i386}
  144. { place jump in codesegment }
  145. codeSegment.concat(Tai_align.Create_op(4,$90));
  146. codeSegment.concat(Tai_symbol.Createname_global(hp2.name^,0));
  147. codeSegment.concat(Taicpu.Op_sym(A_JMP,S_NO,newasmsymbol(hp2.sym^.mangledname)));
  148. codeSegment.concat(Tai_symbol_end.Createname(hp2.name^));
  149. {$endif i386}
  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. with Info do
  172. begin
  173. ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
  174. DllCmd[1]:='ld $OPT -shared -L. -o $EXE $RES';
  175. DllCmd[2]:='strip --strip-unneeded $EXE';
  176. { first try glibc2 }
  177. {$ifndef BSD} {Keep linux code in place. FBSD might go to a different
  178. glibc too once}
  179. DynamicLinker:='/lib/ld-linux.so.2';
  180. if FileExists(DynamicLinker) then
  181. begin
  182. Glibc2:=true;
  183. { Check for 2.0 files, else use the glibc 2.1 stub }
  184. if FileExists('/lib/ld-2.0.*') then
  185. Glibc21:=false
  186. else
  187. Glibc21:=true;
  188. end
  189. else
  190. DynamicLinker:='/lib/ld-linux.so.1';
  191. {$ELSE}
  192. DynamicLinker:='';
  193. {$endif}
  194. end;
  195. end;
  196. Function TLinkerFreeBSD.WriteResponseFile(isdll:boolean) : Boolean;
  197. Var
  198. linkres : TLinkRes;
  199. i : longint;
  200. cprtobj,
  201. gprtobj,
  202. prtobj : string[80];
  203. HPath : TStringListItem;
  204. s : string;
  205. found,
  206. linkdynamic,
  207. linklibc : boolean;
  208. begin
  209. WriteResponseFile:=False;
  210. { set special options for some targets }
  211. linkdynamic:=not(SharedLibFiles.empty);
  212. linklibc:=(SharedLibFiles.Find('c')<>nil);
  213. prtobj:='prt0';
  214. cprtobj:='cprt0';
  215. gprtobj:='gprt0';
  216. if glibc21 then
  217. begin
  218. cprtobj:='cprt21';
  219. gprtobj:='gprt21';
  220. end;
  221. if cs_profile in aktmoduleswitches then
  222. begin
  223. prtobj:=gprtobj;
  224. if not glibc2 then
  225. AddSharedLibrary('gmon');
  226. AddSharedLibrary('c');
  227. linklibc:=true;
  228. end
  229. else
  230. begin
  231. if linklibc then
  232. prtobj:=cprtobj;
  233. end;
  234. { Open link.res file }
  235. LinkRes.Init(outputexedir+Info.ResName);
  236. { Write path to search libraries }
  237. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  238. while assigned(HPath) do
  239. begin
  240. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  241. HPath:=TStringListItem(HPath.Next);
  242. end;
  243. HPath:=TStringListItem(LibrarySearchPath.First);
  244. while assigned(HPath) do
  245. begin
  246. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  247. HPath:=TStringListItem(HPath.Next);
  248. end;
  249. LinkRes.Add('INPUT(');
  250. { add objectfiles, start with prt0 always }
  251. if prtobj<>'' then
  252. LinkRes.AddFileName(FindObjectFile(prtobj,''));
  253. { try to add crti and crtbegin if linking to C }
  254. if linklibc then
  255. begin
  256. s:=librarysearchpath.FindFile('crtbegin.o',found)+'crtbegin.o';
  257. if found then
  258. LinkRes.AddFileName(s);
  259. s:=librarysearchpath.FindFile('crti.o',found)+'crti.o';
  260. if found then
  261. LinkRes.AddFileName(s);
  262. end;
  263. { main objectfiles }
  264. while not ObjectFiles.Empty do
  265. begin
  266. s:=ObjectFiles.GetFirst;
  267. if s<>'' then
  268. LinkRes.AddFileName(s);
  269. end;
  270. { objects which must be at the end }
  271. if linklibc then
  272. begin
  273. s:=librarysearchpath.FindFile('crtend.o',found)+'crtend.o';
  274. if found then
  275. LinkRes.AddFileName(s);
  276. s:=librarysearchpath.FindFile('crtn.o',found)+'crtn.o';
  277. if found then
  278. LinkRes.AddFileName(s);
  279. end;
  280. LinkRes.Add(')');
  281. { Write staticlibraries }
  282. if not StaticLibFiles.Empty then
  283. begin
  284. LinkRes.Add('GROUP(');
  285. While not StaticLibFiles.Empty do
  286. begin
  287. S:=StaticLibFiles.GetFirst;
  288. LinkRes.AddFileName(s)
  289. end;
  290. LinkRes.Add(')');
  291. end;
  292. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  293. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  294. if not SharedLibFiles.Empty then
  295. begin
  296. LinkRes.Add('INPUT(');
  297. While not SharedLibFiles.Empty do
  298. begin
  299. S:=SharedLibFiles.GetFirst;
  300. if s<>'c' then
  301. begin
  302. i:=Pos(target_os.sharedlibext,S);
  303. if i>0 then
  304. Delete(S,i,255);
  305. LinkRes.Add('-l'+s);
  306. end
  307. else
  308. begin
  309. linklibc:=true;
  310. linkdynamic:=false; { libc will include the ld-linux for us }
  311. end;
  312. end;
  313. { be sure that libc is the last lib }
  314. if linklibc then
  315. LinkRes.Add('-lc');
  316. { when we have -static for the linker the we also need libgcc }
  317. if (cs_link_staticflag in aktglobalswitches) then
  318. LinkRes.Add('-lgcc');
  319. if linkdynamic and (Info.DynamicLinker<>'') then
  320. LinkRes.AddFileName(Info.DynamicLinker);
  321. LinkRes.Add(')');
  322. end;
  323. { Write and Close response }
  324. linkres.writetodisk;
  325. linkres.done;
  326. WriteResponseFile:=True;
  327. end;
  328. function TLinkerFreeBSD.MakeExecutable:boolean;
  329. var
  330. binstr,
  331. cmdstr : string;
  332. success : boolean;
  333. DynLinkStr : string[60];
  334. StaticStr,
  335. StripStr : string[40];
  336. begin
  337. if not(cs_link_extern in aktglobalswitches) then
  338. Message1(exec_i_linking,current_module.exefilename^);
  339. { Create some replacements }
  340. StaticStr:='';
  341. StripStr:='';
  342. DynLinkStr:='';
  343. if (cs_link_staticflag in aktglobalswitches) then
  344. StaticStr:='-static';
  345. if (cs_link_strip in aktglobalswitches) then
  346. StripStr:='-s';
  347. If (cs_profile in aktmoduleswitches) or
  348. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  349. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  350. { Write used files and libraries }
  351. WriteResponseFile(false);
  352. { Call linker }
  353. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  354. Replace(cmdstr,'$EXE',current_module.exefilename^);
  355. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  356. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  357. Replace(cmdstr,'$STATIC',StaticStr);
  358. Replace(cmdstr,'$STRIP',StripStr);
  359. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  360. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  361. { Remove ReponseFile }
  362. if (success) and not(cs_link_extern in aktglobalswitches) then
  363. RemoveFile(outputexedir+Info.ResName);
  364. MakeExecutable:=success; { otherwise a recursive call to link method }
  365. end;
  366. Function TLinkerFreeBSD.MakeSharedLibrary:boolean;
  367. var
  368. binstr,
  369. cmdstr : string;
  370. success : boolean;
  371. begin
  372. MakeSharedLibrary:=false;
  373. if not(cs_link_extern in aktglobalswitches) then
  374. Message1(exec_i_linking,current_module.sharedlibfilename^);
  375. { Write used files and libraries }
  376. WriteResponseFile(true);
  377. { Call linker }
  378. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  379. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  380. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  381. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  382. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  383. { Strip the library ? }
  384. if success and (cs_link_strip in aktglobalswitches) then
  385. begin
  386. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  387. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  388. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  389. end;
  390. { Remove ReponseFile }
  391. if (success) and not(cs_link_extern in aktglobalswitches) then
  392. RemoveFile(outputexedir+Info.ResName);
  393. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  394. end;
  395. end.
  396. {
  397. $Log$
  398. Revision 1.5 2000-12-25 00:07:30 peter
  399. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  400. tlinkedlist objects)
  401. Revision 1.4 2000/10/31 22:02:53 peter
  402. * symtable splitted, no real code changes
  403. Revision 1.3 2000/09/24 21:33:47 peter
  404. * message updates merges
  405. Revision 1.2 2000/09/24 15:12:12 peter
  406. * renamed to be 8.3
  407. Revision 1.2 2000/09/16 12:24:00 peter
  408. * freebsd support routines
  409. }