t_freebsd.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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_freebsd;
  21. interface
  22. uses
  23. import,export,link;
  24. type
  25. pimportlibfreebsd=^timportlibfreebsd;
  26. timportlibfreebsd=object(timportlib)
  27. procedure preparelib(const s:string);virtual;
  28. procedure importprocedure(const func,module:string;index:longint;const name:string);virtual;
  29. procedure importvariable(const varname,module:string;const name:string);virtual;
  30. procedure generatelib;virtual;
  31. end;
  32. pexportlibfreebsd=^texportlibfreebsd;
  33. texportlibfreebsd=object(texportlib)
  34. procedure preparelib(const s : string);virtual;
  35. procedure exportprocedure(hp : pexported_item);virtual;
  36. procedure exportvar(hp : pexported_item);virtual;
  37. procedure generatelib;virtual;
  38. end;
  39. plinkerfreebsd=^tlinkerfreebsd;
  40. tlinkerfreebsd=object(tlinker)
  41. private
  42. Glibc2,
  43. Glibc21 : boolean;
  44. Function WriteResponseFile(isdll:boolean) : Boolean;
  45. public
  46. constructor Init;
  47. procedure SetDefaultInfo;virtual;
  48. function MakeExecutable:boolean;virtual;
  49. function MakeSharedLibrary:boolean;virtual;
  50. end;
  51. implementation
  52. uses
  53. cutils,verbose,strings,cobjects,systems,globtype,globals,
  54. symconst,script,
  55. fmodule,aasm,cpuasm,cpubase,symtable{$IFDEF NEWST},symbols{$ENDIF NEWST};
  56. {*****************************************************************************
  57. TIMPORTLIBLINUX
  58. *****************************************************************************}
  59. procedure timportlibfreebsd.preparelib(const s : string);
  60. begin
  61. end;
  62. procedure timportlibfreebsd.importprocedure(const func,module : string;index : longint;const name : string);
  63. begin
  64. { insert sharedlibrary }
  65. {$IFDEF NEWST}
  66. current_module^.linkothersharedlibs.
  67. insert(new(Plinkitem,init(SplitName(module),link_allways)));
  68. { do nothing with the procedure, only set the mangledname }
  69. if name<>'' then
  70. aktprocdef^.setmangledname(name)
  71. else
  72. message(parser_e_empty_import_name);
  73. {$ELSE}
  74. current_module^.linkothersharedlibs.
  75. insert(SplitName(module),link_allways);
  76. { do nothing with the procedure, only set the mangledname }
  77. if name<>'' then
  78. aktprocsym^.definition^.setmangledname(name)
  79. else
  80. message(parser_e_empty_import_name);
  81. {$ENDIF NEWST}
  82. end;
  83. procedure timportlibfreebsd.importvariable(const varname,module:string;const name:string);
  84. begin
  85. { insert sharedlibrary }
  86. {$IFDEF NEWST}
  87. current_module^.linkothersharedlibs.
  88. insert(new(Plinkitem,init(SplitName(module),link_allways)));
  89. {$ELSE}
  90. current_module^.linkothersharedlibs.
  91. insert(SplitName(module),link_allways);
  92. {$ENDIF NEWST}
  93. { reset the mangledname and turn off the dll_var option }
  94. aktvarsym^.setmangledname(name);
  95. {$IFDEF NEWST}
  96. exclude(aktvarsym^.properties,vo_is_dll_var);
  97. {$ELSE}
  98. {$ifdef INCLUDEOK}
  99. exclude(aktvarsym^.varoptions,vo_is_dll_var);
  100. {$else}
  101. aktvarsym^.varoptions:=aktvarsym^.varoptions-[vo_is_dll_var];
  102. {$endif}
  103. {$ENDIF NEWST}
  104. end;
  105. procedure timportlibfreebsd.generatelib;
  106. begin
  107. end;
  108. {*****************************************************************************
  109. TEXPORTLIBLINUX
  110. *****************************************************************************}
  111. procedure texportlibfreebsd.preparelib(const s:string);
  112. begin
  113. end;
  114. procedure texportlibfreebsd.exportprocedure(hp : pexported_item);
  115. var
  116. hp2 : pexported_item;
  117. begin
  118. { first test the index value }
  119. if (hp^.options and eo_index)<>0 then
  120. begin
  121. Comment(V_Error,'can''t export with index under linux');
  122. exit;
  123. end;
  124. { use pascal name is none specified }
  125. if (hp^.options and eo_name)=0 then
  126. begin
  127. hp^.name:=stringdup(hp^.sym^.name);
  128. hp^.options:=hp^.options or eo_name;
  129. end;
  130. { now place in correct order }
  131. hp2:=pexported_item(current_module^._exports^.first);
  132. while assigned(hp2) and
  133. (hp^.name^>hp2^.name^) do
  134. hp2:=pexported_item(hp2^.next);
  135. { insert hp there !! }
  136. if assigned(hp2) and (hp2^.name^=hp^.name^) then
  137. begin
  138. { this is not allowed !! }
  139. Message1(parser_e_export_name_double,hp^.name^);
  140. exit;
  141. end;
  142. if hp2=pexported_item(current_module^._exports^.first) then
  143. current_module^._exports^.insert(hp)
  144. else if assigned(hp2) then
  145. begin
  146. hp^.next:=hp2;
  147. hp^.previous:=hp2^.previous;
  148. if assigned(hp2^.previous) then
  149. hp2^.previous^.next:=hp;
  150. hp2^.previous:=hp;
  151. end
  152. else
  153. current_module^._exports^.concat(hp);
  154. end;
  155. procedure texportlibfreebsd.exportvar(hp : pexported_item);
  156. begin
  157. hp^.is_var:=true;
  158. exportprocedure(hp);
  159. end;
  160. procedure texportlibfreebsd.generatelib;
  161. var
  162. hp2 : pexported_item;
  163. begin
  164. hp2:=pexported_item(current_module^._exports^.first);
  165. while assigned(hp2) do
  166. begin
  167. if not hp2^.is_var then
  168. begin
  169. {$ifdef i386}
  170. { place jump in codesegment }
  171. codesegment^.concat(new(pai_align,init_op(4,$90)));
  172. codesegment^.concat(new(pai_symbol,initname_global(hp2^.name^,0)));
  173. codesegment^.concat(new(paicpu,op_sym(A_JMP,S_NO,newasmsymbol(hp2^.sym^.mangledname))));
  174. codesegment^.concat(new(pai_symbol_end,initname(hp2^.name^)));
  175. {$endif i386}
  176. end
  177. else
  178. Comment(V_Error,'Exporting of variables is not supported under linux');
  179. hp2:=pexported_item(hp2^.next);
  180. end;
  181. end;
  182. {*****************************************************************************
  183. TLINKERLINUX
  184. *****************************************************************************}
  185. Constructor TLinkerFreeBSD.Init;
  186. begin
  187. Inherited Init;
  188. LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
  189. end;
  190. procedure TLinkerFreeBSD.SetDefaultInfo;
  191. {
  192. This will also detect which libc version will be used
  193. }
  194. begin
  195. Glibc2:=false;
  196. Glibc21:=false;
  197. with Info do
  198. begin
  199. ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
  200. DllCmd[1]:='ld $OPT -shared -L. -o $EXE $RES';
  201. DllCmd[2]:='strip --strip-unneeded $EXE';
  202. { first try glibc2 }
  203. {$ifndef BSD} {Keep linux code in place. FBSD might go to a different
  204. glibc too once}
  205. DynamicLinker:='/lib/ld-linux.so.2';
  206. if FileExists(DynamicLinker) then
  207. begin
  208. Glibc2:=true;
  209. { Check for 2.0 files, else use the glibc 2.1 stub }
  210. if FileExists('/lib/ld-2.0.*') then
  211. Glibc21:=false
  212. else
  213. Glibc21:=true;
  214. end
  215. else
  216. DynamicLinker:='/lib/ld-linux.so.1';
  217. {$ELSE}
  218. DynamicLinker:='';
  219. {$endif}
  220. end;
  221. end;
  222. Function TLinkerFreeBSD.WriteResponseFile(isdll:boolean) : Boolean;
  223. Var
  224. linkres : TLinkRes;
  225. i : longint;
  226. cprtobj,
  227. gprtobj,
  228. prtobj : string[80];
  229. {$IFDEF NEWST}
  230. HPath : PStringItem;
  231. {$ELSE}
  232. HPath : PStringQueueItem;
  233. {$ENDIF NEWST}
  234. s : string;
  235. found,
  236. linkdynamic,
  237. linklibc : boolean;
  238. begin
  239. WriteResponseFile:=False;
  240. { set special options for some targets }
  241. linkdynamic:=not(SharedLibFiles.empty);
  242. linklibc:=SharedLibFiles.Find('c');
  243. prtobj:='prt0';
  244. cprtobj:='cprt0';
  245. gprtobj:='gprt0';
  246. if glibc21 then
  247. begin
  248. cprtobj:='cprt21';
  249. gprtobj:='gprt21';
  250. end;
  251. if cs_profile in aktmoduleswitches then
  252. begin
  253. prtobj:=gprtobj;
  254. if not glibc2 then
  255. AddSharedLibrary('gmon');
  256. AddSharedLibrary('c');
  257. linklibc:=true;
  258. end
  259. else
  260. begin
  261. if linklibc then
  262. prtobj:=cprtobj;
  263. end;
  264. { Open link.res file }
  265. LinkRes.Init(outputexedir+Info.ResName);
  266. { Write path to search libraries }
  267. HPath:=current_module^.locallibrarysearchpath.First;
  268. while assigned(HPath) do
  269. begin
  270. LinkRes.Add('SEARCH_DIR('+HPath^.Data^+')');
  271. HPath:=HPath^.Next;
  272. end;
  273. HPath:=LibrarySearchPath.First;
  274. while assigned(HPath) do
  275. begin
  276. LinkRes.Add('SEARCH_DIR('+HPath^.Data^+')');
  277. HPath:=HPath^.Next;
  278. end;
  279. LinkRes.Add('INPUT(');
  280. { add objectfiles, start with prt0 always }
  281. if prtobj<>'' then
  282. LinkRes.AddFileName(FindObjectFile(prtobj,''));
  283. { try to add crti and crtbegin if linking to C }
  284. if linklibc then
  285. begin
  286. s:=librarysearchpath.FindFile('crtbegin.o',found)+'crtbegin.o';
  287. if found then
  288. LinkRes.AddFileName(s);
  289. s:=librarysearchpath.FindFile('crti.o',found)+'crti.o';
  290. if found then
  291. LinkRes.AddFileName(s);
  292. end;
  293. { main objectfiles }
  294. while not ObjectFiles.Empty do
  295. begin
  296. s:=ObjectFiles.Get;
  297. if s<>'' then
  298. LinkRes.AddFileName(s);
  299. end;
  300. { objects which must be at the end }
  301. if linklibc then
  302. begin
  303. s:=librarysearchpath.FindFile('crtend.o',found)+'crtend.o';
  304. if found then
  305. LinkRes.AddFileName(s);
  306. s:=librarysearchpath.FindFile('crtn.o',found)+'crtn.o';
  307. if found then
  308. LinkRes.AddFileName(s);
  309. end;
  310. LinkRes.Add(')');
  311. { Write staticlibraries }
  312. if not StaticLibFiles.Empty then
  313. begin
  314. LinkRes.Add('GROUP(');
  315. While not StaticLibFiles.Empty do
  316. begin
  317. S:=StaticLibFiles.Get;
  318. LinkRes.AddFileName(s)
  319. end;
  320. LinkRes.Add(')');
  321. end;
  322. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  323. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  324. if not SharedLibFiles.Empty then
  325. begin
  326. LinkRes.Add('INPUT(');
  327. While not SharedLibFiles.Empty do
  328. begin
  329. S:=SharedLibFiles.Get;
  330. if s<>'c' then
  331. begin
  332. i:=Pos(target_os.sharedlibext,S);
  333. if i>0 then
  334. Delete(S,i,255);
  335. LinkRes.Add('-l'+s);
  336. end
  337. else
  338. begin
  339. linklibc:=true;
  340. linkdynamic:=false; { libc will include the ld-linux for us }
  341. end;
  342. end;
  343. { be sure that libc is the last lib }
  344. if linklibc then
  345. LinkRes.Add('-lc');
  346. { when we have -static for the linker the we also need libgcc }
  347. if (cs_link_staticflag in aktglobalswitches) then
  348. LinkRes.Add('-lgcc');
  349. if linkdynamic and (Info.DynamicLinker<>'') then
  350. LinkRes.AddFileName(Info.DynamicLinker);
  351. LinkRes.Add(')');
  352. end;
  353. { Write and Close response }
  354. linkres.writetodisk;
  355. linkres.done;
  356. WriteResponseFile:=True;
  357. end;
  358. function TLinkerFreeBSD.MakeExecutable:boolean;
  359. var
  360. binstr,
  361. cmdstr : string;
  362. success : boolean;
  363. DynLinkStr : string[60];
  364. StaticStr,
  365. StripStr : string[40];
  366. begin
  367. if not(cs_link_extern in aktglobalswitches) then
  368. Message1(exec_i_linking,current_module^.exefilename^);
  369. { Create some replacements }
  370. StaticStr:='';
  371. StripStr:='';
  372. DynLinkStr:='';
  373. if (cs_link_staticflag in aktglobalswitches) then
  374. StaticStr:='-static';
  375. if (cs_link_strip in aktglobalswitches) then
  376. StripStr:='-s';
  377. If (cs_profile in aktmoduleswitches) or
  378. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  379. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  380. { Write used files and libraries }
  381. WriteResponseFile(false);
  382. { Call linker }
  383. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  384. Replace(cmdstr,'$EXE',current_module^.exefilename^);
  385. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  386. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  387. Replace(cmdstr,'$STATIC',StaticStr);
  388. Replace(cmdstr,'$STRIP',StripStr);
  389. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  390. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  391. { Remove ReponseFile }
  392. if (success) and not(cs_link_extern in aktglobalswitches) then
  393. RemoveFile(outputexedir+Info.ResName);
  394. MakeExecutable:=success; { otherwise a recursive call to link method }
  395. end;
  396. Function TLinkerFreeBSD.MakeSharedLibrary:boolean;
  397. var
  398. binstr,
  399. cmdstr : string;
  400. success : boolean;
  401. begin
  402. MakeSharedLibrary:=false;
  403. if not(cs_link_extern in aktglobalswitches) then
  404. Message1(exec_i_linking,current_module^.sharedlibfilename^);
  405. { Write used files and libraries }
  406. WriteResponseFile(true);
  407. { Call linker }
  408. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  409. Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
  410. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  411. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  412. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  413. { Strip the library ? }
  414. if success and (cs_link_strip in aktglobalswitches) then
  415. begin
  416. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  417. Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
  418. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  419. end;
  420. { Remove ReponseFile }
  421. if (success) and not(cs_link_extern in aktglobalswitches) then
  422. RemoveFile(outputexedir+Info.ResName);
  423. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  424. end;
  425. end.
  426. {
  427. $Log$
  428. Revision 1.2 2000-09-16 12:24:00 peter
  429. * freebsd support routines
  430. Revision 1.1.2.1 2000/09/13 14:08:28 marco
  431. Initial FreeBSD version
  432. Revision 1.1.2.1 2000/09/10 16:11:59 marco
  433. Dynamic linker name is always empty for BSD
  434. Revision 1.1 2000/07/13 06:29:57 michael
  435. + Initial import
  436. Revision 1.15 2000/07/08 20:43:38 peter
  437. * findobjectfile gets extra arg with directory where the unit is found
  438. and the .o should be looked first
  439. Revision 1.14 2000/03/21 21:36:52 peter
  440. * only include crtbegin when linking to libc
  441. Revision 1.13 2000/03/12 08:24:03 daniel
  442. * Modification for new symtable
  443. Revision 1.12 2000/03/02 13:12:37 daniel
  444. * Removed a comment to fix gtk.
  445. Revision 1.11 2000/02/28 17:23:57 daniel
  446. * Current work of symtable integration committed. The symtable can be
  447. activated by defining 'newst', but doesn't compile yet. Changes in type
  448. checking and oop are completed. What is left is to write a new
  449. symtablestack and adapt the parser to use it.
  450. Revision 1.10 2000/02/27 14:46:04 peter
  451. * check for ld-so.2.0.* then no glibc21 is used, else glibc21 is used
  452. Revision 1.9 2000/02/09 10:35:48 peter
  453. * -Xt option to link staticly against c libs
  454. Revision 1.8 2000/01/11 09:52:07 peter
  455. * fixed placing of .sl directories
  456. * use -b again for base-file selection
  457. * fixed group writing for linux with smartlinking
  458. Revision 1.7 2000/01/09 00:55:51 pierre
  459. * GROUP of smartlink units put before the C libraries
  460. to allow for smartlinking code that uses C code.
  461. Revision 1.6 2000/01/07 01:14:42 peter
  462. * updated copyright to 2000
  463. Revision 1.5 1999/11/16 23:39:04 peter
  464. * use outputexedir for link.res location
  465. Revision 1.4 1999/11/12 11:03:50 peter
  466. * searchpaths changed to stringqueue object
  467. Revision 1.3 1999/11/05 13:15:00 florian
  468. * some fixes to get the new cg compiling again
  469. Revision 1.2 1999/11/04 10:55:31 peter
  470. * TSearchPathString for the string type of the searchpaths, which is
  471. ansistring under FPC/Delphi
  472. Revision 1.1 1999/10/21 14:29:38 peter
  473. * redesigned linker object
  474. + library support for linux (only procedures can be exported)
  475. }