t_fbsd.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  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. pimportlibfreebsd=^timportlibfreebsd;
  27. timportlibfreebsd=object(timportlib)
  28. procedure preparelib(const s:string);virtual;
  29. procedure importprocedure(const func,module:string;index:longint;const name:string);virtual;
  30. procedure importvariable(const varname,module:string;const name:string);virtual;
  31. procedure generatelib;virtual;
  32. end;
  33. pexportlibfreebsd=^texportlibfreebsd;
  34. texportlibfreebsd=object(texportlib)
  35. procedure preparelib(const s : string);virtual;
  36. procedure exportprocedure(hp : pexported_item);virtual;
  37. procedure exportvar(hp : pexported_item);virtual;
  38. procedure generatelib;virtual;
  39. end;
  40. plinkerfreebsd=^tlinkerfreebsd;
  41. tlinkerfreebsd=object(tlinker)
  42. private
  43. Glibc2,
  44. Glibc21 : boolean;
  45. Function WriteResponseFile(isdll:boolean) : Boolean;
  46. public
  47. constructor Init;
  48. procedure SetDefaultInfo;virtual;
  49. function MakeExecutable:boolean;virtual;
  50. function MakeSharedLibrary:boolean;virtual;
  51. end;
  52. implementation
  53. uses
  54. cutils,verbose,cobjects,systems,globtype,globals,
  55. symconst,script,
  56. fmodule,aasm,cpuasm,cpubase,symtable{$IFDEF NEWST},symbols{$ENDIF NEWST};
  57. {*****************************************************************************
  58. TIMPORTLIBLINUX
  59. *****************************************************************************}
  60. procedure timportlibfreebsd.preparelib(const s : string);
  61. begin
  62. end;
  63. procedure timportlibfreebsd.importprocedure(const func,module : string;index : longint;const name : string);
  64. begin
  65. { insert sharedlibrary }
  66. current_module^.linkothersharedlibs.insert(SplitName(module),link_allways);
  67. { do nothing with the procedure, only set the mangledname }
  68. if name<>'' then
  69. aktprocsym^.definition^.setmangledname(name)
  70. else
  71. message(parser_e_empty_import_name);
  72. end;
  73. procedure timportlibfreebsd.importvariable(const varname,module:string;const name:string);
  74. begin
  75. { insert sharedlibrary }
  76. current_module^.linkothersharedlibs.insert(SplitName(module),link_allways);
  77. { reset the mangledname and turn off the dll_var option }
  78. aktvarsym^.setmangledname(name);
  79. exclude(aktvarsym^.varoptions,vo_is_dll_var);
  80. end;
  81. procedure timportlibfreebsd.generatelib;
  82. begin
  83. end;
  84. {*****************************************************************************
  85. TEXPORTLIBLINUX
  86. *****************************************************************************}
  87. procedure texportlibfreebsd.preparelib(const s:string);
  88. begin
  89. end;
  90. procedure texportlibfreebsd.exportprocedure(hp : pexported_item);
  91. var
  92. hp2 : pexported_item;
  93. begin
  94. { first test the index value }
  95. if (hp^.options and eo_index)<>0 then
  96. begin
  97. Message1(parser_e_no_export_with_index_for_target,'freebsd');
  98. exit;
  99. end;
  100. { use pascal name is none specified }
  101. if (hp^.options and eo_name)=0 then
  102. begin
  103. hp^.name:=stringdup(hp^.sym^.name);
  104. hp^.options:=hp^.options or eo_name;
  105. end;
  106. { now place in correct order }
  107. hp2:=pexported_item(current_module^._exports^.first);
  108. while assigned(hp2) and
  109. (hp^.name^>hp2^.name^) do
  110. hp2:=pexported_item(hp2^.next);
  111. { insert hp there !! }
  112. if assigned(hp2) and (hp2^.name^=hp^.name^) then
  113. begin
  114. { this is not allowed !! }
  115. Message1(parser_e_export_name_double,hp^.name^);
  116. exit;
  117. end;
  118. if hp2=pexported_item(current_module^._exports^.first) then
  119. current_module^._exports^.insert(hp)
  120. else if assigned(hp2) then
  121. begin
  122. hp^.next:=hp2;
  123. hp^.previous:=hp2^.previous;
  124. if assigned(hp2^.previous) then
  125. hp2^.previous^.next:=hp;
  126. hp2^.previous:=hp;
  127. end
  128. else
  129. current_module^._exports^.concat(hp);
  130. end;
  131. procedure texportlibfreebsd.exportvar(hp : pexported_item);
  132. begin
  133. hp^.is_var:=true;
  134. exportprocedure(hp);
  135. end;
  136. procedure texportlibfreebsd.generatelib;
  137. var
  138. hp2 : pexported_item;
  139. begin
  140. hp2:=pexported_item(current_module^._exports^.first);
  141. while assigned(hp2) do
  142. begin
  143. if not hp2^.is_var then
  144. begin
  145. {$ifdef i386}
  146. { place jump in codesegment }
  147. codesegment^.concat(new(pai_align,init_op(4,$90)));
  148. codesegment^.concat(new(pai_symbol,initname_global(hp2^.name^,0)));
  149. codesegment^.concat(new(paicpu,op_sym(A_JMP,S_NO,newasmsymbol(hp2^.sym^.mangledname))));
  150. codesegment^.concat(new(pai_symbol_end,initname(hp2^.name^)));
  151. {$endif i386}
  152. end
  153. else
  154. Message1(parser_e_no_export_of_variables_for_target,'freebsd');
  155. hp2:=pexported_item(hp2^.next);
  156. end;
  157. end;
  158. {*****************************************************************************
  159. TLINKERLINUX
  160. *****************************************************************************}
  161. Constructor TLinkerFreeBSD.Init;
  162. begin
  163. Inherited Init;
  164. LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib',true);
  165. end;
  166. procedure TLinkerFreeBSD.SetDefaultInfo;
  167. {
  168. This will also detect which libc version will be used
  169. }
  170. begin
  171. Glibc2:=false;
  172. Glibc21:=false;
  173. with Info do
  174. begin
  175. ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
  176. DllCmd[1]:='ld $OPT -shared -L. -o $EXE $RES';
  177. DllCmd[2]:='strip --strip-unneeded $EXE';
  178. { first try glibc2 }
  179. {$ifndef BSD} {Keep linux code in place. FBSD might go to a different
  180. glibc too once}
  181. DynamicLinker:='/lib/ld-linux.so.2';
  182. if FileExists(DynamicLinker) then
  183. begin
  184. Glibc2:=true;
  185. { Check for 2.0 files, else use the glibc 2.1 stub }
  186. if FileExists('/lib/ld-2.0.*') then
  187. Glibc21:=false
  188. else
  189. Glibc21:=true;
  190. end
  191. else
  192. DynamicLinker:='/lib/ld-linux.so.1';
  193. {$ELSE}
  194. DynamicLinker:='';
  195. {$endif}
  196. end;
  197. end;
  198. Function TLinkerFreeBSD.WriteResponseFile(isdll:boolean) : Boolean;
  199. Var
  200. linkres : TLinkRes;
  201. i : longint;
  202. cprtobj,
  203. gprtobj,
  204. prtobj : string[80];
  205. HPath : PStringQueueItem;
  206. s : string;
  207. found,
  208. linkdynamic,
  209. linklibc : boolean;
  210. begin
  211. WriteResponseFile:=False;
  212. { set special options for some targets }
  213. linkdynamic:=not(SharedLibFiles.empty);
  214. linklibc:=SharedLibFiles.Find('c');
  215. prtobj:='prt0';
  216. cprtobj:='cprt0';
  217. gprtobj:='gprt0';
  218. if glibc21 then
  219. begin
  220. cprtobj:='cprt21';
  221. gprtobj:='gprt21';
  222. end;
  223. if cs_profile in aktmoduleswitches then
  224. begin
  225. prtobj:=gprtobj;
  226. if not glibc2 then
  227. AddSharedLibrary('gmon');
  228. AddSharedLibrary('c');
  229. linklibc:=true;
  230. end
  231. else
  232. begin
  233. if linklibc then
  234. prtobj:=cprtobj;
  235. end;
  236. { Open link.res file }
  237. LinkRes.Init(outputexedir+Info.ResName);
  238. { Write path to search libraries }
  239. HPath:=current_module^.locallibrarysearchpath.First;
  240. while assigned(HPath) do
  241. begin
  242. LinkRes.Add('SEARCH_DIR('+HPath^.Data^+')');
  243. HPath:=HPath^.Next;
  244. end;
  245. HPath:=LibrarySearchPath.First;
  246. while assigned(HPath) do
  247. begin
  248. LinkRes.Add('SEARCH_DIR('+HPath^.Data^+')');
  249. HPath:=HPath^.Next;
  250. end;
  251. LinkRes.Add('INPUT(');
  252. { add objectfiles, start with prt0 always }
  253. if prtobj<>'' then
  254. LinkRes.AddFileName(FindObjectFile(prtobj,''));
  255. { try to add crti and crtbegin if linking to C }
  256. if linklibc then
  257. begin
  258. s:=librarysearchpath.FindFile('crtbegin.o',found)+'crtbegin.o';
  259. if found then
  260. LinkRes.AddFileName(s);
  261. s:=librarysearchpath.FindFile('crti.o',found)+'crti.o';
  262. if found then
  263. LinkRes.AddFileName(s);
  264. end;
  265. { main objectfiles }
  266. while not ObjectFiles.Empty do
  267. begin
  268. s:=ObjectFiles.Get;
  269. if s<>'' then
  270. LinkRes.AddFileName(s);
  271. end;
  272. { objects which must be at the end }
  273. if linklibc then
  274. begin
  275. s:=librarysearchpath.FindFile('crtend.o',found)+'crtend.o';
  276. if found then
  277. LinkRes.AddFileName(s);
  278. s:=librarysearchpath.FindFile('crtn.o',found)+'crtn.o';
  279. if found then
  280. LinkRes.AddFileName(s);
  281. end;
  282. LinkRes.Add(')');
  283. { Write staticlibraries }
  284. if not StaticLibFiles.Empty then
  285. begin
  286. LinkRes.Add('GROUP(');
  287. While not StaticLibFiles.Empty do
  288. begin
  289. S:=StaticLibFiles.Get;
  290. LinkRes.AddFileName(s)
  291. end;
  292. LinkRes.Add(')');
  293. end;
  294. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  295. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  296. if not SharedLibFiles.Empty then
  297. begin
  298. LinkRes.Add('INPUT(');
  299. While not SharedLibFiles.Empty do
  300. begin
  301. S:=SharedLibFiles.Get;
  302. if s<>'c' then
  303. begin
  304. i:=Pos(target_os.sharedlibext,S);
  305. if i>0 then
  306. Delete(S,i,255);
  307. LinkRes.Add('-l'+s);
  308. end
  309. else
  310. begin
  311. linklibc:=true;
  312. linkdynamic:=false; { libc will include the ld-linux for us }
  313. end;
  314. end;
  315. { be sure that libc is the last lib }
  316. if linklibc then
  317. LinkRes.Add('-lc');
  318. { when we have -static for the linker the we also need libgcc }
  319. if (cs_link_staticflag in aktglobalswitches) then
  320. LinkRes.Add('-lgcc');
  321. if linkdynamic and (Info.DynamicLinker<>'') then
  322. LinkRes.AddFileName(Info.DynamicLinker);
  323. LinkRes.Add(')');
  324. end;
  325. { Write and Close response }
  326. linkres.writetodisk;
  327. linkres.done;
  328. WriteResponseFile:=True;
  329. end;
  330. function TLinkerFreeBSD.MakeExecutable:boolean;
  331. var
  332. binstr,
  333. cmdstr : string;
  334. success : boolean;
  335. DynLinkStr : string[60];
  336. StaticStr,
  337. StripStr : string[40];
  338. begin
  339. if not(cs_link_extern in aktglobalswitches) then
  340. Message1(exec_i_linking,current_module^.exefilename^);
  341. { Create some replacements }
  342. StaticStr:='';
  343. StripStr:='';
  344. DynLinkStr:='';
  345. if (cs_link_staticflag in aktglobalswitches) then
  346. StaticStr:='-static';
  347. if (cs_link_strip in aktglobalswitches) then
  348. StripStr:='-s';
  349. If (cs_profile in aktmoduleswitches) or
  350. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  351. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  352. { Write used files and libraries }
  353. WriteResponseFile(false);
  354. { Call linker }
  355. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  356. Replace(cmdstr,'$EXE',current_module^.exefilename^);
  357. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  358. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  359. Replace(cmdstr,'$STATIC',StaticStr);
  360. Replace(cmdstr,'$STRIP',StripStr);
  361. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  362. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  363. { Remove ReponseFile }
  364. if (success) and not(cs_link_extern in aktglobalswitches) then
  365. RemoveFile(outputexedir+Info.ResName);
  366. MakeExecutable:=success; { otherwise a recursive call to link method }
  367. end;
  368. Function TLinkerFreeBSD.MakeSharedLibrary:boolean;
  369. var
  370. binstr,
  371. cmdstr : string;
  372. success : boolean;
  373. begin
  374. MakeSharedLibrary:=false;
  375. if not(cs_link_extern in aktglobalswitches) then
  376. Message1(exec_i_linking,current_module^.sharedlibfilename^);
  377. { Write used files and libraries }
  378. WriteResponseFile(true);
  379. { Call linker }
  380. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  381. Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
  382. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  383. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  384. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  385. { Strip the library ? }
  386. if success and (cs_link_strip in aktglobalswitches) then
  387. begin
  388. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  389. Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
  390. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  391. end;
  392. { Remove ReponseFile }
  393. if (success) and not(cs_link_extern in aktglobalswitches) then
  394. RemoveFile(outputexedir+Info.ResName);
  395. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  396. end;
  397. end.
  398. {
  399. $Log$
  400. Revision 1.3 2000-09-24 21:33:47 peter
  401. * message updates merges
  402. Revision 1.2 2000/09/24 15:12:12 peter
  403. * renamed to be 8.3
  404. Revision 1.2 2000/09/16 12:24:00 peter
  405. * freebsd support routines
  406. }