t_nwm.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit implements support import,export,link routines
  5. for the (i386) Netware 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. First Implementation 10 Sept 2000 Armin Diehl
  18. Currently generating NetWare-NLM's only work under Linux. This is
  19. because nlmconf from binutils does not work with i.e. win32 coff
  20. object files. It works fine with ELF-Objects.
  21. The following compiler-swiches are supported for NetWare:
  22. $DESCRIPTION : NLM-Description, will be displayed at load-time
  23. $M : For Stack-Size, Heap-Size will be ignored
  24. $VERSION x.x.x : Sets Major, Minor and Revision
  25. Sorry, Displaying copyright does not work with nlmconv from gnu bunutils.
  26. Exports will be handled like in win32:
  27. procedure bla;
  28. begin
  29. end;
  30. exports bla name 'bla';
  31. Without Name 'bla' this will be exported in upper-case.
  32. The path to the import-Files (from netware-sdk, see developer.novell.com)
  33. must be specified by the library-path. All external modules are defined
  34. as autoload.
  35. i.e. Procedure ConsolePrintf (p:pchar); cdecl; external 'clib.nlm';
  36. sets IMPORT @clib.imp and MODULE clib.
  37. If you dont have nlmconv, compile gnu-binutils with
  38. ./configure --enable-targets=i386-linux,i386-netware
  39. make all
  40. Debugging is currently only possible at assembler level with nwdbg, written
  41. by Jan Beulich. Nwdbg supports symbols but it's not a source-level
  42. debugger. You can get nwdbg from developer.novell.com. To enter the
  43. debugger from your program, define "EnterDebugger" as external cdecl and
  44. call it. Int3 will not work with Netware 5.
  45. A sample program:
  46. Program Hello;
  47. (*$DESCRIPTION HelloWorldNlm*)
  48. (*$VERSION 1.2.2*)
  49. (*$M 8192,8192*)
  50. begin
  51. writeLn ('hello world');
  52. end.
  53. compile with:
  54. ppc386 -Tnetware hello
  55. ToDo:
  56. - No duplicate imports and autoloads
  57. - Screen and Thread-Names
  58. ****************************************************************************
  59. }
  60. unit t_nwm;
  61. {$i defines.inc}
  62. interface
  63. implementation
  64. uses
  65. cutils,
  66. verbose,systems,globtype,globals,
  67. symconst,script,
  68. fmodule,aasm,cpuasm,cpubase,symsym,
  69. import,export,link;
  70. type
  71. timportlibnetware=class(timportlib)
  72. procedure preparelib(const s:string);override;
  73. procedure importprocedure(const func,module:string;index:longint;const name:string);override;
  74. procedure importvariable(const varname,module:string;const name:string);override;
  75. procedure generatelib;override;
  76. end;
  77. texportlibnetware=class(texportlib)
  78. procedure preparelib(const s : string);override;
  79. procedure exportprocedure(hp : texported_item);override;
  80. procedure exportvar(hp : texported_item);override;
  81. procedure generatelib;override;
  82. end;
  83. tlinkernetware=class(tlinker)
  84. private
  85. Function WriteResponseFile(isdll:boolean) : Boolean;
  86. public
  87. constructor Create;override;
  88. procedure SetDefaultInfo;override;
  89. function MakeExecutable:boolean;override;
  90. end;
  91. {*****************************************************************************
  92. TIMPORTLIBNETWARE
  93. *****************************************************************************}
  94. procedure timportlibnetware.preparelib(const s : string);
  95. begin
  96. end;
  97. procedure timportlibnetware.importprocedure(const func,module : string;index : longint;const name : string);
  98. begin
  99. { insert sharedlibrary }
  100. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  101. { do nothing with the procedure, only set the mangledname }
  102. if name<>'' then
  103. aktprocdef.setmangledname(name)
  104. else
  105. message(parser_e_empty_import_name);
  106. end;
  107. procedure timportlibnetware.importvariable(const varname,module:string;const name:string);
  108. begin
  109. { insert sharedlibrary }
  110. current_module.linkothersharedlibs.add(SplitName(module),link_allways);
  111. { reset the mangledname and turn off the dll_var option }
  112. aktvarsym.setmangledname(name);
  113. exclude(aktvarsym.varoptions,vo_is_dll_var);
  114. end;
  115. procedure timportlibnetware.generatelib;
  116. begin
  117. end;
  118. {*****************************************************************************
  119. TEXPORTLIBNETWARE
  120. *****************************************************************************}
  121. procedure texportlibnetware.preparelib(const s:string);
  122. begin
  123. end;
  124. procedure texportlibnetware.exportprocedure(hp : texported_item);
  125. var
  126. hp2 : texported_item;
  127. begin
  128. { first test the index value }
  129. if (hp.options and eo_index)<>0 then
  130. begin
  131. Comment(V_Error,'can''t export with index under netware');
  132. exit;
  133. end;
  134. { use pascal name is none specified }
  135. if (hp.options and eo_name)=0 then
  136. begin
  137. hp.name:=stringdup(hp.sym.name);
  138. hp.options:=hp.options or eo_name;
  139. end;
  140. { now place in correct order }
  141. hp2:=texported_item(current_module._exports.first);
  142. while assigned(hp2) and
  143. (hp.name^>hp2.name^) do
  144. hp2:=texported_item(hp2.next);
  145. { insert hp there !! }
  146. if assigned(hp2) and (hp2.name^=hp.name^) then
  147. begin
  148. { this is not allowed !! }
  149. Message1(parser_e_export_name_double,hp.name^);
  150. exit;
  151. end;
  152. if hp2=texported_item(current_module._exports.first) then
  153. current_module._exports.insert(hp)
  154. else if assigned(hp2) then
  155. begin
  156. hp.next:=hp2;
  157. hp.previous:=hp2.previous;
  158. if assigned(hp2.previous) then
  159. hp2.previous.next:=hp;
  160. hp2.previous:=hp;
  161. end
  162. else
  163. current_module._exports.concat(hp);
  164. end;
  165. procedure texportlibnetware.exportvar(hp : texported_item);
  166. begin
  167. hp.is_var:=true;
  168. exportprocedure(hp);
  169. end;
  170. procedure texportlibnetware.generatelib;
  171. var
  172. hp2 : texported_item;
  173. begin
  174. hp2:=texported_item(current_module._exports.first);
  175. while assigned(hp2) do
  176. begin
  177. if (not hp2.is_var) and
  178. (hp2.sym.typ=procsym) then
  179. begin
  180. { the manglednames can already be the same when the procedure
  181. is declared with cdecl }
  182. if tprocsym(hp2.sym).defs^.def.mangledname<>hp2.name^ then
  183. begin
  184. {$ifdef i386}
  185. { place jump in codesegment }
  186. codesegment.concat(Tai_align.Create_op(4,$90));
  187. codeSegment.concat(Tai_symbol.Createname_global(hp2.name^,0));
  188. codeSegment.concat(Taicpu.Op_sym(A_JMP,S_NO,newasmsymbol(tprocsym(hp2.sym).defs^.def.mangledname)));
  189. codeSegment.concat(Tai_symbol_end.Createname(hp2.name^));
  190. {$endif i386}
  191. end;
  192. end
  193. else
  194. Comment(V_Error,'Exporting of variables is not supported under netware');
  195. hp2:=texported_item(hp2.next);
  196. end;
  197. end;
  198. {*****************************************************************************
  199. TLINKERNETWARE
  200. *****************************************************************************}
  201. Constructor TLinkerNetware.Create;
  202. begin
  203. Inherited Create;
  204. end;
  205. procedure TLinkerNetware.SetDefaultInfo;
  206. begin
  207. with Info do
  208. begin
  209. ExeCmd[1]:='nlmconv -T$RES';
  210. {DllCmd[1]:='ld $OPT -shared -L. -o $EXE $RES';}
  211. DllCmd[2]:='strip --strip-unneeded $EXE';
  212. end;
  213. end;
  214. Function TLinkerNetware.WriteResponseFile(isdll:boolean) : Boolean;
  215. Var
  216. linkres : TLinkRes;
  217. i : longint;
  218. s,s2 : string;
  219. ProgNam : string [80];
  220. NlmNam : string [80];
  221. hp2 : texported_item; { for exports }
  222. p : byte;
  223. begin
  224. WriteResponseFile:=False;
  225. ProgNam := current_module.exefilename^;
  226. i:=Pos(target_info.exeext,ProgNam);
  227. if i>0 then
  228. Delete(ProgNam,i,255);
  229. NlmNam := ProgNam + target_info.exeext;
  230. { Open link.res file }
  231. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  232. p := Pos ('"', Description);
  233. while (p > 0) do
  234. begin
  235. delete (Description,p,1);
  236. p := Pos ('"', Description);
  237. end;
  238. if Description <> '' then
  239. LinkRes.Add('DESCRIPTION "' + Description + '"');
  240. LinkRes.Add('VERSION '+tostr(dllmajor)+','+tostr(dllminor)+','+tostr(dllrevision));
  241. {if nwscreenname = '' then nwscreenname := ProgNam;
  242. if nwthreadname = '' then nwthreadname := ProgNam;}
  243. p := Pos ('"', nwscreenname);
  244. while (p > 0) do
  245. begin
  246. delete (nwscreenname,p,1);
  247. p := Pos ('"', nwscreenname);
  248. end;
  249. p := Pos ('"', nwthreadname);
  250. while (p > 0) do
  251. begin
  252. delete (nwthreadname,p,1);
  253. p := Pos ('"', nwthreadname);
  254. end;
  255. p := Pos ('"', nwcopyright);
  256. while (p > 0) do
  257. begin
  258. delete (nwcopyright,p,1);
  259. p := Pos ('"', nwcopyright);
  260. end;
  261. if nwscreenname <> '' then
  262. LinkRes.Add('SCREENNAME "' + nwscreenname + '"');
  263. if nwthreadname <> '' then
  264. LinkRes.Add('THREADNAME "' + nwthreadname + '"');
  265. if nwcopyright <> '' then
  266. LinkRes.Add('COPYRIGHT "' + nwcopyright + '"');
  267. if stacksize > 1024 then
  268. begin
  269. str (stacksize, s);
  270. LinkRes.Add ('STACKSIZE '+s);
  271. end;
  272. { add objectfiles, start with nwpre always }
  273. LinkRes.Add ('INPUT '+FindObjectFile('nwpre',''));
  274. { main objectfiles }
  275. while not ObjectFiles.Empty do
  276. begin
  277. s:=ObjectFiles.GetFirst;
  278. if s<>'' then
  279. LinkRes.Add ('INPUT ' + FindObjectFile (s,''));
  280. end;
  281. { output file (nlm) }
  282. LinkRes.Add ('OUTPUT ' + NlmNam);
  283. { start and stop-procedures }
  284. LinkRes.Add ('START _Prelude'); { defined in rtl/netware/nwpre.pp }
  285. LinkRes.Add ('EXIT _Stop');
  286. //if not (cs_link_strip in aktglobalswitches) then
  287. { ahhhggg: how do i detect if we have debug-symbols ? }
  288. LinkRes.Add ('DEBUG');
  289. { Write staticlibraries, is that correct ? }
  290. if not StaticLibFiles.Empty then
  291. begin
  292. While not StaticLibFiles.Empty do
  293. begin
  294. S:=lower (StaticLibFiles.GetFirst);
  295. if s<>'' then
  296. begin
  297. i:=Pos(target_info.staticlibext,S);
  298. if i>0 then
  299. Delete(S,i,255);
  300. S := S + '.imp';
  301. librarysearchpath.FindFile(S,s);
  302. LinkRes.Add('IMPORT @'+s);
  303. end
  304. end;
  305. end;
  306. if not SharedLibFiles.Empty then
  307. begin
  308. While not SharedLibFiles.Empty do
  309. begin
  310. {becuase of upper/lower case mix, we may get duplicate
  311. names but nlmconv ignores that.
  312. Here we are setting the import-files for nlmconv. I.e. for
  313. the module clib or clib.nlm we add IMPORT @clib.imp and also
  314. the module clib.nlm (autoload)
  315. ? may it be better to set autoload's via StaticLibFiles ? }
  316. S:=lower (SharedLibFiles.GetFirst);
  317. if s<>'' then
  318. begin
  319. s2:=s;
  320. i:=Pos(target_info.sharedlibext,S);
  321. if i>0 then
  322. Delete(S,i,255);
  323. S := S + '.imp';
  324. librarysearchpath.FindFile(S,s);
  325. LinkRes.Add('IMPORT @'+s);
  326. LinkRes.Add('MODULE '+s2);
  327. end
  328. end;
  329. end;
  330. { write exports }
  331. hp2:=texported_item(current_module._exports.first);
  332. while assigned(hp2) do
  333. begin
  334. if not hp2.is_var then
  335. begin
  336. { Export the Symbol
  337. Warning: The Symbol is converted to upper-case if not explicitly
  338. specified by >>Exports BlaBla NAME 'BlaBla';<< }
  339. Comment(V_Debug,'Exporting '+hp2.name^);
  340. LinkRes.Add ('EXPORT '+hp2.name^);
  341. end
  342. else
  343. { really ? }
  344. Comment(V_Error,'Exporting of variables is not supported under netware');
  345. hp2:=texported_item(hp2.next);
  346. end;
  347. { Write and Close response }
  348. linkres.writetodisk;
  349. LinkRes.Free;
  350. WriteResponseFile:=True;
  351. end;
  352. function TLinkerNetware.MakeExecutable:boolean;
  353. var
  354. binstr,
  355. cmdstr : string;
  356. success : boolean;
  357. DynLinkStr : string[60];
  358. StaticStr,
  359. StripStr : string[40];
  360. begin
  361. if not(cs_link_extern in aktglobalswitches) then
  362. Message1(exec_i_linking,current_module.exefilename^);
  363. { Create some replacements }
  364. StaticStr:='';
  365. StripStr:='';
  366. DynLinkStr:='';
  367. { Write used files and libraries }
  368. WriteResponseFile(false);
  369. { Call linker }
  370. SplitBinCmd(Info.ExeCmd[1],binstr,cmdstr);
  371. Replace(cmdstr,'$EXE',current_module.exefilename^);
  372. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  373. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  374. Replace(cmdstr,'$STATIC',StaticStr);
  375. Replace(cmdstr,'$STRIP',StripStr);
  376. Replace(cmdstr,'$DYNLINK',DynLinkStr);
  377. success:=DoExec(FindUtil(BinStr),CmdStr,true,false);
  378. { Remove ReponseFile }
  379. if (success) and not(cs_link_extern in aktglobalswitches) then
  380. RemoveFile(outputexedir+Info.ResName);
  381. MakeExecutable:=success; { otherwise a recursive call to link method }
  382. end;
  383. {*****************************************************************************
  384. Initialize
  385. *****************************************************************************}
  386. const
  387. target_i386_netware_info : ttargetinfo =
  388. (
  389. target : target_i386_NETWARE;
  390. name : 'Netware for i386';
  391. shortname : 'Netware';
  392. flags : [];
  393. cpu : i386;
  394. unit_env : 'NETWAREUNITS';
  395. extradefines : '';
  396. sourceext : '.pp';
  397. pasext : '.pas';
  398. exeext : '.nlm';
  399. defext : '.def';
  400. scriptext : '.sh';
  401. smartext : '.sl';
  402. unitext : '.ppn';
  403. unitlibext : '.ppl';
  404. asmext : '.s';
  405. objext : '.on';
  406. resext : '.res';
  407. resobjext : '.or';
  408. sharedlibext : '.nlm';
  409. staticlibext : '.a';
  410. staticlibprefix : '';
  411. sharedlibprefix : '';
  412. sharedClibext : '.nlm';
  413. staticClibext : '.a';
  414. staticClibprefix : '';
  415. sharedClibprefix : '';
  416. Cprefix : '';
  417. newline : #13#10;
  418. dirsep : '\';
  419. files_case_relevent : false;
  420. assem : as_i386_elf32;
  421. assemextern : as_i386_as;
  422. link : ld_i386_netware;
  423. linkextern : ld_i386_netware;
  424. ar : ar_gnu_ar;
  425. res : res_none;
  426. script : script_unix;
  427. endian : endian_little;
  428. alignment :
  429. (
  430. procalign : 4;
  431. loopalign : 4;
  432. jumpalign : 0;
  433. constalignmin : 0;
  434. constalignmax : 1;
  435. varalignmin : 0;
  436. varalignmax : 1;
  437. localalignmin : 0;
  438. localalignmax : 1;
  439. paraalign : 4;
  440. recordalignmin : 0;
  441. recordalignmax : 2;
  442. maxCrecordalign : 4
  443. );
  444. size_of_pointer : 4;
  445. size_of_longint : 4;
  446. heapsize : 256*1024;
  447. maxheapsize : 32768*1024;
  448. stacksize : 8192;
  449. DllScanSupported:false;
  450. use_bound_instruction : false;
  451. use_function_relative_addresses : true
  452. );
  453. initialization
  454. RegisterLinker(ld_i386_netware,TLinkerNetware);
  455. RegisterImport(target_i386_netware,TImportLibNetware);
  456. RegisterExport(target_i386_netware,TExportLibNetware);
  457. RegisterTarget(target_i386_netware_info);
  458. end.
  459. {
  460. $Log$
  461. Revision 1.12 2001-11-02 22:58:12 peter
  462. * procsym definition rewrite
  463. Revision 1.11 2001/09/18 11:32:00 michael
  464. * Fixes win32 linking problems with import libraries
  465. * LINKLIB Libraries are now looked for using C file extensions
  466. * get_exepath fix
  467. Revision 1.10 2001/09/17 21:29:16 peter
  468. * merged netbsd, fpu-overflow from fixes branch
  469. Revision 1.9 2001/08/07 18:47:15 peter
  470. * merged netbsd start
  471. * profile for win32
  472. Revision 1.8 2001/07/01 20:16:20 peter
  473. * alignmentinfo record added
  474. * -Oa argument supports more alignment settings that can be specified
  475. per type: PROC,LOOP,VARMIN,VARMAX,CONSTMIN,CONSTMAX,RECORDMIN
  476. RECORDMAX,LOCALMIN,LOCALMAX. It is possible to set the mimimum
  477. required alignment and the maximum usefull alignment. The final
  478. alignment will be choosen per variable size dependent on these
  479. settings
  480. Revision 1.7 2001/06/28 19:46:25 peter
  481. * added override and virtual for constructors
  482. Revision 1.6 2001/06/03 15:15:32 peter
  483. * dllprt0 stub for linux shared libs
  484. * pass -init and -fini for linux shared libs
  485. * libprefix splitted into staticlibprefix and sharedlibprefix
  486. Revision 1.5 2001/06/02 19:22:44 peter
  487. * extradefines field added
  488. Revision 1.4 2001/05/30 21:35:49 peter
  489. * netware patches for copyright, screenname, threadname directives
  490. Revision 1.3 2001/04/18 22:02:04 peter
  491. * registration of targets and assemblers
  492. Revision 1.2 2001/04/13 01:22:21 peter
  493. * symtable change to classes
  494. * range check generation and errors fixed, make cycle DEBUG=1 works
  495. * memory leaks fixed
  496. Revision 1.1 2001/02/26 19:43:11 peter
  497. * moved target units to subdir
  498. Revision 1.6 2001/02/20 21:41:16 peter
  499. * new fixfilename, findfile for unix. Look first for lowercase, then
  500. NormalCase and last for UPPERCASE names.
  501. Revision 1.5 2000/12/25 00:07:30 peter
  502. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  503. tlinkedlist objects)
  504. Revision 1.4 2000/11/29 00:30:42 florian
  505. * unused units removed from uses clause
  506. * some changes for widestrings
  507. Revision 1.3 2000/10/31 22:02:55 peter
  508. * symtable splitted, no real code changes
  509. Revision 1.2 2000/09/24 15:06:31 peter
  510. * use defines.inc
  511. Revision 1.1 2000/09/11 17:00:23 florian
  512. + first implementation of Netware Module support, thanks to
  513. Armin Diehl ([email protected]) for providing the patches
  514. }