t_beos.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Peter Vreman
  4. This unit implements support import,export,link routines
  5. for the (i386) BeOS target.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit t_beos;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. symsym,symdef,
  24. import,export,link;
  25. type
  26. timportlibbeos=class(timportlib)
  27. procedure preparelib(const s:string);override;
  28. procedure importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);override;
  29. procedure importvariable(vs:tvarsym;const name,module:string);override;
  30. procedure generatelib;override;
  31. end;
  32. texportlibbeos=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. tlinkerbeos=class(texternallinker)
  39. private
  40. Function WriteResponseFile(isdll:boolean;makelib:boolean) : Boolean;
  41. public
  42. constructor Create;override;
  43. procedure SetDefaultInfo;override;
  44. function MakeExecutable:boolean;override;
  45. function MakeSharedLibrary:boolean;override;
  46. end;
  47. implementation
  48. uses
  49. {$ifdef delphi}
  50. dmisc,
  51. {$else}
  52. dos,
  53. {$endif}
  54. cutils,cclasses,
  55. verbose,systems,globtype,globals,
  56. symconst,script,
  57. fmodule,aasmbase,aasmtai,aasmcpu,cpubase,i_beos;
  58. {*****************************************************************************
  59. TIMPORTLIBBEOS
  60. *****************************************************************************}
  61. procedure timportlibbeos.preparelib(const s : string);
  62. begin
  63. end;
  64. procedure timportlibbeos.importprocedure(aprocdef:tprocdef;const module:string;index:longint;const name:string);
  65. begin
  66. { insert sharedlibrary }
  67. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  68. { do nothing with the procedure, only set the mangledname }
  69. if name<>'' then
  70. aprocdef.setmangledname(name)
  71. else
  72. message(parser_e_empty_import_name);
  73. end;
  74. procedure timportlibbeos.importvariable(vs:tvarsym;const name,module:string);
  75. begin
  76. { insert sharedlibrary }
  77. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  78. { reset the mangledname and turn off the dll_var option }
  79. vs.set_mangledname(name);
  80. exclude(vs.varoptions,vo_is_dll_var);
  81. end;
  82. procedure timportlibbeos.generatelib;
  83. begin
  84. end;
  85. {*****************************************************************************
  86. TEXPORTLIBBEOS
  87. *****************************************************************************}
  88. procedure texportlibbeos.preparelib(const s:string);
  89. begin
  90. end;
  91. procedure texportlibbeos.exportprocedure(hp : texported_item);
  92. var
  93. hp2 : texported_item;
  94. begin
  95. { first test the index value }
  96. if (hp.options and eo_index)<>0 then
  97. begin
  98. Message1(parser_e_no_export_with_index_for_target,'beos');
  99. exit;
  100. end;
  101. { now place in correct order }
  102. hp2:=texported_item(current_module._exports.first);
  103. while assigned(hp2) and
  104. (hp.name^>hp2.name^) do
  105. hp2:=texported_item(hp2.next);
  106. { insert hp there !! }
  107. if assigned(hp2) and (hp2.name^=hp.name^) then
  108. begin
  109. { this is not allowed !! }
  110. Message1(parser_e_export_name_double,hp.name^);
  111. exit;
  112. end;
  113. if hp2=texported_item(current_module._exports.first) then
  114. current_module._exports.concat(hp)
  115. else if assigned(hp2) then
  116. begin
  117. hp.next:=hp2;
  118. hp.previous:=hp2.previous;
  119. if assigned(hp2.previous) then
  120. hp2.previous.next:=hp;
  121. hp2.previous:=hp;
  122. end
  123. else
  124. current_module._exports.concat(hp);
  125. end;
  126. procedure texportlibbeos.exportvar(hp : texported_item);
  127. begin
  128. hp.is_var:=true;
  129. exportprocedure(hp);
  130. end;
  131. procedure texportlibbeos.generatelib;
  132. var
  133. hp2 : texported_item;
  134. begin
  135. hp2:=texported_item(current_module._exports.first);
  136. while assigned(hp2) do
  137. begin
  138. if (not hp2.is_var) and
  139. (hp2.sym.typ=procsym) then
  140. begin
  141. { the manglednames can already be the same when the procedure
  142. is declared with cdecl }
  143. if tprocsym(hp2.sym).first_procdef.mangledname<>hp2.name^ then
  144. begin
  145. {$ifdef i386}
  146. { place jump in codesegment }
  147. codesegment.concat(Tai_align.Create_op(4,$90));
  148. codeSegment.concat(Tai_symbol.Createname_global(hp2.name^,0));
  149. codeSegment.concat(Taicpu.Op_sym(A_JMP,S_NO,objectlibrary.newasmsymbol(tprocsym(hp2.sym).first_procdef.mangledname)));
  150. codeSegment.concat(Tai_symbol_end.Createname(hp2.name^));
  151. {$endif i386}
  152. end;
  153. end
  154. else
  155. Message1(parser_e_no_export_of_variables_for_target,'beos');
  156. hp2:=texported_item(hp2.next);
  157. end;
  158. end;
  159. {*****************************************************************************
  160. TLINKERBEOS
  161. *****************************************************************************}
  162. Constructor TLinkerBeos.Create;
  163. var
  164. s : string;
  165. i : integer;
  166. begin
  167. Inherited Create;
  168. s:=GetEnv('BELIBRARIES');
  169. { convert to correct format in case under unix system }
  170. for i:=1 to length(s) do
  171. if s[i] = ':' then
  172. s[i] := ';';
  173. { just in case we have a single path : add the ending ; }
  174. { since that is what the compiler expects. }
  175. if pos(';',s) = 0 then
  176. s:=s+';';
  177. LibrarySearchPath.AddPath(s,true); {format:'path1;path2;...'}
  178. end;
  179. procedure TLinkerBeOS.SetDefaultInfo;
  180. begin
  181. with Info do
  182. begin
  183. ExeCmd[1]:='ld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE `cat $RES`';
  184. DllCmd[1]:='ld $OPT $INIT $FINI $SONAME -shared -L. -o $EXE `cat $RES`';
  185. DllCmd[2]:='strip --strip-unneeded $EXE';
  186. {
  187. ExeCmd[1]:='sh $RES $EXE $OPT $STATIC $STRIP -L.';
  188. { ExeCmd[1]:='sh $RES $EXE $OPT $DYNLINK $STATIC $STRIP -L.';}
  189. DllCmd[1]:='sh $RES $EXE $OPT -L.';
  190. { DllCmd[1]:='sh $RES $EXE $OPT -L. -g -nostart -soname=$EXE';
  191. } DllCmd[2]:='strip --strip-unneeded $EXE';
  192. { DynamicLinker:='/lib/ld-beos.so.2';}
  193. }
  194. end;
  195. end;
  196. function TLinkerBeOS.WriteResponseFile(isdll:boolean;makelib:boolean) : Boolean;
  197. Var
  198. linkres : TLinkRes;
  199. i : integer;
  200. cprtobj,
  201. prtobj : string[80];
  202. HPath : TStringListItem;
  203. s : string;
  204. linklibc : boolean;
  205. begin
  206. WriteResponseFile:=False;
  207. { set special options for some targets }
  208. linklibc:=(SharedLibFiles.Find('root')<>nil);
  209. prtobj:='prt0';
  210. cprtobj:='cprt0';
  211. if (cs_profile in aktmoduleswitches) or
  212. (not SharedLibFiles.Empty) then
  213. begin
  214. AddSharedLibrary('root');
  215. linklibc:=true;
  216. end;
  217. if (not linklibc) and makelib then
  218. begin
  219. linklibc:=true;
  220. cprtobj:='dllprt.o';
  221. end;
  222. if linklibc then
  223. prtobj:=cprtobj;
  224. { Open link.res file }
  225. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  226. {
  227. if not isdll then
  228. LinkRes.Add('ld -o $1 $2 $3 $4 $5 $6 $7 $8 $9 \')
  229. else
  230. LinkRes.Add('ld -o $1 -e 0 $2 $3 $4 $5 $6 $7 $8 $9\');
  231. }
  232. LinkRes.Add('-m elf_i386_be -shared -Bsymbolic');
  233. { Write path to search libraries }
  234. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  235. while assigned(HPath) do
  236. begin
  237. LinkRes.Add('-L'+HPath.Str);
  238. HPath:=TStringListItem(HPath.Next);
  239. end;
  240. HPath:=TStringListItem(LibrarySearchPath.First);
  241. while assigned(HPath) do
  242. begin
  243. LinkRes.Add('-L'+HPath.Str);
  244. HPath:=TStringListItem(HPath.Next);
  245. end;
  246. { try to add crti and crtbegin if linking to C }
  247. if linklibc then
  248. begin
  249. if librarysearchpath.FindFile('crti.o',s) then
  250. LinkRes.AddFileName(s);
  251. if librarysearchpath.FindFile('crtbegin.o',s) then
  252. LinkRes.AddFileName(s);
  253. { s:=librarysearchpath.FindFile('start_dyn.o',found)+'start_dyn.o';
  254. if found then LinkRes.AddFileName(s+' \');}
  255. if prtobj<>'' then
  256. LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
  257. if isdll then
  258. LinkRes.AddFileName(FindObjectFile('func.o','',false));
  259. if librarysearchpath.FindFile('init_term_dyn.o',s) then
  260. LinkRes.AddFileName(s);
  261. end
  262. else
  263. begin
  264. if prtobj<>'' then
  265. LinkRes.AddFileName(FindObjectFile(prtobj,'',false));
  266. end;
  267. { main objectfiles }
  268. while not ObjectFiles.Empty do
  269. begin
  270. s:=ObjectFiles.GetFirst;
  271. if s<>'' then
  272. LinkRes.AddFileName(s);
  273. end;
  274. { LinkRes.Add('-lroot \');
  275. LinkRes.Add('/boot/develop/tools/gnupro/lib/gcc-lib/i586-beos/2.9-beos-991026/crtend.o \');
  276. LinkRes.Add('/boot/develop/lib/x86/crtn.o \');}
  277. { Write staticlibraries }
  278. if not StaticLibFiles.Empty then
  279. begin
  280. While not StaticLibFiles.Empty do
  281. begin
  282. S:=StaticLibFiles.GetFirst;
  283. LinkRes.AddFileName(s)
  284. end;
  285. end;
  286. { Write sharedlibraries like -l<lib> }
  287. if not SharedLibFiles.Empty then
  288. begin
  289. While not SharedLibFiles.Empty do
  290. begin
  291. S:=SharedLibFiles.GetFirst;
  292. if s<>'c' then
  293. begin
  294. i:=Pos(target_info.sharedlibext,S);
  295. if i>0 then
  296. Delete(S,i,255);
  297. LinkRes.Add('-l'+s);
  298. end
  299. else
  300. begin
  301. linklibc:=true;
  302. end;
  303. end;
  304. { be sure that libc is the last lib }
  305. { if linklibc then
  306. LinkRes.Add('-lroot');}
  307. { if linkdynamic and (Info.DynamicLinker<>'') then
  308. LinkRes.AddFileName(Info.DynamicLinker);}
  309. end;
  310. if isdll then
  311. LinkRes.Add('-lroot');
  312. { objects which must be at the end }
  313. if linklibc then
  314. begin
  315. if librarysearchpath.FindFile('crtend.o',s) then
  316. LinkRes.AddFileName(s);
  317. if librarysearchpath.FindFile('crtn.o',s) then
  318. LinkRes.AddFileName(s);
  319. end;
  320. { Write and Close response }
  321. linkres.Add(' ');
  322. linkres.writetodisk;
  323. linkres.free;
  324. WriteResponseFile:=True;
  325. end;
  326. function TLinkerBeOS.MakeExecutable:boolean;
  327. var
  328. binstr,
  329. cmdstr : string;
  330. success : boolean;
  331. DynLinkStr : string[60];
  332. StaticStr,
  333. StripStr : string[40];
  334. begin
  335. if not(cs_link_extern in aktglobalswitches) then
  336. Message1(exec_i_linking,current_module.exefilename^);
  337. { Create some replacements }
  338. StaticStr:='';
  339. StripStr:='';
  340. DynLinkStr:='';
  341. if (cs_link_staticflag in aktglobalswitches) then
  342. StaticStr:='-static';
  343. if (cs_link_strip in aktglobalswitches) then
  344. StripStr:='-s';
  345. If (cs_profile in aktmoduleswitches) or
  346. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  347. begin
  348. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  349. if cshared Then
  350. DynLinkStr:='--shared ' + DynLinkStr;
  351. if rlinkpath<>'' Then
  352. DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
  353. End;
  354. { Write used files and libraries }
  355. WriteResponseFile(false,false);
  356. { Call linker }
  357. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  358. Replace(cmdstr,'$EXE',current_module.exefilename^);
  359. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  360. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  361. Replace(cmdstr,'$STATIC',StaticStr);
  362. Replace(cmdstr,'$STRIP',StripStr);
  363. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  364. success:=DoExec(FindUtil(utilsprefix+BinStr),CmdStr,true,true);
  365. { Remove ReponseFile }
  366. if (success) and not(cs_link_extern in aktglobalswitches) then
  367. RemoveFile(outputexedir+Info.ResName);
  368. MakeExecutable:=success; { otherwise a recursive call to link method }
  369. end;
  370. Function TLinkerBeOS.MakeSharedLibrary:boolean;
  371. var
  372. binstr,
  373. cmdstr : string;
  374. success : boolean;
  375. DynLinkStr : string[60];
  376. StaticStr,
  377. StripStr : string[40];
  378. begin
  379. MakeSharedLibrary:=false;
  380. if not(cs_link_extern in aktglobalswitches) then
  381. Message1(exec_i_linking,current_module.sharedlibfilename^);
  382. { Create some replacements }
  383. StaticStr:='';
  384. StripStr:='';
  385. DynLinkStr:='';
  386. if (cs_link_staticflag in aktglobalswitches) then
  387. StaticStr:='-static';
  388. if (cs_link_strip in aktglobalswitches) then
  389. StripStr:='-s';
  390. If (cs_profile in aktmoduleswitches) or
  391. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  392. begin
  393. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  394. if cshared Then
  395. DynLinkStr:='--shared ' + DynLinkStr;
  396. if rlinkpath<>'' Then
  397. DynLinkStr:='--rpath-link '+rlinkpath + ' '+ DynLinkStr;
  398. End;
  399. { Write used files and libraries }
  400. WriteResponseFile(true,true);
  401. { Call linker }
  402. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  403. Replace(cmdstr,'$EXE',current_module.exefilename^);
  404. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  405. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  406. Replace(cmdstr,'$STATIC',StaticStr);
  407. Replace(cmdstr,'$STRIP',StripStr);
  408. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  409. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,true);
  410. { Strip the library ? }
  411. if success and (cs_link_strip in aktglobalswitches) then
  412. begin
  413. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  414. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  415. success:=DoExec(FindUtil(utilsprefix+binstr),cmdstr,true,false);
  416. end;
  417. { Remove ReponseFile }
  418. if (success) and not(cs_link_extern in aktglobalswitches) then
  419. RemoveFile(outputexedir+Info.ResName);
  420. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  421. end;
  422. {*****************************************************************************
  423. Initialize
  424. *****************************************************************************}
  425. initialization
  426. {$ifdef i386}
  427. RegisterExternalLinker(system_i386_beos_info,TLinkerbeos);
  428. RegisterImport(system_i386_beos,timportlibbeos);
  429. RegisterExport(system_i386_beos,texportlibbeos);
  430. RegisterTarget(system_i386_beos_info);
  431. {$endif i386}
  432. end.
  433. {
  434. $Log$
  435. Revision 1.8 2004-01-29 23:57:15 florian
  436. * fixed linker response file handling
  437. Revision 1.7 2004/01/29 22:50:53 florian
  438. * tried to fix BeOS linking
  439. Revision 1.6 2003/10/03 14:16:48 marco
  440. * -XP<prefix> support
  441. Revision 1.5 2003/04/27 07:29:52 peter
  442. * aktprocdef cleanup, aktprocdef is now always nil when parsing
  443. a new procdef declaration
  444. * aktprocsym removed
  445. * lexlevel removed, use symtable.symtablelevel instead
  446. * implicit init/final code uses the normal genentry/genexit
  447. * funcret state checking updated for new funcret handling
  448. Revision 1.4 2003/04/26 09:16:08 peter
  449. * .o files belonging to the unit are first searched in the same dir
  450. as the .ppu
  451. Revision 1.3 2002/10/05 12:43:29 carl
  452. * fixes for Delphi 6 compilation
  453. (warning : Some features do not work under Delphi)
  454. Revision 1.2 2002/09/09 17:34:17 peter
  455. * tdicationary.replace added to replace and item in a dictionary. This
  456. is only allowed for the same name
  457. * varsyms are inserted in symtable before the types are parsed. This
  458. fixes the long standing "var longint : longint" bug
  459. - consume_idlist and idstringlist removed. The loops are inserted
  460. at the callers place and uses the symtable for duplicate id checking
  461. Revision 1.1 2002/09/06 15:03:51 carl
  462. * moved files to systems directory
  463. Revision 1.24 2002/09/03 16:26:28 daniel
  464. * Make Tprocdef.defs protected
  465. Revision 1.23 2002/08/12 15:08:44 carl
  466. + stab register indexes for powerpc (moved from gdb to cpubase)
  467. + tprocessor enumeration moved to cpuinfo
  468. + linker in target_info is now a class
  469. * many many updates for m68k (will soon start to compile)
  470. - removed some ifdef or correct them for correct cpu
  471. Revision 1.22 2002/08/11 14:32:32 peter
  472. * renamed current_library to objectlibrary
  473. Revision 1.21 2002/08/11 13:24:19 peter
  474. * saving of asmsymbols in ppu supported
  475. * asmsymbollist global is removed and moved into a new class
  476. tasmlibrarydata that will hold the info of a .a file which
  477. corresponds with a single module. Added librarydata to tmodule
  478. to keep the library info stored for the module. In the future the
  479. objectfiles will also be stored to the tasmlibrarydata class
  480. * all getlabel/newasmsymbol and friends are moved to the new class
  481. Revision 1.20 2002/07/26 21:15:45 florian
  482. * rewrote the system handling
  483. Revision 1.19 2002/07/01 18:46:34 peter
  484. * internal linker
  485. * reorganized aasm layer
  486. Revision 1.18 2002/05/18 13:34:26 peter
  487. * readded missing revisions
  488. Revision 1.17 2002/05/16 19:46:53 carl
  489. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  490. + try to fix temp allocation (still in ifdef)
  491. + generic constructor calls
  492. + start of tassembler / tmodulebase class cleanup
  493. Revision 1.15 2002/04/22 18:19:22 carl
  494. - remove use_bound_instruction field
  495. Revision 1.14 2002/04/20 21:43:18 carl
  496. * fix stack size for some targets
  497. + add offset to parameters from frame pointer info.
  498. - remove some unused stuff
  499. Revision 1.13 2002/04/19 15:46:04 peter
  500. * mangledname rewrite, tprocdef.mangledname is now created dynamicly
  501. in most cases and not written to the ppu
  502. * add mangeledname_prefix() routine to generate the prefix of
  503. manglednames depending on the current procedure, object and module
  504. * removed static procprefix since the mangledname is now build only
  505. on demand from tprocdef.mangledname
  506. Revision 1.12 2002/04/15 19:16:57 carl
  507. - remove size_of_pointer field
  508. Revision 1.11 2002/01/29 21:27:34 peter
  509. * default alignment changed to 4 bytes for locals and static const,var
  510. }