t_beos.pas 16 KB

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