t_win32.pas 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405
  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. hp:=pexported_item(current_module^._exports^.first);
  431. if not assigned(hp) then
  432. exit;
  433. ordinal_max:=0;
  434. ordinal_min:=$7FFFFFFF;
  435. entries:=0;
  436. named_entries:=0;
  437. getlabel(dll_name_label);
  438. getlabel(export_address_table);
  439. getlabel(export_name_table_pointers);
  440. getlabel(export_ordinal_table);
  441. { count entries }
  442. while assigned(hp) do
  443. begin
  444. inc(entries);
  445. if (hp^.index>ordinal_max) then
  446. ordinal_max:=hp^.index;
  447. if (hp^.index>0) and (hp^.index<ordinal_min) then
  448. ordinal_min:=hp^.index;
  449. if assigned(hp^.name) then
  450. inc(named_entries);
  451. hp:=pexported_item(hp^.next);
  452. end;
  453. { no support for higher ordinal base yet !! }
  454. ordinal_base:=1;
  455. current_index:=ordinal_base;
  456. { we must also count the holes !! }
  457. entries:=ordinal_max-ordinal_base+1;
  458. exportssection^.concat(new(pai_section,init(sec_edata)));
  459. { export flags }
  460. exportssection^.concat(new(pai_const,init_32bit(0)));
  461. { date/time stamp }
  462. exportssection^.concat(new(pai_const,init_32bit(0)));
  463. { major version }
  464. exportssection^.concat(new(pai_const,init_16bit(0)));
  465. { minor version }
  466. exportssection^.concat(new(pai_const,init_16bit(0)));
  467. { pointer to dll name }
  468. exportssection^.concat(new(pai_const_symbol,init_rva(dll_name_label)));
  469. { ordinal base normally set to 1 }
  470. exportssection^.concat(new(pai_const,init_32bit(ordinal_base)));
  471. { number of entries }
  472. exportssection^.concat(new(pai_const,init_32bit(entries)));
  473. { number of named entries }
  474. exportssection^.concat(new(pai_const,init_32bit(named_entries)));
  475. { address of export address table }
  476. exportssection^.concat(new(pai_const_symbol,init_rva(export_address_table)));
  477. { address of name pointer pointers }
  478. exportssection^.concat(new(pai_const_symbol,init_rva(export_name_table_pointers)));
  479. { address of ordinal number pointers }
  480. exportssection^.concat(new(pai_const_symbol,init_rva(export_ordinal_table)));
  481. { the name }
  482. exportssection^.concat(new(pai_label,init(dll_name_label)));
  483. if st='' then
  484. exportssection^.concat(new(pai_string,init(current_module^.modulename^+target_os.sharedlibext+#0)))
  485. else
  486. exportssection^.concat(new(pai_string,init(st+target_os.sharedlibext+#0)));
  487. { export address table }
  488. address_table:=new(paasmoutput,init);
  489. address_table^.concat(new(pai_align,init_op(4,0)));
  490. address_table^.concat(new(pai_label,init(export_address_table)));
  491. name_table_pointers:=new(paasmoutput,init);
  492. name_table_pointers^.concat(new(pai_align,init_op(4,0)));
  493. name_table_pointers^.concat(new(pai_label,init(export_name_table_pointers)));
  494. ordinal_table:=new(paasmoutput,init);
  495. ordinal_table^.concat(new(pai_align,init_op(4,0)));
  496. ordinal_table^.concat(new(pai_label,init(export_ordinal_table)));
  497. name_table:=new(paasmoutput,init);
  498. name_table^.concat(new(pai_align,init_op(4,0)));
  499. { write each address }
  500. hp:=pexported_item(current_module^._exports^.first);
  501. while assigned(hp) do
  502. begin
  503. if (hp^.options and eo_name)<>0 then
  504. begin
  505. getlabel(name_label);
  506. name_table_pointers^.concat(new(pai_const_symbol,init_rva(name_label)));
  507. ordinal_table^.concat(new(pai_const,init_16bit(hp^.index-ordinal_base)));
  508. name_table^.concat(new(pai_align,init_op(2,0)));
  509. name_table^.concat(new(pai_label,init(name_label)));
  510. name_table^.concat(new(pai_string,init(hp^.name^+#0)));
  511. end;
  512. hp:=pexported_item(hp^.next);
  513. end;
  514. { order in increasing ordinal values }
  515. { into tempexport list }
  516. tempexport:=new(plinkedlist,init);
  517. hp:=pexported_item(current_module^._exports^.first);
  518. while assigned(hp) do
  519. begin
  520. current_module^._exports^.remove(hp);
  521. hp2:=pexported_item(tempexport^.first);
  522. while assigned(hp2) and (hp^.index>hp2^.index) do
  523. begin
  524. hp2:=pexported_item(hp2^.next);
  525. end;
  526. if hp2=pexported_item(tempexport^.first) then
  527. tempexport^.insert(hp)
  528. else
  529. begin
  530. if assigned(hp2) then
  531. begin
  532. hp^.next:=hp2;
  533. hp^.previous:=hp2^.previous;
  534. hp2^.previous:=hp;
  535. if assigned(hp^.previous) then
  536. hp^.previous^.next:=hp;
  537. end
  538. else
  539. tempexport^.concat(hp);
  540. end;
  541. hp:=pexported_item(current_module^._exports^.first);;
  542. end;
  543. { write the export adress table }
  544. current_index:=ordinal_base;
  545. hp:=pexported_item(tempexport^.first);
  546. while assigned(hp) do
  547. begin
  548. { fill missing values }
  549. while current_index<hp^.index do
  550. begin
  551. address_table^.concat(new(pai_const,init_32bit(0)));
  552. inc(current_index);
  553. end;
  554. address_table^.concat(new(pai_const_symbol,initname_rva(hp^.sym^.mangledname)));
  555. inc(current_index);
  556. hp:=pexported_item(hp^.next);
  557. end;
  558. exportssection^.concatlist(address_table);
  559. exportssection^.concatlist(name_table_pointers);
  560. exportssection^.concatlist(ordinal_table);
  561. exportssection^.concatlist(name_table);
  562. dispose(address_table,done);
  563. dispose(name_table_pointers,done);
  564. dispose(ordinal_table,done);
  565. dispose(name_table,done);
  566. dispose(tempexport,done);
  567. end;
  568. {****************************************************************************
  569. TLINKERWIN32
  570. ****************************************************************************}
  571. Constructor TLinkerWin32.Init;
  572. begin
  573. Inherited Init;
  574. { allow duplicated libs (PM) }
  575. SharedLibFiles.doubles:=true;
  576. StaticLibFiles.doubles:=true;
  577. If not ForceDeffileForExport then
  578. UseDeffileForExport:=false;
  579. end;
  580. Procedure TLinkerWin32.SetDefaultInfo;
  581. begin
  582. with Info do
  583. begin
  584. ExeCmd[1]:='ldw $OPT $STRIP $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
  585. DllCmd[1]:='ldw $OPT $STRIP --dll $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
  586. if RelocSection or UseDeffileForExport then
  587. begin
  588. { ExeCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF';
  589. use short forms to avoid 128 char limitation problem }
  590. ExeCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
  591. ExeCmd[3]:='ldw $OPT $STRIP $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
  592. { DllCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF'; }
  593. DllCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
  594. DllCmd[3]:='ldw $OPT $STRIP --dll $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
  595. end;
  596. end;
  597. end;
  598. {$ifndef PAVEL_LINKLIB}
  599. Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
  600. Var
  601. linkres : TLinkRes;
  602. i : longint;
  603. {$IFDEF NEWST}
  604. HPath : PStringItem;
  605. {$ELSE}
  606. HPath : PStringQueueItem;
  607. {$ENDIF NEWST}
  608. s,s2 : string;
  609. found,linklibc : boolean;
  610. begin
  611. WriteResponseFile:=False;
  612. { Open link.res file }
  613. LinkRes.Init(outputexedir+Info.ResName);
  614. { Write path to search libraries }
  615. HPath:=current_module^.locallibrarysearchpath.First;
  616. while assigned(HPath) do
  617. begin
  618. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath^.Data^)+')');
  619. HPath:=HPath^.Next;
  620. end;
  621. HPath:=LibrarySearchPath.First;
  622. while assigned(HPath) do
  623. begin
  624. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath^.Data^)+')');
  625. HPath:=HPath^.Next;
  626. end;
  627. { add objectfiles, start with prt0 always }
  628. LinkRes.Add('INPUT(');
  629. if isdll then
  630. LinkRes.AddFileName(GetShortName(FindObjectFile('wdllprt0','')))
  631. else
  632. LinkRes.AddFileName(GetShortName(FindObjectFile('wprt0','')));
  633. while not ObjectFiles.Empty do
  634. begin
  635. s:=ObjectFiles.Get;
  636. if s<>'' then
  637. LinkRes.AddFileName(GetShortName(s));
  638. end;
  639. LinkRes.Add(')');
  640. { Write staticlibraries }
  641. if not StaticLibFiles.Empty then
  642. begin
  643. LinkRes.Add('GROUP(');
  644. While not StaticLibFiles.Empty do
  645. begin
  646. S:=StaticLibFiles.Get;
  647. LinkRes.AddFileName(GetShortName(s));
  648. end;
  649. LinkRes.Add(')');
  650. end;
  651. { Write sharedlibraries like -l<lib>, also add the needed dynamic linker
  652. here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
  653. if not SharedLibFiles.Empty then
  654. begin
  655. linklibc:=false;
  656. LinkRes.Add('INPUT(');
  657. While not SharedLibFiles.Empty do
  658. begin
  659. S:=SharedLibFiles.Get;
  660. if pos('.',s)=0 then
  661. { we never directly link a DLL
  662. its allways through an import library PM }
  663. { libraries created by C compilers have .a extensions }
  664. s2:=s+'.a'{ target_os.sharedlibext }
  665. else
  666. s2:=s;
  667. s2:=FindLibraryFile(s2,'',found);
  668. if found then
  669. begin
  670. LinkRes.Add(s2);
  671. continue;
  672. end;
  673. if pos(target_os.libprefix,s)=1 then
  674. s:=copy(s,length(target_os.libprefix)+1,255);
  675. if s<>'c' then
  676. begin
  677. i:=Pos(target_os.sharedlibext,S);
  678. if i>0 then
  679. Delete(S,i,255);
  680. LinkRes.Add('-l'+s);
  681. end
  682. else
  683. begin
  684. LinkRes.Add('-l'+s);
  685. linklibc:=true;
  686. end;
  687. end;
  688. { be sure that libc is the last lib }
  689. if linklibc then
  690. LinkRes.Add('-lc');
  691. LinkRes.Add(')');
  692. end;
  693. { Write and Close response }
  694. linkres.writetodisk;
  695. linkres.done;
  696. WriteResponseFile:=True;
  697. end;
  698. {$else PAVEL_LINKLIB}
  699. Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
  700. Var
  701. linkres : TLinkRes;
  702. HPath : {$ifdef NEWST} PStringItem {$else} PStringQueueItem {$endif};
  703. s,s2 : string;
  704. success : boolean;
  705. function ExpandName(const s:string):string;
  706. var
  707. sysdir:string;
  708. procedure GetSysDir;
  709. begin
  710. sysdir:=GetEnv('windir');
  711. if sysdir<>''then
  712. begin
  713. if not(sysdir[length(sysdir)]in['\','/'])then
  714. sysdir:=sysdir+dirsep;
  715. end;
  716. end;
  717. function IsFile(d:string;var PathToDll:string):longbool;
  718. var
  719. f:file;
  720. attr:word;
  721. begin
  722. PathToDll:='';
  723. if d<>''then
  724. if d[length(d)]<>dirsep then
  725. d:=d+dirsep;
  726. d:=d+s;
  727. assign(f,d);
  728. GetFattr(f,Attr);
  729. if DOSerror<>0 then
  730. IsFile:=false
  731. else
  732. begin
  733. if(attr and directory)=0 then
  734. begin
  735. IsFile:=true;
  736. PathToDll:=GetShortName(d);
  737. end
  738. else
  739. IsFile:=false;
  740. end;
  741. end;
  742. var
  743. PathToDll:string;
  744. begin
  745. if not isFile('',PathToDll)then
  746. begin
  747. HPath:=LibrarySearchPath.First;
  748. while assigned(HPath) do
  749. begin
  750. if isFile(GetShortName(HPath^.Data^),PathToDll)then
  751. break;
  752. HPath:=HPath^.Next;
  753. end;
  754. if PathToDll='' then
  755. begin
  756. GetSysDir;
  757. if not isFile(sysdir,PathToDll)then
  758. if not isFile(sysdir+'system32',PathToDll)then
  759. if not isFile(sysdir+'system',PathToDll)then
  760. begin
  761. message1(exec_w_libfile_not_found,S2);
  762. PathToDll:=S2;
  763. end;
  764. end;
  765. end;
  766. ExpandName:=PathToDll;
  767. end;
  768. function DotPos(const s:string):longint;
  769. var
  770. i:longint;
  771. begin
  772. DotPos:=0;
  773. for i:=length(s)downto 1 do
  774. begin
  775. if s[i]in['/','\',':']then
  776. exit
  777. else if s[i]='.'then
  778. begin
  779. DotPos:=i;
  780. exit;
  781. end;
  782. end;
  783. end;
  784. procedure strip(var s:string);
  785. var
  786. d:dirstr;
  787. n:namestr;
  788. e:extstr;
  789. begin
  790. fsplit(s,d,n,e);
  791. s:=n;
  792. end;
  793. function do_makedef(const s:string):longbool;
  794. begin
  795. if cs_link_extern in aktglobalswitches then
  796. do_makedef:=DoExec(FindUtil('fpimpdef'),'-o deffile.$$$ -i '+s,false,false)
  797. else
  798. do_makedef:=makedef(s,'deffile.$$$');
  799. end;
  800. begin
  801. WriteResponseFile:=False;
  802. While not SharedLibFiles.Empty do
  803. begin
  804. S:=SharedLibFiles.Get;
  805. if DotPos(s)=0 then
  806. s2:=s+target_os.sharedlibext
  807. else
  808. s2:=s;
  809. strip(s);
  810. if not do_makedef(ExpandName(s2))then
  811. begin
  812. Message(exec_w_error_while_linking);
  813. aktglobalswitches:=aktglobalswitches+[cs_link_extern];
  814. end
  815. else
  816. begin
  817. s:=target_os.libprefix+s+target_os.staticlibext;
  818. success:=DoExec(FindUtil('dlltool'),'-l '+s+' -D '+s2+' -d deffile.$$$',false,false);
  819. ObjectFiles.insert(s);
  820. if not success then
  821. break;
  822. end;
  823. end;
  824. { Open link.res file }
  825. LinkRes.Init(outputexedir+Info.ResName);
  826. { Write path to search libraries }
  827. HPath:=current_module^.locallibrarysearchpath.First;
  828. while assigned(HPath) do
  829. begin
  830. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath^.Data^)+')');
  831. HPath:=HPath^.Next;
  832. end;
  833. HPath:=LibrarySearchPath.First;
  834. while assigned(HPath) do
  835. begin
  836. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath^.Data^)+')');
  837. HPath:=HPath^.Next;
  838. end;
  839. { add objectfiles, start with prt0 always }
  840. LinkRes.Add('INPUT(');
  841. if isdll then
  842. LinkRes.AddFileName(GetShortName(FindObjectFile('wdllprt0')))
  843. else
  844. LinkRes.AddFileName(GetShortName(FindObjectFile('wprt0')));
  845. while not ObjectFiles.Empty do
  846. begin
  847. s:=ObjectFiles.Get;
  848. if s<>'' then
  849. LinkRes.AddFileName(GetShortName(s));
  850. end;
  851. LinkRes.Add(')');
  852. { Write staticlibraries }
  853. if not StaticLibFiles.Empty then
  854. begin
  855. LinkRes.Add('GROUP(');
  856. While not StaticLibFiles.Empty do
  857. begin
  858. S:=StaticLibFiles.Get;
  859. LinkRes.AddFileName(GetShortName(s));
  860. end;
  861. LinkRes.Add(')');
  862. end;
  863. { Write and Close response }
  864. linkres.writetodisk;
  865. linkres.done;
  866. WriteResponseFile:=True;
  867. end;
  868. {$endif PAVEL_LINKLIB}
  869. function TLinkerWin32.MakeExecutable:boolean;
  870. var
  871. binstr,
  872. cmdstr : string;
  873. found,
  874. success : boolean;
  875. i : longint;
  876. AsBinStr : string[80];
  877. StripStr,
  878. RelocStr,
  879. AppTypeStr,
  880. ImageBaseStr : string[40];
  881. begin
  882. if not(cs_link_extern in aktglobalswitches) then
  883. Message1(exec_i_linking,current_module^.exefilename^);
  884. { Create some replacements }
  885. RelocStr:='';
  886. AppTypeStr:='';
  887. ImageBaseStr:='';
  888. StripStr:='';
  889. AsBinStr:=FindExe('asw',found);
  890. if RelocSection then
  891. { Using short form to avoid problems with 128 char limitation under Dos. }
  892. RelocStr:='-b base.$$$';
  893. if apptype=at_gui then
  894. AppTypeStr:='--subsystem windows';
  895. if assigned(DLLImageBase) then
  896. ImageBaseStr:='--image-base=0x'+DLLImageBase^;
  897. if (cs_link_strip in aktglobalswitches) then
  898. StripStr:='-s';
  899. { Write used files and libraries }
  900. WriteResponseFile(false);
  901. { Call linker }
  902. success:=false;
  903. for i:=1 to 3 do
  904. begin
  905. SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
  906. if binstr<>'' then
  907. begin
  908. Replace(cmdstr,'$EXE',current_module^.exefilename^);
  909. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  910. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  911. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  912. Replace(cmdstr,'$ASBIN',AsbinStr);
  913. Replace(cmdstr,'$RELOC',RelocStr);
  914. Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
  915. Replace(cmdstr,'$STRIP',StripStr);
  916. if not DefFile.Empty {and UseDefFileForExport} then
  917. begin
  918. DefFile.WriteFile;
  919. Replace(cmdstr,'$DEF','-d '+deffile.fname);
  920. end
  921. else
  922. Replace(cmdstr,'$DEF','');
  923. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
  924. if not success then
  925. break;
  926. end;
  927. end;
  928. { Post process }
  929. if success then
  930. success:=PostProcessExecutable(current_module^.exefilename^,false);
  931. { Remove ReponseFile }
  932. if (success) and not(cs_link_extern in aktglobalswitches) then
  933. begin
  934. RemoveFile(outputexedir+Info.ResName);
  935. RemoveFile('base.$$$');
  936. RemoveFile('exp.$$$');
  937. RemoveFile('deffile.$$$');
  938. end;
  939. MakeExecutable:=success; { otherwise a recursive call to link method }
  940. end;
  941. Function TLinkerWin32.MakeSharedLibrary:boolean;
  942. var
  943. binstr,
  944. cmdstr : string;
  945. found,
  946. success : boolean;
  947. i : longint;
  948. AsBinStr : string[80];
  949. StripStr,
  950. RelocStr,
  951. AppTypeStr,
  952. ImageBaseStr : string[40];
  953. begin
  954. MakeSharedLibrary:=false;
  955. if not(cs_link_extern in aktglobalswitches) then
  956. Message1(exec_i_linking,current_module^.sharedlibfilename^);
  957. { Create some replacements }
  958. RelocStr:='';
  959. AppTypeStr:='';
  960. ImageBaseStr:='';
  961. StripStr:='';
  962. AsBinStr:=FindExe('asw',found);
  963. if RelocSection then
  964. { Using short form to avoid problems with 128 char limitation under Dos. }
  965. RelocStr:='-b base.$$$';
  966. if apptype=at_gui then
  967. AppTypeStr:='--subsystem windows';
  968. if assigned(DLLImageBase) then
  969. ImageBaseStr:='--image-base=0x'+DLLImageBase^;
  970. if (cs_link_strip in aktglobalswitches) then
  971. StripStr:='-s';
  972. { Write used files and libraries }
  973. WriteResponseFile(true);
  974. { Call linker }
  975. success:=false;
  976. for i:=1 to 3 do
  977. begin
  978. SplitBinCmd(Info.DllCmd[i],binstr,cmdstr);
  979. if binstr<>'' then
  980. begin
  981. Replace(cmdstr,'$EXE',current_module^.sharedlibfilename^);
  982. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  983. Replace(cmdstr,'$RES',outputexedir+Info.ResName);
  984. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  985. Replace(cmdstr,'$ASBIN',AsbinStr);
  986. Replace(cmdstr,'$RELOC',RelocStr);
  987. Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
  988. Replace(cmdstr,'$STRIP',StripStr);
  989. if not DefFile.Empty {and UseDefFileForExport} then
  990. begin
  991. DefFile.WriteFile;
  992. Replace(cmdstr,'$DEF','-d '+deffile.fname);
  993. end
  994. else
  995. Replace(cmdstr,'$DEF','');
  996. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
  997. if not success then
  998. break;
  999. end;
  1000. end;
  1001. { Post process }
  1002. if success then
  1003. success:=PostProcessExecutable(current_module^.sharedlibfilename^,true);
  1004. { Remove ReponseFile }
  1005. if (success) and not(cs_link_extern in aktglobalswitches) then
  1006. begin
  1007. RemoveFile(outputexedir+Info.ResName);
  1008. RemoveFile('base.$$$');
  1009. RemoveFile('exp.$$$');
  1010. end;
  1011. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  1012. end;
  1013. function tlinkerwin32.postprocessexecutable(const fn : string;isdll:boolean):boolean;
  1014. type
  1015. tdosheader = packed record
  1016. e_magic : word;
  1017. e_cblp : word;
  1018. e_cp : word;
  1019. e_crlc : word;
  1020. e_cparhdr : word;
  1021. e_minalloc : word;
  1022. e_maxalloc : word;
  1023. e_ss : word;
  1024. e_sp : word;
  1025. e_csum : word;
  1026. e_ip : word;
  1027. e_cs : word;
  1028. e_lfarlc : word;
  1029. e_ovno : word;
  1030. e_res : array[0..3] of word;
  1031. e_oemid : word;
  1032. e_oeminfo : word;
  1033. e_res2 : array[0..9] of word;
  1034. e_lfanew : longint;
  1035. end;
  1036. tpeheader = packed record
  1037. PEMagic : array[0..3] of char;
  1038. Machine : word;
  1039. NumberOfSections : word;
  1040. TimeDateStamp : longint;
  1041. PointerToSymbolTable : longint;
  1042. NumberOfSymbols : longint;
  1043. SizeOfOptionalHeader : word;
  1044. Characteristics : word;
  1045. Magic : word;
  1046. MajorLinkerVersion : byte;
  1047. MinorLinkerVersion : byte;
  1048. SizeOfCode : longint;
  1049. SizeOfInitializedData : longint;
  1050. SizeOfUninitializedData : longint;
  1051. AddressOfEntryPoint : longint;
  1052. BaseOfCode : longint;
  1053. BaseOfData : longint;
  1054. ImageBase : longint;
  1055. SectionAlignment : longint;
  1056. FileAlignment : longint;
  1057. MajorOperatingSystemVersion : word;
  1058. MinorOperatingSystemVersion : word;
  1059. MajorImageVersion : word;
  1060. MinorImageVersion : word;
  1061. MajorSubsystemVersion : word;
  1062. MinorSubsystemVersion : word;
  1063. Reserved1 : longint;
  1064. SizeOfImage : longint;
  1065. SizeOfHeaders : longint;
  1066. CheckSum : longint;
  1067. Subsystem : word;
  1068. DllCharacteristics : word;
  1069. SizeOfStackReserve : longint;
  1070. SizeOfStackCommit : longint;
  1071. SizeOfHeapReserve : longint;
  1072. SizeOfHeapCommit : longint;
  1073. LoaderFlags : longint;
  1074. NumberOfRvaAndSizes : longint;
  1075. DataDirectory : array[1..$80] of byte;
  1076. end;
  1077. tcoffsechdr=packed record
  1078. name : array[0..7] of char;
  1079. vsize : longint;
  1080. rvaofs : longint;
  1081. datalen : longint;
  1082. datapos : longint;
  1083. relocpos : longint;
  1084. lineno1 : longint;
  1085. nrelocs : word;
  1086. lineno2 : word;
  1087. flags : longint;
  1088. end;
  1089. psecfill=^tsecfill;
  1090. tsecfill=record
  1091. fillpos,
  1092. fillsize : longint;
  1093. next : psecfill;
  1094. end;
  1095. var
  1096. f : file;
  1097. cmdstr : string;
  1098. dosheader : tdosheader;
  1099. peheader : tpeheader;
  1100. firstsecpos,
  1101. maxfillsize,
  1102. l,peheaderpos : longint;
  1103. coffsec : tcoffsechdr;
  1104. secroot,hsecroot : psecfill;
  1105. zerobuf : pointer;
  1106. begin
  1107. postprocessexecutable:=false;
  1108. { when -s is used or it's a dll then quit }
  1109. if (cs_link_extern in aktglobalswitches) then
  1110. begin
  1111. if apptype=at_gui then
  1112. cmdstr:='--subsystem gui'
  1113. else if apptype=at_cui then
  1114. cmdstr:='--subsystem console';
  1115. if dllversion<>'' then
  1116. cmdstr:=cmdstr+' --version '+dllversion;
  1117. cmdstr:=cmdstr+' --input '+fn;
  1118. cmdstr:=cmdstr+' --stack '+tostr(stacksize);
  1119. DoExec(FindUtil('postw32'),cmdstr,false,false);
  1120. postprocessexecutable:=true;
  1121. exit;
  1122. end;
  1123. { open file }
  1124. assign(f,fn);
  1125. {$I-}
  1126. reset(f,1);
  1127. if ioresult<>0 then
  1128. Message1(execinfo_f_cant_open_executable,fn);
  1129. { read headers }
  1130. blockread(f,dosheader,sizeof(tdosheader));
  1131. peheaderpos:=dosheader.e_lfanew;
  1132. seek(f,peheaderpos);
  1133. blockread(f,peheader,sizeof(tpeheader));
  1134. { write info }
  1135. Message1(execinfo_x_codesize,tostr(peheader.SizeOfCode));
  1136. Message1(execinfo_x_initdatasize,tostr(peheader.SizeOfInitializedData));
  1137. Message1(execinfo_x_uninitdatasize,tostr(peheader.SizeOfUninitializedData));
  1138. { change stack size (PM) }
  1139. { I am not sure that the default value is adequate !! }
  1140. peheader.SizeOfStackReserve:=stacksize;
  1141. { change the header }
  1142. { sub system }
  1143. { gui=2 }
  1144. { cui=3 }
  1145. if apptype=at_gui then
  1146. peheader.Subsystem:=2
  1147. else if apptype=at_cui then
  1148. peheader.Subsystem:=3;
  1149. if dllversion<>'' then
  1150. begin
  1151. peheader.MajorImageVersion:=dllmajor;
  1152. peheader.MinorImageVersion:=dllminor;
  1153. end;
  1154. { reset timestamp }
  1155. peheader.TimeDateStamp:=0;
  1156. { write header back }
  1157. seek(f,peheaderpos);
  1158. blockwrite(f,peheader,sizeof(tpeheader));
  1159. if ioresult<>0 then
  1160. Message1(execinfo_f_cant_process_executable,fn);
  1161. seek(f,peheaderpos);
  1162. blockread(f,peheader,sizeof(tpeheader));
  1163. { write the value after the change }
  1164. Message1(execinfo_x_stackreserve,tostr(peheader.SizeOfStackReserve));
  1165. Message1(execinfo_x_stackcommit,tostr(peheader.SizeOfStackCommit));
  1166. { read section info }
  1167. maxfillsize:=0;
  1168. firstsecpos:=0;
  1169. secroot:=nil;
  1170. for l:=1 to peheader.NumberOfSections do
  1171. begin
  1172. blockread(f,coffsec,sizeof(tcoffsechdr));
  1173. if coffsec.datapos>0 then
  1174. begin
  1175. if secroot=nil then
  1176. firstsecpos:=coffsec.datapos;
  1177. new(hsecroot);
  1178. hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
  1179. hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
  1180. hsecroot^.next:=secroot;
  1181. secroot:=hsecroot;
  1182. if secroot^.fillsize>maxfillsize then
  1183. maxfillsize:=secroot^.fillsize;
  1184. end;
  1185. end;
  1186. if firstsecpos>0 then
  1187. begin
  1188. l:=firstsecpos-filepos(f);
  1189. if l>maxfillsize then
  1190. maxfillsize:=l;
  1191. end
  1192. else
  1193. l:=0;
  1194. { get zero buffer }
  1195. getmem(zerobuf,maxfillsize);
  1196. fillchar(zerobuf^,maxfillsize,0);
  1197. { zero from sectioninfo until first section }
  1198. blockwrite(f,zerobuf^,l);
  1199. { zero section alignments }
  1200. while assigned(secroot) do
  1201. begin
  1202. seek(f,secroot^.fillpos);
  1203. blockwrite(f,zerobuf^,secroot^.fillsize);
  1204. hsecroot:=secroot;
  1205. secroot:=secroot^.next;
  1206. dispose(hsecroot);
  1207. end;
  1208. freemem(zerobuf,maxfillsize);
  1209. close(f);
  1210. {$I+}
  1211. if ioresult<>0 then;
  1212. postprocessexecutable:=true;
  1213. end;
  1214. end.
  1215. {
  1216. $Log$
  1217. Revision 1.25 2000-07-08 20:43:38 peter
  1218. * findobjectfile gets extra arg with directory where the unit is found
  1219. and the .o should be looked first
  1220. Revision 1.24 2000/06/20 12:44:30 pierre
  1221. * do not create an empty export section
  1222. Revision 1.23 2000/05/23 20:18:25 pierre
  1223. + pavel's code integrated, but onyl inside
  1224. ifdef pavel_linklib !
  1225. Revision 1.22 2000/04/14 11:16:10 pierre
  1226. * partial linklib change
  1227. I could not use Pavel's code because it broke the current way
  1228. linklib is used, which is messy :(
  1229. + add postw32 call if external linking on win32
  1230. Revision 1.21 2000/03/10 09:14:40 pierre
  1231. * dlltool is also needed if we use DefFile
  1232. Revision 1.20 2000/02/28 17:23:57 daniel
  1233. * Current work of symtable integration committed. The symtable can be
  1234. activated by defining 'newst', but doesn't compile yet. Changes in type
  1235. checking and oop are completed. What is left is to write a new
  1236. symtablestack and adapt the parser to use it.
  1237. Revision 1.19 2000/02/24 18:41:39 peter
  1238. * removed warnings/notes
  1239. Revision 1.18 2000/01/12 10:31:45 peter
  1240. * fixed group() writing
  1241. Revision 1.17 2000/01/11 09:52:07 peter
  1242. * fixed placing of .sl directories
  1243. * use -b again for base-file selection
  1244. * fixed group writing for linux with smartlinking
  1245. Revision 1.16 2000/01/09 00:55:51 pierre
  1246. * GROUP of smartlink units put before the C libraries
  1247. to allow for smartlinking code that uses C code.
  1248. Revision 1.15 2000/01/07 01:14:43 peter
  1249. * updated copyright to 2000
  1250. Revision 1.14 2000/01/07 00:10:26 peter
  1251. * --base-file instead of -b as dlltool 2.9.1 doesn't understand it
  1252. * clear timestamp in pe header
  1253. Revision 1.13 1999/12/20 23:23:30 pierre
  1254. + $description $version
  1255. Revision 1.12 1999/12/08 10:40:01 pierre
  1256. + allow use of unit var in exports of DLL for win32
  1257. by using direct export writing by default instead of use of DEFFILE
  1258. that does not allow assembler labels that do not
  1259. start with an underscore.
  1260. Use -WD to force use of Deffile for Win32 DLL
  1261. Revision 1.11 1999/12/06 18:21:04 peter
  1262. * support !ENVVAR for long commandlines
  1263. * win32/go32v2 write short pathnames to link.res so c:\Program Files\ is
  1264. finally supported as installdir.
  1265. Revision 1.10 1999/11/24 11:45:36 pierre
  1266. * $STRIP was missign in DllCmd[1]
  1267. Revision 1.9 1999/11/22 22:20:43 pierre
  1268. * Def file syntax for win32 with index corrected
  1269. * direct output of .edata leads to same indexes
  1270. (index 5 leads to next export being 6 unless otherwise
  1271. specified like for enums)
  1272. Revision 1.8 1999/11/16 23:39:04 peter
  1273. * use outputexedir for link.res location
  1274. Revision 1.7 1999/11/15 15:01:56 pierre
  1275. + Pavel's changes to support reloc section in exes
  1276. Revision 1.6 1999/11/12 11:03:50 peter
  1277. * searchpaths changed to stringqueue object
  1278. Revision 1.5 1999/11/04 10:55:31 peter
  1279. * TSearchPathString for the string type of the searchpaths, which is
  1280. ansistring under FPC/Delphi
  1281. Revision 1.4 1999/11/02 15:06:58 peter
  1282. * import library fixes for win32
  1283. * alignment works again
  1284. Revision 1.3 1999/10/28 10:33:06 pierre
  1285. * Libs can be link serveral times
  1286. Revision 1.2 1999/10/22 14:42:40 peter
  1287. * reset linklibc
  1288. Revision 1.1 1999/10/21 14:29:38 peter
  1289. * redesigned linker object
  1290. + library support for linux (only procedures can be exported)
  1291. }