t_win32.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. This unit implements support import,export,link routines
  5. for the (i386) Win32 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_win32;
  20. interface
  21. uses
  22. import,export,link;
  23. const
  24. winstackpagesize = 4096;
  25. type
  26. pimportlibwin32=^timportlibwin32;
  27. timportlibwin32=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. procedure generatesmartlib;virtual;
  33. end;
  34. pexportlibwin32=^texportlibwin32;
  35. texportlibwin32=object(texportlib)
  36. st : string;
  37. last_index : longint;
  38. procedure preparelib(const s:string);virtual;
  39. procedure exportprocedure(hp : pexported_item);virtual;
  40. procedure exportvar(hp : pexported_item);virtual;
  41. procedure generatelib;virtual;
  42. end;
  43. plinkerwin32=^tlinkerwin32;
  44. tlinkerwin32=object(tlinker)
  45. private
  46. Function WriteResponseFile(isdll:boolean) : Boolean;
  47. Function PostProcessExecutable(const fn:string;isdll:boolean) : Boolean;
  48. public
  49. Constructor Init;
  50. Procedure SetDefaultInfo;virtual;
  51. function MakeExecutable:boolean;virtual;
  52. function MakeSharedLibrary:boolean;virtual;
  53. end;
  54. implementation
  55. uses
  56. {$ifdef PAVEL_LINKLIB}
  57. {$ifdef Delphi}
  58. dmisc,
  59. {$else Delphi}
  60. dos,
  61. {$endif Delphi}
  62. impdef,
  63. {$endif PAVEL_LINKLIB}
  64. aasm,files,globtype,globals,cobjects,systems,verbose,
  65. script,gendef,
  66. cpubase,cpuasm
  67. {$ifdef GDB}
  68. ,gdb
  69. {$endif}
  70. ;
  71. function DllName(Const Name : string) : string;
  72. var n : string;
  73. begin
  74. n:=Upper(SplitExtension(Name));
  75. if (n='.DLL') or (n='.DRV') or (n='.EXE') then
  76. DllName:=Name
  77. else
  78. DllName:=Name+target_os.sharedlibext;
  79. end;
  80. {*****************************************************************************
  81. TIMPORTLIBWIN32
  82. *****************************************************************************}
  83. procedure timportlibwin32.preparelib(const s : string);
  84. begin
  85. if not(assigned(importssection)) then
  86. importssection:=new(paasmoutput,init);
  87. end;
  88. procedure timportlibwin32.importprocedure(const func,module : string;index : longint;const name : string);
  89. var
  90. hp1 : pimportlist;
  91. hp2 : pimported_item;
  92. hs : string;
  93. begin
  94. hs:=DllName(module);
  95. { search for the module }
  96. hp1:=pimportlist(current_module^.imports^.first);
  97. while assigned(hp1) do
  98. begin
  99. if hs=hp1^.dllname^ then
  100. break;
  101. hp1:=pimportlist(hp1^.next);
  102. end;
  103. { generate a new item ? }
  104. if not(assigned(hp1)) then
  105. begin
  106. hp1:=new(pimportlist,init(hs));
  107. current_module^.imports^.concat(hp1);
  108. end;
  109. { search for reuse of old import item }
  110. hp2:=pimported_item(hp1^.imported_items^.first);
  111. while assigned(hp2) do
  112. begin
  113. if hp2^.func^=func then
  114. break;
  115. hp2:=pimported_item(hp2^.next);
  116. end;
  117. if not assigned(hp2) then
  118. begin
  119. hp2:=new(pimported_item,init(func,name,index));
  120. hp1^.imported_items^.concat(hp2);
  121. end;
  122. end;
  123. procedure timportlibwin32.importvariable(const varname,module:string;const name:string);
  124. var
  125. hp1 : pimportlist;
  126. hp2 : pimported_item;
  127. hs : string;
  128. begin
  129. hs:=DllName(module);
  130. { search for the module }
  131. hp1:=pimportlist(current_module^.imports^.first);
  132. while assigned(hp1) do
  133. begin
  134. if hs=hp1^.dllname^ then
  135. break;
  136. hp1:=pimportlist(hp1^.next);
  137. end;
  138. { generate a new item ? }
  139. if not(assigned(hp1)) then
  140. begin
  141. hp1:=new(pimportlist,init(hs));
  142. current_module^.imports^.concat(hp1);
  143. end;
  144. hp2:=new(pimported_item,init_var(varname,name));
  145. hp1^.imported_items^.concat(hp2);
  146. end;
  147. procedure timportlibwin32.generatesmartlib;
  148. var
  149. hp1 : pimportlist;
  150. hp2 : pimported_item;
  151. lhead,lname,lcode,
  152. lidata4,lidata5 : pasmlabel;
  153. r : preference;
  154. begin
  155. hp1:=pimportlist(current_module^.imports^.first);
  156. while assigned(hp1) do
  157. begin
  158. { Get labels for the sections }
  159. getdatalabel(lhead);
  160. getdatalabel(lname);
  161. getlabel(lidata4);
  162. getlabel(lidata5);
  163. { create header for this importmodule }
  164. importssection^.concat(new(pai_cut,init_begin));
  165. importssection^.concat(new(pai_section,init(sec_idata2)));
  166. importssection^.concat(new(pai_label,init(lhead)));
  167. { pointer to procedure names }
  168. importssection^.concat(new(pai_const_symbol,init_rva(lidata4)));
  169. { two empty entries follow }
  170. importssection^.concat(new(pai_const,init_32bit(0)));
  171. importssection^.concat(new(pai_const,init_32bit(0)));
  172. { pointer to dll name }
  173. importssection^.concat(new(pai_const_symbol,init_rva(lname)));
  174. { pointer to fixups }
  175. importssection^.concat(new(pai_const_symbol,init_rva(lidata5)));
  176. { first write the name references }
  177. importssection^.concat(new(pai_section,init(sec_idata4)));
  178. importssection^.concat(new(pai_const,init_32bit(0)));
  179. importssection^.concat(new(pai_label,init(lidata4)));
  180. { then the addresses and create also the indirect jump }
  181. importssection^.concat(new(pai_section,init(sec_idata5)));
  182. importssection^.concat(new(pai_const,init_32bit(0)));
  183. importssection^.concat(new(pai_label,init(lidata5)));
  184. { create procedures }
  185. hp2:=pimported_item(hp1^.imported_items^.first);
  186. while assigned(hp2) do
  187. begin
  188. { insert cuts }
  189. importssection^.concat(new(pai_cut,init));
  190. { create indirect jump }
  191. if not hp2^.is_var then
  192. begin
  193. getlabel(lcode);
  194. new(r);
  195. reset_reference(r^);
  196. r^.symbol:=lcode;
  197. { place jump in codesegment, insert a code section in the
  198. importsection to reduce the amount of .s files (PFV) }
  199. importssection^.concat(new(pai_section,init(sec_code)));
  200. {$IfDef GDB}
  201. if (cs_debuginfo in aktmoduleswitches) then
  202. importssection^.concat(new(pai_stab_function_name,init(nil)));
  203. {$EndIf GDB}
  204. importssection^.concat(new(pai_symbol,initname_global(hp2^.func^,0)));
  205. importssection^.concat(new(paicpu,op_ref(A_JMP,S_NO,r)));
  206. importssection^.concat(new(pai_align,init_op(4,$90)));
  207. end;
  208. { create head link }
  209. importssection^.concat(new(pai_section,init(sec_idata7)));
  210. importssection^.concat(new(pai_const_symbol,init_rva(lhead)));
  211. { fixup }
  212. getlabel(pasmlabel(hp2^.lab));
  213. importssection^.concat(new(pai_section,init(sec_idata4)));
  214. importssection^.concat(new(pai_const_symbol,init_rva(hp2^.lab)));
  215. { add jump field to importsection }
  216. importssection^.concat(new(pai_section,init(sec_idata5)));
  217. if hp2^.is_var then
  218. importssection^.concat(new(pai_symbol,initname_global(hp2^.func^,0)))
  219. else
  220. importssection^.concat(new(pai_label,init(lcode)));
  221. if hp2^.name^<>'' then
  222. importssection^.concat(new(pai_const_symbol,init_rva(hp2^.lab)))
  223. else
  224. importssection^.concat(new(pai_const,init_32bit($80000000 or hp2^.ordnr)));
  225. { finally the import information }
  226. importssection^.concat(new(pai_section,init(sec_idata6)));
  227. importssection^.concat(new(pai_label,init(hp2^.lab)));
  228. importssection^.concat(new(pai_const,init_16bit(hp2^.ordnr)));
  229. importssection^.concat(new(pai_string,init(hp2^.name^+#0)));
  230. importssection^.concat(new(pai_align,init_op(2,0)));
  231. hp2:=pimported_item(hp2^.next);
  232. end;
  233. { write final section }
  234. importssection^.concat(new(pai_cut,init_end));
  235. { end of name references }
  236. importssection^.concat(new(pai_section,init(sec_idata4)));
  237. importssection^.concat(new(pai_const,init_32bit(0)));
  238. { end if addresses }
  239. importssection^.concat(new(pai_section,init(sec_idata5)));
  240. importssection^.concat(new(pai_const,init_32bit(0)));
  241. { dllname }
  242. importssection^.concat(new(pai_section,init(sec_idata7)));
  243. importssection^.concat(new(pai_label,init(lname)));
  244. importssection^.concat(new(pai_string,init(hp1^.dllname^+#0)));
  245. hp1:=pimportlist(hp1^.next);
  246. end;
  247. end;
  248. procedure timportlibwin32.generatelib;
  249. var
  250. hp1 : pimportlist;
  251. hp2 : pimported_item;
  252. l1,l2,l3,l4 : pasmlabel;
  253. r : preference;
  254. begin
  255. hp1:=pimportlist(current_module^.imports^.first);
  256. while assigned(hp1) do
  257. begin
  258. { align codesegment for the jumps }
  259. importssection^.concat(new(pai_section,init(sec_code)));
  260. importssection^.concat(new(pai_align,init_op(4,$90)));
  261. { Get labels for the sections }
  262. getlabel(l1);
  263. getlabel(l2);
  264. getlabel(l3);
  265. importssection^.concat(new(pai_section,init(sec_idata2)));
  266. { pointer to procedure names }
  267. importssection^.concat(new(pai_const_symbol,init_rva(l2)));
  268. { two empty entries follow }
  269. importssection^.concat(new(pai_const,init_32bit(0)));
  270. importssection^.concat(new(pai_const,init_32bit(0)));
  271. { pointer to dll name }
  272. importssection^.concat(new(pai_const_symbol,init_rva(l1)));
  273. { pointer to fixups }
  274. importssection^.concat(new(pai_const_symbol,init_rva(l3)));
  275. { only create one section for each else it will
  276. create a lot of idata* }
  277. { first write the name references }
  278. importssection^.concat(new(pai_section,init(sec_idata4)));
  279. importssection^.concat(new(pai_label,init(l2)));
  280. hp2:=pimported_item(hp1^.imported_items^.first);
  281. while assigned(hp2) do
  282. begin
  283. getlabel(pasmlabel(hp2^.lab));
  284. if hp2^.name^<>'' then
  285. importssection^.concat(new(pai_const_symbol,init_rva(hp2^.lab)))
  286. else
  287. importssection^.concat(new(pai_const,init_32bit($80000000 or hp2^.ordnr)));
  288. hp2:=pimported_item(hp2^.next);
  289. end;
  290. { finalize the names ... }
  291. importssection^.concat(new(pai_const,init_32bit(0)));
  292. { then the addresses and create also the indirect jump }
  293. importssection^.concat(new(pai_section,init(sec_idata5)));
  294. importssection^.concat(new(pai_label,init(l3)));
  295. hp2:=pimported_item(hp1^.imported_items^.first);
  296. while assigned(hp2) do
  297. begin
  298. if not hp2^.is_var then
  299. begin
  300. getlabel(l4);
  301. { create indirect jump }
  302. new(r);
  303. reset_reference(r^);
  304. r^.symbol:=l4;
  305. { place jump in codesegment }
  306. importssection^.concat(new(pai_section,init(sec_code)));
  307. importssection^.concat(new(pai_symbol,initname_global(hp2^.func^,0)));
  308. importssection^.concat(new(paicpu,op_ref(A_JMP,S_NO,r)));
  309. importssection^.concat(new(pai_align,init_op(4,$90)));
  310. { add jump field to importsection }
  311. importssection^.concat(new(pai_section,init(sec_idata5)));
  312. importssection^.concat(new(pai_label,init(l4)));
  313. end
  314. else
  315. begin
  316. importssection^.concat(new(pai_symbol,initname_global(hp2^.func^,0)));
  317. end;
  318. importssection^.concat(new(pai_const_symbol,init_rva(hp2^.lab)));
  319. hp2:=pimported_item(hp2^.next);
  320. end;
  321. { finalize the addresses }
  322. importssection^.concat(new(pai_const,init_32bit(0)));
  323. { finally the import information }
  324. importssection^.concat(new(pai_section,init(sec_idata6)));
  325. hp2:=pimported_item(hp1^.imported_items^.first);
  326. while assigned(hp2) do
  327. begin
  328. importssection^.concat(new(pai_label,init(hp2^.lab)));
  329. { the ordinal number }
  330. importssection^.concat(new(pai_const,init_16bit(hp2^.ordnr)));
  331. importssection^.concat(new(pai_string,init(hp2^.name^+#0)));
  332. importssection^.concat(new(pai_align,init_op(2,0)));
  333. hp2:=pimported_item(hp2^.next);
  334. end;
  335. { create import dll name }
  336. importssection^.concat(new(pai_section,init(sec_idata7)));
  337. importssection^.concat(new(pai_label,init(l1)));
  338. importssection^.concat(new(pai_string,init(hp1^.dllname^+#0)));
  339. hp1:=pimportlist(hp1^.next);
  340. end;
  341. end;
  342. {*****************************************************************************
  343. TEXPORTLIBWIN32
  344. *****************************************************************************}
  345. procedure texportlibwin32.preparelib(const s:string);
  346. begin
  347. if not(assigned(exportssection)) then
  348. exportssection:=new(paasmoutput,init);
  349. last_index:=0;
  350. end;
  351. procedure texportlibwin32.exportvar(hp : pexported_item);
  352. begin
  353. { same code used !! PM }
  354. exportprocedure(hp);
  355. end;
  356. procedure texportlibwin32.exportprocedure(hp : pexported_item);
  357. { must be ordered at least for win32 !! }
  358. var
  359. hp2 : pexported_item;
  360. begin
  361. { first test the index value }
  362. if (hp^.options and eo_index)<>0 then
  363. begin
  364. if (hp^.index<=0) or (hp^.index>$ffff) then
  365. begin
  366. message1(parser_e_export_invalid_index,tostr(hp^.index));
  367. exit;
  368. end;
  369. if (hp^.index<=last_index) then
  370. begin
  371. message1(parser_e_export_ordinal_double,tostr(hp^.index));
  372. { disregard index value }
  373. inc(last_index);
  374. hp^.index:=last_index;
  375. exit;
  376. end
  377. else
  378. begin
  379. last_index:=hp^.index;
  380. end;
  381. end
  382. else
  383. begin
  384. inc(last_index);
  385. hp^.index:=last_index;
  386. end;
  387. { use pascal name is none specified }
  388. if (hp^.options and eo_name)=0 then
  389. begin
  390. hp^.name:=stringdup(hp^.sym^.name);
  391. hp^.options:=hp^.options or eo_name;
  392. end;
  393. { now place in correct order }
  394. hp2:=pexported_item(current_module^._exports^.first);
  395. while assigned(hp2) and
  396. (hp^.name^>hp2^.name^) do
  397. hp2:=pexported_item(hp2^.next);
  398. { insert hp there !! }
  399. if assigned(hp2) and (hp2^.name^=hp^.name^) then
  400. begin
  401. { this is not allowed !! }
  402. message1(parser_e_export_name_double,hp^.name^);
  403. exit;
  404. end;
  405. if hp2=pexported_item(current_module^._exports^.first) then
  406. current_module^._exports^.insert(hp)
  407. else if assigned(hp2) then
  408. begin
  409. hp^.next:=hp2;
  410. hp^.previous:=hp2^.previous;
  411. if assigned(hp2^.previous) then
  412. hp2^.previous^.next:=hp;
  413. hp2^.previous:=hp;
  414. end
  415. else
  416. current_module^._exports^.concat(hp);
  417. end;
  418. procedure texportlibwin32.generatelib;
  419. var
  420. ordinal_base,ordinal_max,ordinal_min : longint;
  421. current_index : longint;
  422. entries,named_entries : longint;
  423. name_label,dll_name_label,export_address_table : pasmlabel;
  424. export_name_table_pointers,export_ordinal_table : pasmlabel;
  425. hp,hp2 : pexported_item;
  426. tempexport : plinkedlist;
  427. address_table,name_table_pointers,
  428. name_table,ordinal_table : paasmoutput;
  429. begin
  430. ordinal_max:=0;
  431. ordinal_min:=$7FFFFFFF;
  432. entries:=0;
  433. named_entries:=0;
  434. getlabel(dll_name_label);
  435. getlabel(export_address_table);
  436. getlabel(export_name_table_pointers);
  437. getlabel(export_ordinal_table);
  438. hp:=pexported_item(current_module^._exports^.first);
  439. { count entries }
  440. while assigned(hp) do
  441. begin
  442. inc(entries);
  443. if (hp^.index>ordinal_max) then
  444. ordinal_max:=hp^.index;
  445. if (hp^.index>0) and (hp^.index<ordinal_min) then
  446. ordinal_min:=hp^.index;
  447. if assigned(hp^.name) then
  448. inc(named_entries);
  449. hp:=pexported_item(hp^.next);
  450. end;
  451. { no support for higher ordinal base yet !! }
  452. ordinal_base:=1;
  453. current_index:=ordinal_base;
  454. { we must also count the holes !! }
  455. entries:=ordinal_max-ordinal_base+1;
  456. exportssection^.concat(new(pai_section,init(sec_edata)));
  457. { export flags }
  458. exportssection^.concat(new(pai_const,init_32bit(0)));
  459. { date/time stamp }
  460. exportssection^.concat(new(pai_const,init_32bit(0)));
  461. { major version }
  462. exportssection^.concat(new(pai_const,init_16bit(0)));
  463. { minor version }
  464. exportssection^.concat(new(pai_const,init_16bit(0)));
  465. { pointer to dll name }
  466. exportssection^.concat(new(pai_const_symbol,init_rva(dll_name_label)));
  467. { ordinal base normally set to 1 }
  468. exportssection^.concat(new(pai_const,init_32bit(ordinal_base)));
  469. { number of entries }
  470. exportssection^.concat(new(pai_const,init_32bit(entries)));
  471. { number of named entries }
  472. exportssection^.concat(new(pai_const,init_32bit(named_entries)));
  473. { address of export address table }
  474. exportssection^.concat(new(pai_const_symbol,init_rva(export_address_table)));
  475. { address of name pointer pointers }
  476. exportssection^.concat(new(pai_const_symbol,init_rva(export_name_table_pointers)));
  477. { address of ordinal number pointers }
  478. exportssection^.concat(new(pai_const_symbol,init_rva(export_ordinal_table)));
  479. { the name }
  480. exportssection^.concat(new(pai_label,init(dll_name_label)));
  481. if st='' then
  482. exportssection^.concat(new(pai_string,init(current_module^.modulename^+target_os.sharedlibext+#0)))
  483. else
  484. exportssection^.concat(new(pai_string,init(st+target_os.sharedlibext+#0)));
  485. { export address table }
  486. address_table:=new(paasmoutput,init);
  487. address_table^.concat(new(pai_align,init_op(4,0)));
  488. address_table^.concat(new(pai_label,init(export_address_table)));
  489. name_table_pointers:=new(paasmoutput,init);
  490. name_table_pointers^.concat(new(pai_align,init_op(4,0)));
  491. name_table_pointers^.concat(new(pai_label,init(export_name_table_pointers)));
  492. ordinal_table:=new(paasmoutput,init);
  493. ordinal_table^.concat(new(pai_align,init_op(4,0)));
  494. ordinal_table^.concat(new(pai_label,init(export_ordinal_table)));
  495. name_table:=new(paasmoutput,init);
  496. name_table^.concat(new(pai_align,init_op(4,0)));
  497. { write each address }
  498. hp:=pexported_item(current_module^._exports^.first);
  499. while assigned(hp) do
  500. begin
  501. if (hp^.options and eo_name)<>0 then
  502. begin
  503. getlabel(name_label);
  504. name_table_pointers^.concat(new(pai_const_symbol,init_rva(name_label)));
  505. ordinal_table^.concat(new(pai_const,init_16bit(hp^.index-ordinal_base)));
  506. name_table^.concat(new(pai_align,init_op(2,0)));
  507. name_table^.concat(new(pai_label,init(name_label)));
  508. name_table^.concat(new(pai_string,init(hp^.name^+#0)));
  509. end;
  510. hp:=pexported_item(hp^.next);
  511. end;
  512. { order in increasing ordinal values }
  513. { into tempexport list }
  514. tempexport:=new(plinkedlist,init);
  515. hp:=pexported_item(current_module^._exports^.first);
  516. while assigned(hp) do
  517. begin
  518. current_module^._exports^.remove(hp);
  519. hp2:=pexported_item(tempexport^.first);
  520. while assigned(hp2) and (hp^.index>hp2^.index) do
  521. begin
  522. hp2:=pexported_item(hp2^.next);
  523. end;
  524. if hp2=pexported_item(tempexport^.first) then
  525. tempexport^.insert(hp)
  526. else
  527. begin
  528. if assigned(hp2) then
  529. begin
  530. hp^.next:=hp2;
  531. hp^.previous:=hp2^.previous;
  532. hp2^.previous:=hp;
  533. if assigned(hp^.previous) then
  534. hp^.previous^.next:=hp;
  535. end
  536. else
  537. tempexport^.concat(hp);
  538. end;
  539. hp:=pexported_item(current_module^._exports^.first);;
  540. end;
  541. { write the export adress table }
  542. current_index:=ordinal_base;
  543. hp:=pexported_item(tempexport^.first);
  544. while assigned(hp) do
  545. begin
  546. { fill missing values }
  547. while current_index<hp^.index do
  548. begin
  549. address_table^.concat(new(pai_const,init_32bit(0)));
  550. inc(current_index);
  551. end;
  552. address_table^.concat(new(pai_const_symbol,initname_rva(hp^.sym^.mangledname)));
  553. inc(current_index);
  554. hp:=pexported_item(hp^.next);
  555. end;
  556. exportssection^.concatlist(address_table);
  557. exportssection^.concatlist(name_table_pointers);
  558. exportssection^.concatlist(ordinal_table);
  559. exportssection^.concatlist(name_table);
  560. dispose(address_table,done);
  561. dispose(name_table_pointers,done);
  562. dispose(ordinal_table,done);
  563. dispose(name_table,done);
  564. dispose(tempexport,done);
  565. end;
  566. {****************************************************************************
  567. TLINKERWIN32
  568. ****************************************************************************}
  569. Constructor TLinkerWin32.Init;
  570. begin
  571. Inherited Init;
  572. { allow duplicated libs (PM) }
  573. SharedLibFiles.doubles:=true;
  574. StaticLibFiles.doubles:=true;
  575. If not ForceDeffileForExport then
  576. UseDeffileForExport:=false;
  577. end;
  578. Procedure TLinkerWin32.SetDefaultInfo;
  579. begin
  580. with Info do
  581. begin
  582. ExeCmd[1]:='ldw $OPT $STRIP $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
  583. DllCmd[1]:='ldw $OPT $STRIP --dll $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
  584. if RelocSection or UseDeffileForExport then
  585. begin
  586. { ExeCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF';
  587. use short forms to avoid 128 char limitation problem }
  588. ExeCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
  589. ExeCmd[3]:='ldw $OPT $STRIP $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
  590. { DllCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF'; }
  591. DllCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
  592. DllCmd[3]:='ldw $OPT $STRIP --dll $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
  593. end;
  594. end;
  595. end;
  596. {$ifndef PAVEL_LINKLIB}
  597. Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
  598. Var
  599. linkres : TLinkRes;
  600. i : longint;
  601. {$IFDEF NEWST}
  602. HPath : PStringItem;
  603. {$ELSE}
  604. HPath : PStringQueueItem;
  605. {$ENDIF NEWST}
  606. s,s2 : string;
  607. found,linklibc : boolean;
  608. begin
  609. WriteResponseFile:=False;
  610. { Open link.res file }
  611. LinkRes.Init(outputexedir+Info.ResName);
  612. { Write path to search libraries }
  613. HPath:=current_module^.locallibrarysearchpath.First;
  614. while assigned(HPath) do
  615. begin
  616. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath^.Data^)+')');
  617. HPath:=HPath^.Next;
  618. end;
  619. HPath:=LibrarySearchPath.First;
  620. while assigned(HPath) do
  621. begin
  622. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath^.Data^)+')');
  623. HPath:=HPath^.Next;
  624. end;
  625. { add objectfiles, start with prt0 always }
  626. LinkRes.Add('INPUT(');
  627. if isdll then
  628. LinkRes.AddFileName(GetShortName(FindObjectFile('wdllprt0')))
  629. else
  630. LinkRes.AddFileName(GetShortName(FindObjectFile('wprt0')));
  631. while not ObjectFiles.Empty do
  632. begin
  633. s:=ObjectFiles.Get;
  634. if s<>'' then
  635. LinkRes.AddFileName(GetShortName(s));
  636. end;
  637. LinkRes.Add(')');
  638. { Write staticlibraries }
  639. if not StaticLibFiles.Empty then
  640. begin
  641. LinkRes.Add('GROUP(');
  642. While not StaticLibFiles.Empty do
  643. begin
  644. S:=StaticLibFiles.Get;
  645. LinkRes.AddFileName(GetShortName(s));
  646. end;
  647. LinkRes.Add(')');
  648. end;
  649. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  650. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  651. if not SharedLibFiles.Empty then
  652. begin
  653. linklibc:=false;
  654. LinkRes.Add('INPUT(');
  655. While not SharedLibFiles.Empty do
  656. begin
  657. S:=SharedLibFiles.Get;
  658. if pos('.',s)=0 then
  659. { we never directly link a DLL
  660. its allways through an import library PM }
  661. { libraries created by C compilers have .a extensions }
  662. s2:=s+'.a'{ target_os.sharedlibext }
  663. else
  664. s2:=s;
  665. s2:=FindLibraryFile(s2,'',found);
  666. if found then
  667. begin
  668. LinkRes.Add(s2);
  669. continue;
  670. end;
  671. if pos(target_os.libprefix,s)=1 then
  672. s:=copy(s,length(target_os.libprefix)+1,255);
  673. if s<>'c' then
  674. begin
  675. i:=Pos(target_os.sharedlibext,S);
  676. if i>0 then
  677. Delete(S,i,255);
  678. LinkRes.Add('-l'+s);
  679. end
  680. else
  681. begin
  682. LinkRes.Add('-l'+s);
  683. linklibc:=true;
  684. end;
  685. end;
  686. { be sure that libc is the last lib }
  687. if linklibc then
  688. LinkRes.Add('-lc');
  689. LinkRes.Add(')');
  690. end;
  691. { Write and Close response }
  692. linkres.writetodisk;
  693. linkres.done;
  694. WriteResponseFile:=True;
  695. end;
  696. {$else PAVEL_LINKLIB}
  697. Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
  698. Var
  699. linkres : TLinkRes;
  700. HPath : {$ifdef NEWST} PStringItem {$else} PStringQueueItem {$endif};
  701. s,s2 : string;
  702. success : boolean;
  703. function ExpandName(const s:string):string;
  704. var
  705. sysdir:string;
  706. procedure GetSysDir;
  707. begin
  708. sysdir:=GetEnv('windir');
  709. if sysdir<>''then
  710. begin
  711. if not(sysdir[length(sysdir)]in['\','/'])then
  712. sysdir:=sysdir+dirsep;
  713. end;
  714. end;
  715. function IsFile(d:string;var PathToDll:string):longbool;
  716. var
  717. f:file;
  718. attr:word;
  719. begin
  720. PathToDll:='';
  721. if d<>''then
  722. if d[length(d)]<>dirsep then
  723. d:=d+dirsep;
  724. d:=d+s;
  725. assign(f,d);
  726. GetFattr(f,Attr);
  727. if DOSerror<>0 then
  728. IsFile:=false
  729. else
  730. begin
  731. if(attr and directory)=0 then
  732. begin
  733. IsFile:=true;
  734. PathToDll:=GetShortName(d);
  735. end
  736. else
  737. IsFile:=false;
  738. end;
  739. end;
  740. var
  741. PathToDll:string;
  742. begin
  743. if not isFile('',PathToDll)then
  744. begin
  745. HPath:=LibrarySearchPath.First;
  746. while assigned(HPath) do
  747. begin
  748. if isFile(GetShortName(HPath^.Data^),PathToDll)then
  749. break;
  750. HPath:=HPath^.Next;
  751. end;
  752. if PathToDll='' then
  753. begin
  754. GetSysDir;
  755. if not isFile(sysdir,PathToDll)then
  756. if not isFile(sysdir+'system32',PathToDll)then
  757. if not isFile(sysdir+'system',PathToDll)then
  758. begin
  759. message1(exec_w_libfile_not_found,S2);
  760. PathToDll:=S2;
  761. end;
  762. end;
  763. end;
  764. ExpandName:=PathToDll;
  765. end;
  766. function DotPos(const s:string):longint;
  767. var
  768. i:longint;
  769. begin
  770. DotPos:=0;
  771. for i:=length(s)downto 1 do
  772. begin
  773. if s[i]in['/','\',':']then
  774. exit
  775. else if s[i]='.'then
  776. begin
  777. DotPos:=i;
  778. exit;
  779. end;
  780. end;
  781. end;
  782. procedure strip(var s:string);
  783. var
  784. d:dirstr;
  785. n:namestr;
  786. e:extstr;
  787. begin
  788. fsplit(s,d,n,e);
  789. s:=n;
  790. end;
  791. function do_makedef(const s:string):longbool;
  792. begin
  793. if cs_link_extern in aktglobalswitches then
  794. do_makedef:=DoExec(FindUtil('fpimpdef'),'-o deffile.$$$ -i '+s,false,false)
  795. else
  796. do_makedef:=makedef(s,'deffile.$$$');
  797. end;
  798. begin
  799. WriteResponseFile:=False;
  800. While not SharedLibFiles.Empty do
  801. begin
  802. S:=SharedLibFiles.Get;
  803. if DotPos(s)=0 then
  804. s2:=s+target_os.sharedlibext
  805. else
  806. s2:=s;
  807. strip(s);
  808. if not do_makedef(ExpandName(s2))then
  809. begin
  810. Message(exec_w_error_while_linking);
  811. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  812. end
  813. else
  814. begin
  815. s:=target_os.libprefix+s+target_os.staticlibext;
  816. success:=DoExec(FindUtil('dlltool'),'-l '+s+' -D '+s2+' -d deffile.$$$',false,false);
  817. ObjectFiles.insert(s);
  818. if not success then
  819. break;
  820. end;
  821. end;
  822. { Open link.res file }
  823. LinkRes.Init(outputexedir+Info.ResName);
  824. { Write path to search libraries }
  825. HPath:=current_module^.locallibrarysearchpath.First;
  826. while assigned(HPath) do
  827. begin
  828. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath^.Data^)+')');
  829. HPath:=HPath^.Next;
  830. end;
  831. HPath:=LibrarySearchPath.First;
  832. while assigned(HPath) do
  833. begin
  834. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath^.Data^)+')');
  835. HPath:=HPath^.Next;
  836. end;
  837. { add objectfiles, start with prt0 always }
  838. LinkRes.Add('INPUT(');
  839. if isdll then
  840. LinkRes.AddFileName(GetShortName(FindObjectFile('wdllprt0')))
  841. else
  842. LinkRes.AddFileName(GetShortName(FindObjectFile('wprt0')));
  843. while not ObjectFiles.Empty do
  844. begin
  845. s:=ObjectFiles.Get;
  846. if s<>'' then
  847. LinkRes.AddFileName(GetShortName(s));
  848. end;
  849. LinkRes.Add(')');
  850. { Write staticlibraries }
  851. if not StaticLibFiles.Empty then
  852. begin
  853. LinkRes.Add('GROUP(');
  854. While not StaticLibFiles.Empty do
  855. begin
  856. S:=StaticLibFiles.Get;
  857. LinkRes.AddFileName(GetShortName(s));
  858. end;
  859. LinkRes.Add(')');
  860. end;
  861. { Write and Close response }
  862. linkres.writetodisk;
  863. linkres.done;
  864. WriteResponseFile:=True;
  865. end;
  866. {$endif PAVEL_LINKLIB}
  867. function TLinkerWin32.MakeExecutable:boolean;
  868. var
  869. binstr,
  870. cmdstr : string;
  871. found,
  872. success : boolean;
  873. i : longint;
  874. AsBinStr : string[80];
  875. StripStr,
  876. RelocStr,
  877. AppTypeStr,
  878. ImageBaseStr : string[40];
  879. begin
  880. if not(cs_link_extern in aktglobalswitches) then
  881. Message1(exec_i_linking,current_module^.exefilename^);
  882. { Create some replacements }
  883. RelocStr:='';
  884. AppTypeStr:='';
  885. ImageBaseStr:='';
  886. StripStr:='';
  887. AsBinStr:=FindExe('asw',found);
  888. if RelocSection then
  889. { Using short form to avoid problems with 128 char limitation under Dos. }
  890. RelocStr:='-b base.$$$';
  891. if apptype=at_gui then
  892. AppTypeStr:='--subsystem windows';
  893. if assigned(DLLImageBase) then
  894. ImageBaseStr:='--image-base=0x'+DLLImageBase^;
  895. if (cs_link_strip in aktglobalswitches) then
  896. StripStr:='-s';
  897. { Write used files and libraries }
  898. WriteResponseFile(false);
  899. { Call linker }
  900. success:=false;
  901. for i:=1 to 3 do
  902. begin
  903. SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
  904. if binstr<>'' then
  905. begin
  906. Replace(cmdstr,'$EXE',current_module^.exefilename^);
  907. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  908. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  909. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  910. Replace(cmdstr,'$ASBIN',AsbinStr);
  911. Replace(cmdstr,'$RELOC',RelocStr);
  912. Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
  913. Replace(cmdstr,'$STRIP',StripStr);
  914. if not DefFile.Empty {and UseDefFileForExport} then
  915. begin
  916. DefFile.WriteFile;
  917. Replace(cmdstr,'$DEF','-d '+deffile.fname);
  918. end
  919. else
  920. Replace(cmdstr,'$DEF','');
  921. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
  922. if not success then
  923. break;
  924. end;
  925. end;
  926. { Post process }
  927. if success then
  928. success:=PostProcessExecutable(current_module^.exefilename^,false);
  929. { Remove ReponseFile }
  930. if (success) and not(cs_link_extern in aktglobalswitches) then
  931. begin
  932. RemoveFile(outputexedir+Info.ResName);
  933. RemoveFile('base.$$$');
  934. RemoveFile('exp.$$$');
  935. RemoveFile('deffile.$$$');
  936. end;
  937. MakeExecutable:=success; { otherwise a recursive call to link method }
  938. end;
  939. Function TLinkerWin32.MakeSharedLibrary:boolean;
  940. var
  941. binstr,
  942. cmdstr : string;
  943. found,
  944. success : boolean;
  945. i : longint;
  946. AsBinStr : string[80];
  947. StripStr,
  948. RelocStr,
  949. AppTypeStr,
  950. ImageBaseStr : string[40];
  951. begin
  952. MakeSharedLibrary:=false;
  953. if not(cs_link_extern in aktglobalswitches) then
  954. Message1(exec_i_linking,current_module^.sharedlibfilename^);
  955. { Create some replacements }
  956. RelocStr:='';
  957. AppTypeStr:='';
  958. ImageBaseStr:='';
  959. StripStr:='';
  960. AsBinStr:=FindExe('asw',found);
  961. if RelocSection then
  962. { Using short form to avoid problems with 128 char limitation under Dos. }
  963. RelocStr:='-b base.$$$';
  964. if apptype=at_gui then
  965. AppTypeStr:='--subsystem windows';
  966. if assigned(DLLImageBase) then
  967. ImageBaseStr:='--image-base=0x'+DLLImageBase^;
  968. if (cs_link_strip in aktglobalswitches) then
  969. StripStr:='-s';
  970. { Write used files and libraries }
  971. WriteResponseFile(true);
  972. { Call linker }
  973. success:=false;
  974. for i:=1 to 3 do
  975. begin
  976. SplitBinCmd(Info.DllCmd[i],binstr,cmdstr);
  977. if binstr<>'' then
  978. begin
  979. Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
  980. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  981. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  982. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  983. Replace(cmdstr,'$ASBIN',AsbinStr);
  984. Replace(cmdstr,'$RELOC',RelocStr);
  985. Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
  986. Replace(cmdstr,'$STRIP',StripStr);
  987. if not DefFile.Empty {and UseDefFileForExport} then
  988. begin
  989. DefFile.WriteFile;
  990. Replace(cmdstr,'$DEF','-d '+deffile.fname);
  991. end
  992. else
  993. Replace(cmdstr,'$DEF','');
  994. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
  995. if not success then
  996. break;
  997. end;
  998. end;
  999. { Post process }
  1000. if success then
  1001. success:=PostProcessExecutable(current_module^.sharedlibfilename^,true);
  1002. { Remove ReponseFile }
  1003. if (success) and not(cs_link_extern in aktglobalswitches) then
  1004. begin
  1005. RemoveFile(outputexedir+Info.ResName);
  1006. RemoveFile('base.$$$');
  1007. RemoveFile('exp.$$$');
  1008. end;
  1009. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  1010. end;
  1011. function tlinkerwin32.postprocessexecutable(const fn : string;isdll:boolean):boolean;
  1012. type
  1013. tdosheader = packed record
  1014. e_magic : word;
  1015. e_cblp : word;
  1016. e_cp : word;
  1017. e_crlc : word;
  1018. e_cparhdr : word;
  1019. e_minalloc : word;
  1020. e_maxalloc : word;
  1021. e_ss : word;
  1022. e_sp : word;
  1023. e_csum : word;
  1024. e_ip : word;
  1025. e_cs : word;
  1026. e_lfarlc : word;
  1027. e_ovno : word;
  1028. e_res : array[0..3] of word;
  1029. e_oemid : word;
  1030. e_oeminfo : word;
  1031. e_res2 : array[0..9] of word;
  1032. e_lfanew : longint;
  1033. end;
  1034. tpeheader = packed record
  1035. PEMagic : array[0..3] of char;
  1036. Machine : word;
  1037. NumberOfSections : word;
  1038. TimeDateStamp : longint;
  1039. PointerToSymbolTable : longint;
  1040. NumberOfSymbols : longint;
  1041. SizeOfOptionalHeader : word;
  1042. Characteristics : word;
  1043. Magic : word;
  1044. MajorLinkerVersion : byte;
  1045. MinorLinkerVersion : byte;
  1046. SizeOfCode : longint;
  1047. SizeOfInitializedData : longint;
  1048. SizeOfUninitializedData : longint;
  1049. AddressOfEntryPoint : longint;
  1050. BaseOfCode : longint;
  1051. BaseOfData : longint;
  1052. ImageBase : longint;
  1053. SectionAlignment : longint;
  1054. FileAlignment : longint;
  1055. MajorOperatingSystemVersion : word;
  1056. MinorOperatingSystemVersion : word;
  1057. MajorImageVersion : word;
  1058. MinorImageVersion : word;
  1059. MajorSubsystemVersion : word;
  1060. MinorSubsystemVersion : word;
  1061. Reserved1 : longint;
  1062. SizeOfImage : longint;
  1063. SizeOfHeaders : longint;
  1064. CheckSum : longint;
  1065. Subsystem : word;
  1066. DllCharacteristics : word;
  1067. SizeOfStackReserve : longint;
  1068. SizeOfStackCommit : longint;
  1069. SizeOfHeapReserve : longint;
  1070. SizeOfHeapCommit : longint;
  1071. LoaderFlags : longint;
  1072. NumberOfRvaAndSizes : longint;
  1073. DataDirectory : array[1..$80] of byte;
  1074. end;
  1075. tcoffsechdr=packed record
  1076. name : array[0..7] of char;
  1077. vsize : longint;
  1078. rvaofs : longint;
  1079. datalen : longint;
  1080. datapos : longint;
  1081. relocpos : longint;
  1082. lineno1 : longint;
  1083. nrelocs : word;
  1084. lineno2 : word;
  1085. flags : longint;
  1086. end;
  1087. psecfill=^tsecfill;
  1088. tsecfill=record
  1089. fillpos,
  1090. fillsize : longint;
  1091. next : psecfill;
  1092. end;
  1093. var
  1094. f : file;
  1095. cmdstr : string;
  1096. dosheader : tdosheader;
  1097. peheader : tpeheader;
  1098. firstsecpos,
  1099. maxfillsize,
  1100. l,peheaderpos : longint;
  1101. coffsec : tcoffsechdr;
  1102. secroot,hsecroot : psecfill;
  1103. zerobuf : pointer;
  1104. begin
  1105. postprocessexecutable:=false;
  1106. { when -s is used or it's a dll then quit }
  1107. if (cs_link_extern in aktglobalswitches) then
  1108. begin
  1109. if apptype=at_gui then
  1110. cmdstr:='--subsystem gui'
  1111. else if apptype=at_cui then
  1112. cmdstr:='--subsystem console';
  1113. if dllversion<>'' then
  1114. cmdstr:=cmdstr+' --version '+dllversion;
  1115. cmdstr:=cmdstr+' --input '+fn;
  1116. cmdstr:=cmdstr+' --stack '+tostr(stacksize);
  1117. DoExec(FindUtil('postw32'),cmdstr,false,false);
  1118. postprocessexecutable:=true;
  1119. exit;
  1120. end;
  1121. { open file }
  1122. assign(f,fn);
  1123. {$I-}
  1124. reset(f,1);
  1125. if ioresult<>0 then
  1126. Message1(execinfo_f_cant_open_executable,fn);
  1127. { read headers }
  1128. blockread(f,dosheader,sizeof(tdosheader));
  1129. peheaderpos:=dosheader.e_lfanew;
  1130. seek(f,peheaderpos);
  1131. blockread(f,peheader,sizeof(tpeheader));
  1132. { write info }
  1133. Message1(execinfo_x_codesize,tostr(peheader.SizeOfCode));
  1134. Message1(execinfo_x_initdatasize,tostr(peheader.SizeOfInitializedData));
  1135. Message1(execinfo_x_uninitdatasize,tostr(peheader.SizeOfUninitializedData));
  1136. { change stack size (PM) }
  1137. { I am not sure that the default value is adequate !! }
  1138. peheader.SizeOfStackReserve:=stacksize;
  1139. { change the header }
  1140. { sub system }
  1141. { gui=2 }
  1142. { cui=3 }
  1143. if apptype=at_gui then
  1144. peheader.Subsystem:=2
  1145. else if apptype=at_cui then
  1146. peheader.Subsystem:=3;
  1147. if dllversion<>'' then
  1148. begin
  1149. peheader.MajorImageVersion:=dllmajor;
  1150. peheader.MinorImageVersion:=dllminor;
  1151. end;
  1152. { reset timestamp }
  1153. peheader.TimeDateStamp:=0;
  1154. { write header back }
  1155. seek(f,peheaderpos);
  1156. blockwrite(f,peheader,sizeof(tpeheader));
  1157. if ioresult<>0 then
  1158. Message1(execinfo_f_cant_process_executable,fn);
  1159. seek(f,peheaderpos);
  1160. blockread(f,peheader,sizeof(tpeheader));
  1161. { write the value after the change }
  1162. Message1(execinfo_x_stackreserve,tostr(peheader.SizeOfStackReserve));
  1163. Message1(execinfo_x_stackcommit,tostr(peheader.SizeOfStackCommit));
  1164. { read section info }
  1165. maxfillsize:=0;
  1166. firstsecpos:=0;
  1167. secroot:=nil;
  1168. for l:=1 to peheader.NumberOfSections do
  1169. begin
  1170. blockread(f,coffsec,sizeof(tcoffsechdr));
  1171. if coffsec.datapos>0 then
  1172. begin
  1173. if secroot=nil then
  1174. firstsecpos:=coffsec.datapos;
  1175. new(hsecroot);
  1176. hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
  1177. hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
  1178. hsecroot^.next:=secroot;
  1179. secroot:=hsecroot;
  1180. if secroot^.fillsize>maxfillsize then
  1181. maxfillsize:=secroot^.fillsize;
  1182. end;
  1183. end;
  1184. if firstsecpos>0 then
  1185. begin
  1186. l:=firstsecpos-filepos(f);
  1187. if l>maxfillsize then
  1188. maxfillsize:=l;
  1189. end
  1190. else
  1191. l:=0;
  1192. { get zero buffer }
  1193. getmem(zerobuf,maxfillsize);
  1194. fillchar(zerobuf^,maxfillsize,0);
  1195. { zero from sectioninfo until first section }
  1196. blockwrite(f,zerobuf^,l);
  1197. { zero section alignments }
  1198. while assigned(secroot) do
  1199. begin
  1200. seek(f,secroot^.fillpos);
  1201. blockwrite(f,zerobuf^,secroot^.fillsize);
  1202. hsecroot:=secroot;
  1203. secroot:=secroot^.next;
  1204. dispose(hsecroot);
  1205. end;
  1206. freemem(zerobuf,maxfillsize);
  1207. close(f);
  1208. {$I+}
  1209. if ioresult<>0 then;
  1210. postprocessexecutable:=true;
  1211. end;
  1212. end.
  1213. {
  1214. $Log$
  1215. Revision 1.23 2000-05-23 20:18:25 pierre
  1216. + pavel's code integrated, but onyl inside
  1217. ifdef pavel_linklib !
  1218. Revision 1.22 2000/04/14 11:16:10 pierre
  1219. * partial linklib change
  1220. I could not use Pavel's code because it broke the current way
  1221. linklib is used, which is messy :(
  1222. + add postw32 call if external linking on win32
  1223. Revision 1.21 2000/03/10 09:14:40 pierre
  1224. * dlltool is also needed if we use DefFile
  1225. Revision 1.20 2000/02/28 17:23:57 daniel
  1226. * Current work of symtable integration committed. The symtable can be
  1227. activated by defining 'newst', but doesn't compile yet. Changes in type
  1228. checking and oop are completed. What is left is to write a new
  1229. symtablestack and adapt the parser to use it.
  1230. Revision 1.19 2000/02/24 18:41:39 peter
  1231. * removed warnings/notes
  1232. Revision 1.18 2000/01/12 10:31:45 peter
  1233. * fixed group() writing
  1234. Revision 1.17 2000/01/11 09:52:07 peter
  1235. * fixed placing of .sl directories
  1236. * use -b again for base-file selection
  1237. * fixed group writing for linux with smartlinking
  1238. Revision 1.16 2000/01/09 00:55:51 pierre
  1239. * GROUP of smartlink units put before the C libraries
  1240. to allow for smartlinking code that uses C code.
  1241. Revision 1.15 2000/01/07 01:14:43 peter
  1242. * updated copyright to 2000
  1243. Revision 1.14 2000/01/07 00:10:26 peter
  1244. * --base-file instead of -b as dlltool 2.9.1 doesn't understand it
  1245. * clear timestamp in pe header
  1246. Revision 1.13 1999/12/20 23:23:30 pierre
  1247. + $description $version
  1248. Revision 1.12 1999/12/08 10:40:01 pierre
  1249. + allow use of unit var in exports of DLL for win32
  1250. by using direct export writing by default instead of use of DEFFILE
  1251. that does not allow assembler labels that do not
  1252. start with an underscore.
  1253. Use -WD to force use of Deffile for Win32 DLL
  1254. Revision 1.11 1999/12/06 18:21:04 peter
  1255. * support !ENVVAR for long commandlines
  1256. * win32/go32v2 write short pathnames to link.res so c:\Program Files\ is
  1257. finally supported as installdir.
  1258. Revision 1.10 1999/11/24 11:45:36 pierre
  1259. * $STRIP was missign in DllCmd[1]
  1260. Revision 1.9 1999/11/22 22:20:43 pierre
  1261. * Def file syntax for win32 with index corrected
  1262. * direct output of .edata leads to same indexes
  1263. (index 5 leads to next export being 6 unless otherwise
  1264. specified like for enums)
  1265. Revision 1.8 1999/11/16 23:39:04 peter
  1266. * use outputexedir for link.res location
  1267. Revision 1.7 1999/11/15 15:01:56 pierre
  1268. + Pavel's changes to support reloc section in exes
  1269. Revision 1.6 1999/11/12 11:03:50 peter
  1270. * searchpaths changed to stringqueue object
  1271. Revision 1.5 1999/11/04 10:55:31 peter
  1272. * TSearchPathString for the string type of the searchpaths, which is
  1273. ansistring under FPC/Delphi
  1274. Revision 1.4 1999/11/02 15:06:58 peter
  1275. * import library fixes for win32
  1276. * alignment works again
  1277. Revision 1.3 1999/10/28 10:33:06 pierre
  1278. * Libs can be link serveral times
  1279. Revision 1.2 1999/10/22 14:42:40 peter
  1280. * reset linklibc
  1281. Revision 1.1 1999/10/21 14:29:38 peter
  1282. * redesigned linker object
  1283. + library support for linux (only procedures can be exported)
  1284. }