t_sunos.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit implements support import,export,link routines
  5. for the (i386) sunos 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_sunos;
  20. {$i defines.inc}
  21. interface
  22. { copy from t_linux
  23. // Up to now we use gld since the solaris ld seems not support .res-files}
  24. {-$DEFINE LinkTest} { DON't del link.res and write Info }
  25. {$DEFINE GnuLd} {The other is not implemented }
  26. implementation
  27. uses
  28. cutils,cclasses,
  29. verbose,systems,globtype,globals,
  30. symconst,script,
  31. fmodule,aasm,cpuasm,cpubase,symsym,
  32. import,export,link;
  33. type
  34. timportlibsunos=class(timportlib)
  35. procedure preparelib(const s:string);override;
  36. procedure importprocedure(const func,module:string;index:longint;const name:string);override;
  37. procedure importvariable(const varname,module:string;const name:string);override;
  38. procedure generatelib;override;
  39. end;
  40. texportlibsunos=class(texportlib)
  41. procedure preparelib(const s : string);override;
  42. procedure exportprocedure(hp : texported_item);override;
  43. procedure exportvar(hp : texported_item);override;
  44. procedure generatelib;override;
  45. end;
  46. tlinkersunos=class(tlinker)
  47. private
  48. Glibc2,
  49. Glibc21 : boolean;
  50. Function WriteResponseFile(isdll:boolean) : Boolean;
  51. public
  52. constructor Create;override;
  53. procedure SetDefaultInfo;override;
  54. function MakeExecutable:boolean;override;
  55. function MakeSharedLibrary:boolean;override;
  56. end;
  57. {*****************************************************************************
  58. TIMPORTLIBsunos
  59. *****************************************************************************}
  60. procedure timportlibsunos.preparelib(const s : string);
  61. begin
  62. {$ifDef LinkTest}
  63. WriteLN('Prepare import: ',s);
  64. {$EndIf}
  65. end;
  66. procedure timportlibsunos.importprocedure(const func,module : string;index : longint;const name : string);
  67. begin
  68. { insert sharedlibrary }
  69. {$ifDef LinkTest}
  70. WriteLN('Import: f:',func,' m:',module,' n:',name);
  71. {$EndIf}
  72. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  73. { do nothing with the procedure, only set the mangledname }
  74. if name<>'' then
  75. aktprocsym.definition.setmangledname(name)
  76. else
  77. message(parser_e_empty_import_name);
  78. end;
  79. procedure timportlibsunos.importvariable(const varname,module:string;const name:string);
  80. begin
  81. { insert sharedlibrary }
  82. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  83. { reset the mangledname and turn off the dll_var option }
  84. aktvarsym.setmangledname(name);
  85. exclude(aktvarsym.varoptions,vo_is_dll_var);
  86. end;
  87. procedure timportlibsunos.generatelib;
  88. begin
  89. end;
  90. {*****************************************************************************
  91. TEXPORTLIBsunos
  92. *****************************************************************************}
  93. procedure texportlibsunos.preparelib(const s:string);
  94. begin
  95. end;
  96. procedure texportlibsunos.exportprocedure(hp : texported_item);
  97. var
  98. hp2 : texported_item;
  99. begin
  100. { first test the index value }
  101. if (hp.options and eo_index)<>0 then
  102. begin
  103. Message1(parser_e_no_export_with_index_for_target,'SunOS');
  104. exit;
  105. end;
  106. { use pascal name is none specified }
  107. if (hp.options and eo_name)=0 then
  108. begin
  109. hp.name:=stringdup(hp.sym.name);
  110. hp.options:=hp.options or eo_name;
  111. end;
  112. { now place in correct order }
  113. hp2:=texported_item(current_module._exports.first);
  114. while assigned(hp2) and
  115. (hp.name^>hp2.name^) do
  116. hp2:=texported_item(hp2.next);
  117. { insert hp there !! }
  118. if assigned(hp2) and (hp2.name^=hp.name^) then
  119. begin
  120. { this is not allowed !! }
  121. Message1(parser_e_export_name_double,hp.name^);
  122. exit;
  123. end;
  124. if hp2=texported_item(current_module._exports.first) then
  125. current_module._exports.insert(hp)
  126. else if assigned(hp2) then
  127. begin
  128. hp.next:=hp2;
  129. hp.previous:=hp2.previous;
  130. if assigned(hp2.previous) then
  131. hp2.previous.next:=hp;
  132. hp2.previous:=hp;
  133. end
  134. else
  135. current_module._exports.concat(hp);
  136. end;
  137. procedure texportlibsunos.exportvar(hp : texported_item);
  138. begin
  139. hp.is_var:=true;
  140. exportprocedure(hp);
  141. end;
  142. procedure texportlibsunos.generatelib;
  143. var
  144. hp2 : texported_item;
  145. begin
  146. hp2:=texported_item(current_module._exports.first);
  147. while assigned(hp2) do
  148. begin
  149. if not hp2.is_var then
  150. begin
  151. {$ifdef i386}
  152. { place jump in codesegment }
  153. codesegment.concat(Tai_align.Create_op(4,$90));
  154. codeSegment.concat(Tai_symbol.Createname_global(hp2.name^,0));
  155. codeSegment.concat(Taicpu.Op_sym(A_JMP,S_NO,newasmsymbol(hp2.sym.mangledname)));
  156. codeSegment.concat(Tai_symbol_end.Createname(hp2.name^));
  157. {$endif i386}
  158. end
  159. else
  160. Message1(parser_e_no_export_of_variables_for_target,'SunOS');
  161. hp2:=texported_item(hp2.next);
  162. end;
  163. end;
  164. {*****************************************************************************
  165. TLINKERSUNOS
  166. *****************************************************************************}
  167. Constructor TLinkersunos.Create;
  168. begin
  169. Inherited Create;
  170. LibrarySearchPath.AddPath('/lib;/usr/lib;/usr/X11R6/lib;/opt/sfw/lib',true);
  171. {$ifdef LinkTest}
  172. if (cs_link_staticflag in aktglobalswitches) then WriteLN('ForceLinkStaticFlag');
  173. if (cs_link_static in aktglobalswitches) then WriteLN('LinkStatic-Flag');
  174. if (cs_link_shared in aktglobalswitches) then WriteLN('LinkSynamicFlag');
  175. {$EndIf}
  176. end;
  177. procedure TLinkersunos.SetDefaultInfo;
  178. {
  179. This will also detect which libc version will be used
  180. }
  181. begin
  182. Glibc2:=false;
  183. Glibc21:=false;
  184. with Info do
  185. begin
  186. {$IFDEF GnuLd}
  187. ExeCmd[1]:='gld $OPT $DYNLINK $STATIC $STRIP -L. -o $EXE $RES';
  188. DllCmd[1]:='gld $OPT -shared -L. -o $EXE $RES';
  189. DllCmd[2]:='strip --strip-unneeded $EXE';
  190. DynamicLinker:=''; { Gnu uses the default }
  191. Glibc21:=false;
  192. {$ELSE}
  193. Not Implememted
  194. {$ENDIF}
  195. (* Linux Stuff not needed?
  196. { first try glibc2 } // muss noch gendert werden
  197. if FileExists(DynamicLinker) then
  198. begin
  199. Glibc2:=true;
  200. { Check for 2.0 files, else use the glibc 2.1 stub }
  201. if FileExists('/lib/ld-2.0.*') then
  202. Glibc21:=false
  203. else
  204. Glibc21:=true;
  205. end
  206. else
  207. DynamicLinker:='/lib/ld-linux.so.1';
  208. *)
  209. end;
  210. end;
  211. Function TLinkersunos.WriteResponseFile(isdll:boolean) : Boolean;
  212. Var
  213. linkres : TLinkRes;
  214. i : longint;
  215. cprtobj,
  216. gprtobj,
  217. prtobj : string[80];
  218. HPath : TStringListItem;
  219. s,s1,s2 : string;
  220. linkdynamic,
  221. linklibc : boolean;
  222. begin
  223. WriteResponseFile:=False;
  224. { set special options for some targets }
  225. linkdynamic:=not(SharedLibFiles.empty);
  226. { linkdynamic:=false; // da nicht getestet }
  227. linklibc:=(SharedLibFiles.Find('c')<>nil);
  228. prtobj:='prt0';
  229. cprtobj:='cprt0';
  230. gprtobj:='gprt0';
  231. (* if glibc21 then
  232. begin
  233. cprtobj:='cprt21';
  234. gprtobj:='gprt21';
  235. end;
  236. *)
  237. if cs_profile in aktmoduleswitches then
  238. begin
  239. prtobj:=gprtobj;
  240. if not glibc2 then
  241. AddSharedLibrary('gmon');
  242. AddSharedLibrary('c');
  243. linklibc:=true;
  244. end
  245. else
  246. begin
  247. if linklibc then
  248. prtobj:=cprtobj
  249. else
  250. AddSharedLibrary('c'); { quick hack: this sunos implementation needs alwys libc }
  251. end;
  252. { Open link.res file }
  253. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  254. { Write path to search libraries }
  255. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  256. while assigned(HPath) do
  257. begin
  258. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  259. HPath:=TStringListItem(HPath.Next);
  260. end;
  261. HPath:=TStringListItem(LibrarySearchPath.First);
  262. while assigned(HPath) do
  263. begin
  264. LinkRes.Add('SEARCH_DIR('+HPath.Str+')');
  265. HPath:=TStringListItem(HPath.Next);
  266. end;
  267. LinkRes.Add('INPUT(');
  268. { add objectfiles, start with prt0 always }
  269. if prtobj<>'' then
  270. LinkRes.AddFileName(FindObjectFile(prtobj,''));
  271. { try to add crti and crtbegin if linking to C }
  272. if linklibc then { Needed in sunos? }
  273. begin
  274. if librarysearchpath.FindFile('crtbegin.o',s) then
  275. LinkRes.AddFileName(s);
  276. if librarysearchpath.FindFile('crti.o',s) then
  277. LinkRes.AddFileName(s);
  278. end;
  279. { main objectfiles }
  280. while not ObjectFiles.Empty do
  281. begin
  282. s:=ObjectFiles.GetFirst;
  283. if s<>'' then
  284. LinkRes.AddFileName(s);
  285. end;
  286. LinkRes.Add(')');
  287. { Write staticlibraries }
  288. if not StaticLibFiles.Empty then
  289. begin
  290. LinkRes.Add('GROUP(');
  291. While not StaticLibFiles.Empty do
  292. begin
  293. S:=StaticLibFiles.GetFirst;
  294. LinkRes.AddFileName(s)
  295. end;
  296. LinkRes.Add(')');
  297. end;
  298. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  299. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  300. if not SharedLibFiles.Empty then
  301. begin
  302. LinkRes.Add('INPUT(');
  303. While not SharedLibFiles.Empty do
  304. begin
  305. S:=SharedLibFiles.GetFirst;
  306. if s<>'c' then
  307. begin
  308. i:=Pos(target_info.sharedlibext,S);
  309. if i>0 then
  310. Delete(S,i,255);
  311. LinkRes.Add('-l'+s);
  312. end
  313. else
  314. begin
  315. linklibc:=true;
  316. linkdynamic:=false; { libc will include the ld-sunos (war ld-linux) for us }
  317. end;
  318. end;
  319. { be sure that libc is the last lib }
  320. if linklibc then
  321. LinkRes.Add('-lc');
  322. { when we have -static for the linker the we also need libgcc }
  323. if (cs_link_staticflag in aktglobalswitches) then begin
  324. LinkRes.Add('-lgcc');
  325. end;
  326. if linkdynamic and (Info.DynamicLinker<>'') then { gld has a default, DynamicLinker is not set in sunos }
  327. LinkRes.AddFileName(Info.DynamicLinker);
  328. LinkRes.Add(')');
  329. end;
  330. { objects which must be at the end }
  331. if linklibc then {needed in sunos ? }
  332. begin
  333. if librarysearchpath.FindFile('crtend.o',s1) or
  334. librarysearchpath.FindFile('crtn.o',s2) then
  335. begin
  336. LinkRes.Add('INPUT(');
  337. LinkRes.AddFileName(s1);
  338. LinkRes.AddFileName(s2);
  339. LinkRes.Add(')');
  340. end;
  341. end;
  342. { Write and Close response }
  343. linkres.writetodisk;
  344. LinkRes.Free;
  345. WriteResponseFile:=True;
  346. end;
  347. function TLinkersunos.MakeExecutable:boolean;
  348. var
  349. binstr,
  350. cmdstr : string;
  351. success : boolean;
  352. DynLinkStr : string[60];
  353. StaticStr,
  354. StripStr : string[40];
  355. begin
  356. if not(cs_link_extern in aktglobalswitches) then
  357. Message1(exec_i_linking,current_module.exefilename^);
  358. { Create some replacements }
  359. StaticStr:='';
  360. StripStr:='';
  361. DynLinkStr:='';
  362. if (cs_link_staticflag in aktglobalswitches) then
  363. StaticStr:='-Bstatic';
  364. if (cs_link_strip in aktglobalswitches) then
  365. StripStr:='-s';
  366. If (cs_profile in aktmoduleswitches) or
  367. ((Info.DynamicLinker<>'') and (not SharedLibFiles.Empty)) then
  368. DynLinkStr:='-dynamic-linker='+Info.DynamicLinker;
  369. { sunos sets DynamicLinker, but gld will (hopefully) defaults to -Bdynamic and add the default-linker }
  370. { Write used files and libraries }
  371. WriteResponseFile(false);
  372. { Call linker }
  373. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  374. Replace(cmdstr,'$EXE',current_module.exefilename^);
  375. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  376. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  377. Replace(cmdstr,'$STATIC',StaticStr);
  378. Replace(cmdstr,'$STRIP',StripStr);
  379. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  380. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  381. { Remove ReponseFile }
  382. {$IFNDEF LinkTest}
  383. if (success) and not(cs_link_extern in aktglobalswitches) then
  384. RemoveFile(outputexedir+Info.ResName);
  385. {$ENDIF}
  386. MakeExecutable:=success; { otherwise a recursive call to link method }
  387. end;
  388. Function TLinkersunos.MakeSharedLibrary:boolean;
  389. var
  390. binstr,
  391. cmdstr : string;
  392. success : boolean;
  393. begin
  394. MakeSharedLibrary:=false;
  395. if not(cs_link_extern in aktglobalswitches) then
  396. Message1(exec_i_linking,current_module.sharedlibfilename^);
  397. { Write used files and libraries }
  398. WriteResponseFile(true);
  399. { Call linker }
  400. SplitBinCmd(Info.DllCmd[1],binstr,cmdstr);
  401. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  402. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  403. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  404. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  405. { Strip the library ? }
  406. if success and (cs_link_strip in aktglobalswitches) then
  407. begin
  408. SplitBinCmd(Info.DllCmd[2],binstr,cmdstr);
  409. Replace(cmdstr,'$EXE',current_module.sharedlibfilename^);
  410. success:=DoExec(FindUtil(binstr),cmdstr,true,false);
  411. end;
  412. { Remove ReponseFile }
  413. {$IFNDEF LinkTest}
  414. if (success) and not(cs_link_extern in aktglobalswitches) then
  415. RemoveFile(outputexedir+Info.ResName);
  416. {$ENDIF}
  417. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  418. end;
  419. {*****************************************************************************
  420. Initialize
  421. *****************************************************************************}
  422. const
  423. target_i386_sunos_info : ttargetinfo =
  424. (
  425. target : target_i386_sunos;
  426. name : 'SunOS/ELF for i386';
  427. shortname : 'SunOS';
  428. flags : [];
  429. cpu : i386;
  430. unit_env : 'SUNOSUNITS';
  431. extradefines : 'UNIX;SOLARIS;LIBC';
  432. sharedlibext : '.so';
  433. staticlibext : '.a';
  434. sourceext : '.pp';
  435. pasext : '.pas';
  436. exeext : '';
  437. defext : '.def';
  438. scriptext : '.sh';
  439. smartext : '.sl';
  440. unitext : '.ppu';
  441. unitlibext : '.ppl';
  442. asmext : '.s';
  443. objext : '.o';
  444. resext : '.res';
  445. resobjext : '.or';
  446. staticlibprefix : 'libp';
  447. sharedlibprefix : 'lib';
  448. Cprefix : '';
  449. newline : #10;
  450. assem : as_i386_as;
  451. assemextern : as_i386_as;
  452. link : ld_i386_sunos;
  453. linkextern : ld_i386_sunos;
  454. ar : ar_gnu_ar;
  455. res : res_none;
  456. endian : endian_little;
  457. alignment :
  458. (
  459. procalign : 4;
  460. loopalign : 4;
  461. jumpalign : 0;
  462. constalignmin : 0;
  463. constalignmax : 1;
  464. varalignmin : 0;
  465. varalignmax : 1;
  466. localalignmin : 0;
  467. localalignmax : 1;
  468. paraalign : 4;
  469. recordalignmin : 0;
  470. recordalignmax : 2;
  471. maxCrecordalign : 4
  472. );
  473. size_of_pointer : 4;
  474. size_of_longint : 4;
  475. heapsize : 256*1024;
  476. maxheapsize : 32768*1024;
  477. stacksize : 8192;
  478. DllScanSupported:false;
  479. use_bound_instruction : false;
  480. use_function_relative_addresses : true
  481. );
  482. initialization
  483. RegisterLinker(ld_i386_sunos,TLinkerSunos);
  484. RegisterImport(target_i386_sunos,TImportLibSunos);
  485. RegisterExport(target_i386_sunos,TExportLibSunos);
  486. RegisterTarget(target_i386_sunos_info);
  487. end.
  488. {
  489. $Log$
  490. Revision 1.8 2001-07-01 20:16:21 peter
  491. * alignmentinfo record added
  492. * -Oa argument supports more alignment settings that can be specified
  493. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  494. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  495. required alignment and the maximum usefull alignment. The final
  496. alignment will be choosen per variable size dependent on these
  497. settings
  498. Revision 1.7 2001/06/28 19:46:25 peter
  499. * added override and virtual for constructors
  500. Revision 1.6 2001/06/03 15:15:32 peter
  501. * dllprt0 stub for linux shared libs
  502. * pass -init and -fini for linux shared libs
  503. * libprefix splitted into staticlibprefix and sharedlibprefix
  504. Revision 1.5 2001/06/02 19:22:44 peter
  505. * extradefines field added
  506. Revision 1.4 2001/04/21 15:34:01 peter
  507. * fixed writing of end objects to not output an empty INPUT()
  508. Revision 1.3 2001/04/18 22:02:04 peter
  509. * registration of targets and assemblers
  510. Revision 1.2 2001/04/13 01:22:22 peter
  511. * symtable change to classes
  512. * range check generation and errors fixed, make cycle DEBUG=1 works
  513. * memory leaks fixed
  514. Revision 1.1 2001/02/26 19:43:11 peter
  515. * moved target units to subdir
  516. }