t_win32.pas 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. {$ifdef Delphi}
  24. dmisc,
  25. {$else Delphi}
  26. dos,
  27. {$endif Delphi}
  28. cutils,cclasses,
  29. aasmbase,aasmtai,aasmcpu,fmodule,globtype,globals,systems,verbose,
  30. symconst,symsym,
  31. script,gendef,
  32. cpubase,
  33. {$ifdef GDB}
  34. gdb,
  35. {$endif}
  36. import,export,link,rgobj,i_win32;
  37. const
  38. MAX_DEFAULT_EXTENSIONS = 3;
  39. type
  40. tStr4=array[1..MAX_DEFAULT_EXTENSIONS]of string[4];
  41. pStr4=^tStr4;
  42. timportlibwin32=class(timportlib)
  43. procedure GetDefExt(var N:longint;var P:pStr4);virtual;
  44. procedure preparelib(const s:string);override;
  45. procedure importprocedure(const func,module:string;index:longint;const name:string);override;
  46. procedure importvariable(const varname,module:string;const name:string);override;
  47. procedure generatelib;override;
  48. procedure generatenasmlib;virtual;
  49. procedure generatesmartlib;override;
  50. end;
  51. texportlibwin32=class(texportlib)
  52. st : string;
  53. last_index : longint;
  54. procedure preparelib(const s:string);override;
  55. procedure exportprocedure(hp : texported_item);override;
  56. procedure exportvar(hp : texported_item);override;
  57. procedure generatelib;override;
  58. procedure generatenasmlib;virtual;
  59. end;
  60. tlinkerwin32=class(texternallinker)
  61. private
  62. Function WriteResponseFile(isdll:boolean) : Boolean;
  63. Function PostProcessExecutable(const fn:string;isdll:boolean) : Boolean;
  64. public
  65. Constructor Create;override;
  66. Procedure SetDefaultInfo;override;
  67. function MakeExecutable:boolean;override;
  68. function MakeSharedLibrary:boolean;override;
  69. end;
  70. tDLLScannerWin32=class(tDLLScanner)
  71. private
  72. cstring : array[0..127]of char;
  73. function DOSstubOK(var x:cardinal):boolean;
  74. function FindDLL(const s:string;var founddll:string):boolean;
  75. function ExtractDllName(Const Name : string) : string;
  76. public
  77. procedure GetDefExt(var N:longint;var P:pStr4);virtual;
  78. function isSuitableFileType(x:cardinal):longbool;override;
  79. function GetEdata(HeaderEntry:cardinal):longbool;override;
  80. function Scan(const binname:string):longbool;override;
  81. end;
  82. implementation
  83. function DllName(Const Name : string;NdefExt:longint;DefExt:pStr4) : string;
  84. var n : string;
  85. i:longint;
  86. begin
  87. n:=Upper(SplitExtension(Name));
  88. for i:=1 to NdefExt do
  89. if n=DefExt^[i]then
  90. begin
  91. DllName:=Name;
  92. exit;
  93. end
  94. else
  95. DllName:=Name+target_info.sharedlibext;
  96. end;
  97. const
  98. DefaultDLLExtensions:array[1..MAX_DEFAULT_EXTENSIONS]of string[4]=('.DLL','.DRV','.EXE');
  99. {*****************************************************************************
  100. TIMPORTLIBWIN32
  101. *****************************************************************************}
  102. procedure timportlibwin32.GetDefExt(var N:longint;var P:pStr4);
  103. begin
  104. N:=sizeof(DefaultDLLExtensions)div sizeof(DefaultDLLExtensions[1]);
  105. pointer(P):=@DefaultDLLExtensions;
  106. end;
  107. procedure timportlibwin32.preparelib(const s : string);
  108. begin
  109. if not(assigned(importssection)) then
  110. importssection:=TAAsmoutput.create;
  111. end;
  112. procedure timportlibwin32.importprocedure(const func,module : string;index : longint;const name : string);
  113. var
  114. hp1 : timportlist;
  115. hp2 : timported_item;
  116. hs : string;
  117. PP:pStr4;NN:longint;
  118. begin
  119. { force the current mangledname }
  120. aktprocdef.has_mangledname:=true;
  121. { append extension if required }
  122. GetDefExt(NN,PP);
  123. hs:=DllName(module,NN,PP);
  124. { search for the module }
  125. hp1:=timportlist(current_module.imports.first);
  126. while assigned(hp1) do
  127. begin
  128. if hs=hp1.dllname^ then
  129. break;
  130. hp1:=timportlist(hp1.next);
  131. end;
  132. { generate a new item ? }
  133. if not(assigned(hp1)) then
  134. begin
  135. hp1:=timportlist.create(hs);
  136. current_module.imports.concat(hp1);
  137. end;
  138. { search for reuse of old import item }
  139. hp2:=timported_item(hp1.imported_items.first);
  140. while assigned(hp2) do
  141. begin
  142. if hp2.func^=func then
  143. break;
  144. hp2:=timported_item(hp2.next);
  145. end;
  146. if not assigned(hp2) then
  147. begin
  148. hp2:=timported_item.create(func,name,index);
  149. hp1.imported_items.concat(hp2);
  150. end;
  151. end;
  152. procedure timportlibwin32.importvariable(const varname,module:string;const name:string);
  153. var
  154. hp1 : timportlist;
  155. hp2 : timported_item;
  156. hs : string;
  157. NN:longint;PP:pStr4;
  158. begin
  159. GetDefExt(NN,PP);
  160. hs:=DllName(module,NN,PP);
  161. { search for the module }
  162. hp1:=timportlist(current_module.imports.first);
  163. while assigned(hp1) do
  164. begin
  165. if hs=hp1.dllname^ then
  166. break;
  167. hp1:=timportlist(hp1.next);
  168. end;
  169. { generate a new item ? }
  170. if not(assigned(hp1)) then
  171. begin
  172. hp1:=timportlist.create(hs);
  173. current_module.imports.concat(hp1);
  174. end;
  175. hp2:=timported_item.create_var(varname,name);
  176. hp1.imported_items.concat(hp2);
  177. end;
  178. procedure timportlibwin32.generatenasmlib;
  179. var
  180. hp1 : timportlist;
  181. hp2 : timported_item;
  182. p : pchar;
  183. begin
  184. importssection.concat(tai_section.create(sec_code));
  185. hp1:=timportlist(current_module.imports.first);
  186. while assigned(hp1) do
  187. begin
  188. hp2:=timported_item(hp1.imported_items.first);
  189. while assigned(hp2) do
  190. begin
  191. if (aktoutputformat=as_i386_tasm) or
  192. (aktoutputformat=as_i386_masm) then
  193. p:=strpnew(#9+'EXTRN '+hp2.func^)
  194. else
  195. p:=strpnew(#9+'EXTERN '+hp2.func^);
  196. importssection.concat(tai_direct.create(p));
  197. p:=strpnew(#9+'import '+hp2.func^+' '+hp1.dllname^+' '+hp2.name^);
  198. importssection.concat(tai_direct.create(p));
  199. hp2:=timported_item(hp2.next);
  200. end;
  201. hp1:=timportlist(hp1.next);
  202. end;
  203. end;
  204. const
  205. MainAsmFormats=[as_i386_asw,as_i386_pecoff,as_i386_pecoffwdosx];
  206. procedure timportlibwin32.generatesmartlib;
  207. var
  208. hp1 : timportlist;
  209. {$ifdef GDB}
  210. importname : string;
  211. suffix : integer;
  212. {$endif GDB}
  213. hp2 : timported_item;
  214. lhead,lname,lcode,
  215. lidata4,lidata5 : tasmlabel;
  216. href : treference;
  217. begin
  218. if not(aktoutputformat in MainAsmFormats)then
  219. begin
  220. generatenasmlib;
  221. exit;
  222. end;
  223. hp1:=timportlist(current_module.imports.first);
  224. while assigned(hp1) do
  225. begin
  226. { Get labels for the sections }
  227. objectlibrary.getdatalabel(lhead);
  228. objectlibrary.getdatalabel(lname);
  229. objectlibrary.getaddrlabel(lidata4);
  230. objectlibrary.getaddrlabel(lidata5);
  231. { create header for this importmodule }
  232. importsSection.concat(Tai_cut.Create_begin);
  233. importsSection.concat(Tai_section.Create(sec_idata2));
  234. importsSection.concat(Tai_label.Create(lhead));
  235. { pointer to procedure names }
  236. importsSection.concat(Tai_const_symbol.Create_rva(lidata4));
  237. { two empty entries follow }
  238. importsSection.concat(Tai_const.Create_32bit(0));
  239. importsSection.concat(Tai_const.Create_32bit(0));
  240. { pointer to dll name }
  241. importsSection.concat(Tai_const_symbol.Create_rva(lname));
  242. { pointer to fixups }
  243. importsSection.concat(Tai_const_symbol.Create_rva(lidata5));
  244. { first write the name references }
  245. importsSection.concat(Tai_section.Create(sec_idata4));
  246. importsSection.concat(Tai_const.Create_32bit(0));
  247. importsSection.concat(Tai_label.Create(lidata4));
  248. { then the addresses and create also the indirect jump }
  249. importsSection.concat(Tai_section.Create(sec_idata5));
  250. importsSection.concat(Tai_const.Create_32bit(0));
  251. importsSection.concat(Tai_label.Create(lidata5));
  252. { create procedures }
  253. hp2:=timported_item(hp1.imported_items.first);
  254. while assigned(hp2) do
  255. begin
  256. { insert cuts }
  257. importsSection.concat(Tai_cut.Create);
  258. { create indirect jump }
  259. if not hp2.is_var then
  260. begin
  261. objectlibrary.getlabel(lcode);
  262. reference_reset_symbol(href,lcode,0);
  263. { place jump in codesegment, insert a code section in the
  264. imporTSection to reduce the amount of .s files (PFV) }
  265. importsSection.concat(Tai_section.Create(sec_code));
  266. {$IfDef GDB}
  267. if (cs_debuginfo in aktmoduleswitches) then
  268. importsSection.concat(Tai_stab_function_name.Create(nil));
  269. {$EndIf GDB}
  270. importsSection.concat(Tai_symbol.Createname_global(hp2.func^,0));
  271. importsSection.concat(Taicpu.Op_ref(A_JMP,S_NO,href));
  272. importsSection.concat(Tai_align.Create_op(4,$90));
  273. end;
  274. { create head link }
  275. importsSection.concat(Tai_section.Create(sec_idata7));
  276. importsSection.concat(Tai_const_symbol.Create_rva(lhead));
  277. { fixup }
  278. objectlibrary.getlabel(tasmlabel(hp2.lab));
  279. importsSection.concat(Tai_section.Create(sec_idata4));
  280. importsSection.concat(Tai_const_symbol.Create_rva(hp2.lab));
  281. { add jump field to imporTSection }
  282. importsSection.concat(Tai_section.Create(sec_idata5));
  283. if hp2.is_var then
  284. importsSection.concat(Tai_symbol.Createname_global(hp2.func^,0))
  285. else
  286. importsSection.concat(Tai_label.Create(lcode));
  287. {$ifdef GDB}
  288. if (cs_debuginfo in aktmoduleswitches) then
  289. begin
  290. if assigned(hp2.name) then
  291. begin
  292. importname:='__imp_'+hp2.name^;
  293. suffix:=0;
  294. while assigned(objectlibrary.getasmsymbol(importname)) do
  295. begin
  296. inc(suffix);
  297. importname:='__imp_'+hp2.name^+'_'+tostr(suffix);
  298. end;
  299. importssection.concat(tai_symbol.createname(importname,4));
  300. end
  301. else
  302. begin
  303. importname:='__imp_by_ordinal'+tostr(hp2.ordnr);
  304. suffix:=0;
  305. while assigned(objectlibrary.getasmsymbol(importname)) do
  306. begin
  307. inc(suffix);
  308. importname:='__imp_by_ordinal'+tostr(hp2.ordnr)+'_'+tostr(suffix);
  309. end;
  310. importssection.concat(tai_symbol.createname(importname,4));
  311. end;
  312. end;
  313. {$endif GDB}
  314. if hp2.name^<>'' then
  315. importsSection.concat(Tai_const_symbol.Create_rva(hp2.lab))
  316. else
  317. importsSection.concat(Tai_const.Create_32bit($80000000 or hp2.ordnr));
  318. { finally the import information }
  319. importsSection.concat(Tai_section.Create(sec_idata6));
  320. importsSection.concat(Tai_label.Create(hp2.lab));
  321. importsSection.concat(Tai_const.Create_16bit(hp2.ordnr));
  322. importsSection.concat(Tai_string.Create(hp2.name^+#0));
  323. importsSection.concat(Tai_align.Create_op(2,0));
  324. hp2:=timported_item(hp2.next);
  325. end;
  326. { write final section }
  327. importsSection.concat(Tai_cut.Create_end);
  328. { end of name references }
  329. importsSection.concat(Tai_section.Create(sec_idata4));
  330. importsSection.concat(Tai_const.Create_32bit(0));
  331. { end if addresses }
  332. importsSection.concat(Tai_section.Create(sec_idata5));
  333. importsSection.concat(Tai_const.Create_32bit(0));
  334. { dllname }
  335. importsSection.concat(Tai_section.Create(sec_idata7));
  336. importsSection.concat(Tai_label.Create(lname));
  337. importsSection.concat(Tai_string.Create(hp1.dllname^+#0));
  338. hp1:=timportlist(hp1.next);
  339. end;
  340. end;
  341. procedure timportlibwin32.generatelib;
  342. var
  343. hp1 : timportlist;
  344. hp2 : timported_item;
  345. l1,l2,l3,l4 : tasmlabel;
  346. {$ifdef GDB}
  347. importname : string;
  348. suffix : integer;
  349. {$endif GDB}
  350. href : treference;
  351. begin
  352. if not(aktoutputformat in MainAsmFormats)then
  353. begin
  354. generatenasmlib;
  355. exit;
  356. end;
  357. hp1:=timportlist(current_module.imports.first);
  358. while assigned(hp1) do
  359. begin
  360. { align codesegment for the jumps }
  361. importsSection.concat(Tai_section.Create(sec_code));
  362. importsSection.concat(Tai_align.Create_op(4,$90));
  363. { Get labels for the sections }
  364. objectlibrary.getlabel(l1);
  365. objectlibrary.getlabel(l2);
  366. objectlibrary.getlabel(l3);
  367. importsSection.concat(Tai_section.Create(sec_idata2));
  368. { pointer to procedure names }
  369. importsSection.concat(Tai_const_symbol.Create_rva(l2));
  370. { two empty entries follow }
  371. importsSection.concat(Tai_const.Create_32bit(0));
  372. importsSection.concat(Tai_const.Create_32bit(0));
  373. { pointer to dll name }
  374. importsSection.concat(Tai_const_symbol.Create_rva(l1));
  375. { pointer to fixups }
  376. importsSection.concat(Tai_const_symbol.Create_rva(l3));
  377. { only create one section for each else it will
  378. create a lot of idata* }
  379. { first write the name references }
  380. importsSection.concat(Tai_section.Create(sec_idata4));
  381. importsSection.concat(Tai_label.Create(l2));
  382. hp2:=timported_item(hp1.imported_items.first);
  383. while assigned(hp2) do
  384. begin
  385. objectlibrary.getlabel(tasmlabel(hp2.lab));
  386. if hp2.name^<>'' then
  387. importsSection.concat(Tai_const_symbol.Create_rva(hp2.lab))
  388. else
  389. importsSection.concat(Tai_const.Create_32bit($80000000 or hp2.ordnr));
  390. hp2:=timported_item(hp2.next);
  391. end;
  392. { finalize the names ... }
  393. importsSection.concat(Tai_const.Create_32bit(0));
  394. { then the addresses and create also the indirect jump }
  395. importsSection.concat(Tai_section.Create(sec_idata5));
  396. importsSection.concat(Tai_label.Create(l3));
  397. hp2:=timported_item(hp1.imported_items.first);
  398. while assigned(hp2) do
  399. begin
  400. if not hp2.is_var then
  401. begin
  402. objectlibrary.getlabel(l4);
  403. { create indirect jump }
  404. reference_reset_symbol(href,l4,0);
  405. { place jump in codesegment }
  406. importsSection.concat(Tai_section.Create(sec_code));
  407. importsSection.concat(Tai_symbol.Createname_global(hp2.func^,0));
  408. importsSection.concat(Taicpu.Op_ref(A_JMP,S_NO,href));
  409. importsSection.concat(Tai_align.Create_op(4,$90));
  410. { add jump field to imporTSection }
  411. importsSection.concat(Tai_section.Create(sec_idata5));
  412. {$ifdef GDB}
  413. if (cs_debuginfo in aktmoduleswitches) then
  414. begin
  415. if assigned(hp2.name) then
  416. begin
  417. importname:='__imp_'+hp2.name^;
  418. suffix:=0;
  419. while assigned(objectlibrary.getasmsymbol(importname)) do
  420. begin
  421. inc(suffix);
  422. importname:='__imp_'+hp2.name^+'_'+tostr(suffix);
  423. end;
  424. importssection.concat(tai_symbol.createname(importname,4));
  425. end
  426. else
  427. begin
  428. importname:='__imp_by_ordinal'+tostr(hp2.ordnr);
  429. suffix:=0;
  430. while assigned(objectlibrary.getasmsymbol(importname)) do
  431. begin
  432. inc(suffix);
  433. importname:='__imp_by_ordinal'+tostr(hp2.ordnr)+'_'+tostr(suffix);
  434. end;
  435. importssection.concat(tai_symbol.createname(importname,4));
  436. end;
  437. end;
  438. {$endif GDB}
  439. importsSection.concat(Tai_label.Create(l4));
  440. end
  441. else
  442. begin
  443. importsSection.concat(Tai_symbol.Createname_global(hp2.func^,0));
  444. end;
  445. importsSection.concat(Tai_const_symbol.Create_rva(hp2.lab));
  446. hp2:=timported_item(hp2.next);
  447. end;
  448. { finalize the addresses }
  449. importsSection.concat(Tai_const.Create_32bit(0));
  450. { finally the import information }
  451. importsSection.concat(Tai_section.Create(sec_idata6));
  452. hp2:=timported_item(hp1.imported_items.first);
  453. while assigned(hp2) do
  454. begin
  455. importsSection.concat(Tai_label.Create(hp2.lab));
  456. { the ordinal number }
  457. importsSection.concat(Tai_const.Create_16bit(hp2.ordnr));
  458. importsSection.concat(Tai_string.Create(hp2.name^+#0));
  459. importsSection.concat(Tai_align.Create_op(2,0));
  460. hp2:=timported_item(hp2.next);
  461. end;
  462. { create import dll name }
  463. importsSection.concat(Tai_section.Create(sec_idata7));
  464. importsSection.concat(Tai_label.Create(l1));
  465. importsSection.concat(Tai_string.Create(hp1.dllname^+#0));
  466. hp1:=timportlist(hp1.next);
  467. end;
  468. end;
  469. {*****************************************************************************
  470. TEXPORTLIBWIN32
  471. *****************************************************************************}
  472. procedure texportlibwin32.preparelib(const s:string);
  473. begin
  474. if not(assigned(exportssection)) then
  475. exportssection:=TAAsmoutput.create;
  476. last_index:=0;
  477. objectlibrary.getdatalabel(edatalabel);
  478. end;
  479. procedure texportlibwin32.exportvar(hp : texported_item);
  480. begin
  481. { same code used !! PM }
  482. exportprocedure(hp);
  483. end;
  484. procedure texportlibwin32.exportprocedure(hp : texported_item);
  485. { must be ordered at least for win32 !! }
  486. var
  487. hp2 : texported_item;
  488. begin
  489. { first test the index value }
  490. if (hp.options and eo_index)<>0 then
  491. begin
  492. if (hp.index<=0) or (hp.index>$ffff) then
  493. begin
  494. message1(parser_e_export_invalid_index,tostr(hp.index));
  495. exit;
  496. end;
  497. if (hp.index<=last_index) then
  498. begin
  499. message1(parser_e_export_ordinal_double,tostr(hp.index));
  500. { disregard index value }
  501. inc(last_index);
  502. hp.index:=last_index;
  503. exit;
  504. end
  505. else
  506. begin
  507. last_index:=hp.index;
  508. end;
  509. end
  510. else
  511. begin
  512. inc(last_index);
  513. hp.index:=last_index;
  514. end;
  515. { now place in correct order }
  516. hp2:=texported_item(current_module._exports.first);
  517. while assigned(hp2) and
  518. (hp.name^>hp2.name^) do
  519. hp2:=texported_item(hp2.next);
  520. { insert hp there !! }
  521. if assigned(hp2) and (hp2.name^=hp.name^) then
  522. begin
  523. { this is not allowed !! }
  524. message1(parser_e_export_name_double,hp.name^);
  525. exit;
  526. end;
  527. if hp2=texported_item(current_module._exports.first) then
  528. current_module._exports.concat(hp)
  529. else if assigned(hp2) then
  530. begin
  531. hp.next:=hp2;
  532. hp.previous:=hp2.previous;
  533. if assigned(hp2.previous) then
  534. hp2.previous.next:=hp;
  535. hp2.previous:=hp;
  536. end
  537. else
  538. current_module._exports.concat(hp);
  539. end;
  540. procedure texportlibwin32.generatelib;
  541. var
  542. ordinal_base,ordinal_max,ordinal_min : longint;
  543. current_index : longint;
  544. entries,named_entries : longint;
  545. name_label,dll_name_label,export_address_table : tasmlabel;
  546. export_name_table_pointers,export_ordinal_table : tasmlabel;
  547. hp,hp2 : texported_item;
  548. temtexport : TLinkedList;
  549. address_table,name_table_pointers,
  550. name_table,ordinal_table : TAAsmoutput;
  551. begin
  552. if not (aktoutputformat in MainAsmFormats)then
  553. begin
  554. generatenasmlib;
  555. exit;
  556. end;
  557. hp:=texported_item(current_module._exports.first);
  558. if not assigned(hp) then
  559. exit;
  560. ordinal_max:=0;
  561. ordinal_min:=$7FFFFFFF;
  562. entries:=0;
  563. named_entries:=0;
  564. objectlibrary.getlabel(dll_name_label);
  565. objectlibrary.getlabel(export_address_table);
  566. objectlibrary.getlabel(export_name_table_pointers);
  567. objectlibrary.getlabel(export_ordinal_table);
  568. { count entries }
  569. while assigned(hp) do
  570. begin
  571. inc(entries);
  572. if (hp.index>ordinal_max) then
  573. ordinal_max:=hp.index;
  574. if (hp.index>0) and (hp.index<ordinal_min) then
  575. ordinal_min:=hp.index;
  576. if assigned(hp.name) then
  577. inc(named_entries);
  578. hp:=texported_item(hp.next);
  579. end;
  580. { no support for higher ordinal base yet !! }
  581. ordinal_base:=1;
  582. current_index:=ordinal_base;
  583. { we must also count the holes !! }
  584. entries:=ordinal_max-ordinal_base+1;
  585. exportsSection.concat(Tai_section.Create(sec_edata));
  586. { create label to reference from main so smartlink will include
  587. the .edata section }
  588. exportsSection.concat(Tai_symbol.Create(edatalabel,0));
  589. { export flags }
  590. exportsSection.concat(Tai_const.Create_32bit(0));
  591. { date/time stamp }
  592. exportsSection.concat(Tai_const.Create_32bit(0));
  593. { major version }
  594. exportsSection.concat(Tai_const.Create_16bit(0));
  595. { minor version }
  596. exportsSection.concat(Tai_const.Create_16bit(0));
  597. { pointer to dll name }
  598. exportsSection.concat(Tai_const_symbol.Create_rva(dll_name_label));
  599. { ordinal base normally set to 1 }
  600. exportsSection.concat(Tai_const.Create_32bit(ordinal_base));
  601. { number of entries }
  602. exportsSection.concat(Tai_const.Create_32bit(entries));
  603. { number of named entries }
  604. exportsSection.concat(Tai_const.Create_32bit(named_entries));
  605. { address of export address table }
  606. exportsSection.concat(Tai_const_symbol.Create_rva(export_address_table));
  607. { address of name pointer pointers }
  608. exportsSection.concat(Tai_const_symbol.Create_rva(export_name_table_pointers));
  609. { address of ordinal number pointers }
  610. exportsSection.concat(Tai_const_symbol.Create_rva(export_ordinal_table));
  611. { the name }
  612. exportsSection.concat(Tai_label.Create(dll_name_label));
  613. if st='' then
  614. exportsSection.concat(Tai_string.Create(current_module.modulename^+target_info.sharedlibext+#0))
  615. else
  616. exportsSection.concat(Tai_string.Create(st+target_info.sharedlibext+#0));
  617. { export address table }
  618. address_table:=TAAsmoutput.create;
  619. address_table.concat(Tai_align.Create_op(4,0));
  620. address_table.concat(Tai_label.Create(export_address_table));
  621. name_table_pointers:=TAAsmoutput.create;
  622. name_table_pointers.concat(Tai_align.Create_op(4,0));
  623. name_table_pointers.concat(Tai_label.Create(export_name_table_pointers));
  624. ordinal_table:=TAAsmoutput.create;
  625. ordinal_table.concat(Tai_align.Create_op(4,0));
  626. ordinal_table.concat(Tai_label.Create(export_ordinal_table));
  627. name_table:=TAAsmoutput.Create;
  628. name_table.concat(Tai_align.Create_op(4,0));
  629. { write each address }
  630. hp:=texported_item(current_module._exports.first);
  631. while assigned(hp) do
  632. begin
  633. if (hp.options and eo_name)<>0 then
  634. begin
  635. objectlibrary.getlabel(name_label);
  636. name_table_pointers.concat(Tai_const_symbol.Create_rva(name_label));
  637. ordinal_table.concat(Tai_const.Create_16bit(hp.index-ordinal_base));
  638. name_table.concat(Tai_align.Create_op(2,0));
  639. name_table.concat(Tai_label.Create(name_label));
  640. name_table.concat(Tai_string.Create(hp.name^+#0));
  641. end;
  642. hp:=texported_item(hp.next);
  643. end;
  644. { order in increasing ordinal values }
  645. { into temtexport list }
  646. temtexport:=TLinkedList.Create;
  647. hp:=texported_item(current_module._exports.first);
  648. while assigned(hp) do
  649. begin
  650. current_module._exports.remove(hp);
  651. hp2:=texported_item(temtexport.first);
  652. while assigned(hp2) and (hp.index>hp2.index) do
  653. begin
  654. hp2:=texported_item(hp2.next);
  655. end;
  656. if hp2=texported_item(temtexport.first) then
  657. temtexport.insert(hp)
  658. else
  659. begin
  660. if assigned(hp2) then
  661. begin
  662. hp.next:=hp2;
  663. hp.previous:=hp2.previous;
  664. hp2.previous:=hp;
  665. if assigned(hp.previous) then
  666. hp.previous.next:=hp;
  667. end
  668. else
  669. temtexport.concat(hp);
  670. end;
  671. hp:=texported_item(current_module._exports.first);;
  672. end;
  673. { write the export adress table }
  674. current_index:=ordinal_base;
  675. hp:=texported_item(temtexport.first);
  676. while assigned(hp) do
  677. begin
  678. { fill missing values }
  679. while current_index<hp.index do
  680. begin
  681. address_table.concat(Tai_const.Create_32bit(0));
  682. inc(current_index);
  683. end;
  684. case hp.sym.typ of
  685. varsym :
  686. address_table.concat(Tai_const_symbol.Createname_rva(tvarsym(hp.sym).mangledname));
  687. typedconstsym :
  688. address_table.concat(Tai_const_symbol.Createname_rva(ttypedconstsym(hp.sym).mangledname));
  689. procsym :
  690. address_table.concat(Tai_const_symbol.Createname_rva(tprocsym(hp.sym).defs^.def.mangledname));
  691. end;
  692. inc(current_index);
  693. hp:=texported_item(hp.next);
  694. end;
  695. exportsSection.concatlist(address_table);
  696. exportsSection.concatlist(name_table_pointers);
  697. exportsSection.concatlist(ordinal_table);
  698. exportsSection.concatlist(name_table);
  699. address_table.Free;
  700. name_table_pointers.free;
  701. ordinal_table.free;
  702. name_table.free;
  703. temtexport.free;
  704. end;
  705. procedure texportlibwin32.generatenasmlib;
  706. var
  707. hp : texported_item;
  708. p : pchar;
  709. s : string;
  710. begin
  711. exportssection.concat(tai_section.create(sec_code));
  712. hp:=texported_item(current_module._exports.first);
  713. while assigned(hp) do
  714. begin
  715. case hp.sym.typ of
  716. varsym :
  717. s:=tvarsym(hp.sym).mangledname;
  718. typedconstsym :
  719. s:=ttypedconstsym(hp.sym).mangledname;
  720. procsym :
  721. s:=tprocsym(hp.sym).defs^.def.mangledname;
  722. else
  723. s:='';
  724. end;
  725. p:=strpnew(#9+'export '+s+' '+hp.name^+' '+tostr(hp.index));
  726. exportssection.concat(tai_direct.create(p));
  727. hp:=texported_item(hp.next);
  728. end;
  729. end;
  730. {****************************************************************************
  731. TLINKERWIN32
  732. ****************************************************************************}
  733. Constructor TLinkerWin32.Create;
  734. begin
  735. Inherited Create;
  736. { allow duplicated libs (PM) }
  737. SharedLibFiles.doubles:=true;
  738. StaticLibFiles.doubles:=true;
  739. If not ForceDeffileForExport then
  740. UseDeffileForExport:=false;
  741. end;
  742. Procedure TLinkerWin32.SetDefaultInfo;
  743. begin
  744. with Info do
  745. begin
  746. ExeCmd[1]:='ldw $OPT $STRIP $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
  747. DllCmd[1]:='ldw $OPT $STRIP --dll $APPTYPE $IMAGEBASE $RELOC -o $EXE $RES';
  748. if RelocSection or UseDeffileForExport then
  749. begin
  750. { ExeCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF';
  751. use short forms to avoid 128 char limitation problem }
  752. ExeCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
  753. ExeCmd[3]:='ldw $OPT $STRIP $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
  754. { DllCmd[2]:='dlltool --as $ASBIN --dllname $EXE --output-exp exp.$$$ $RELOC $DEF'; }
  755. DllCmd[2]:='dlltool -S $ASBIN -D $EXE -e exp.$$$ $RELOC $DEF';
  756. DllCmd[3]:='ldw $OPT $STRIP --dll $APPTYPE $IMAGEBASE -o $EXE $RES exp.$$$';
  757. end;
  758. end;
  759. end;
  760. Function TLinkerWin32.WriteResponseFile(isdll:boolean) : Boolean;
  761. Var
  762. linkres : TLinkRes;
  763. HPath : TStringListItem;
  764. s,s2 : string;
  765. i : integer;
  766. linklibc : boolean;
  767. begin
  768. WriteResponseFile:=False;
  769. linklibc:=false;
  770. { Open link.res file }
  771. LinkRes:=TLinkRes.Create(outputexedir+Info.ResName);
  772. { Write path to search libraries }
  773. HPath:=TStringListItem(current_module.locallibrarysearchpath.First);
  774. while assigned(HPath) do
  775. begin
  776. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath.Str)+')');
  777. HPath:=TStringListItem(HPath.Next);
  778. end;
  779. HPath:=TStringListItem(LibrarySearchPath.First);
  780. while assigned(HPath) do
  781. begin
  782. LinkRes.Add('SEARCH_DIR('+GetShortName(HPath.Str)+')');
  783. HPath:=TStringListItem(HPath.Next);
  784. end;
  785. { add objectfiles, start with prt0 always }
  786. LinkRes.Add('INPUT(');
  787. if isdll then
  788. LinkRes.AddFileName(GetShortName(FindObjectFile('wdllprt0','')))
  789. else
  790. LinkRes.AddFileName(GetShortName(FindObjectFile('wprt0','')));
  791. while not ObjectFiles.Empty do
  792. begin
  793. s:=ObjectFiles.GetFirst;
  794. if s<>'' then
  795. LinkRes.AddFileName(GetShortName(s));
  796. end;
  797. { add libaries required for profiling }
  798. if cs_profile in aktmoduleswitches then
  799. begin
  800. LinkRes.Add('-lgmon');
  801. LinkRes.Add('-lc');
  802. end;
  803. LinkRes.Add(')');
  804. { Write staticlibraries }
  805. if not StaticLibFiles.Empty then
  806. begin
  807. LinkRes.Add('GROUP(');
  808. While not StaticLibFiles.Empty do
  809. begin
  810. S:=StaticLibFiles.GetFirst;
  811. LinkRes.AddFileName(GetShortName(s));
  812. end;
  813. LinkRes.Add(')');
  814. end;
  815. { Write sharedlibraries }
  816. if not SharedLibFiles.Empty then
  817. begin
  818. LinkRes.Add('INPUT(') ;
  819. While not SharedLibFiles.Empty do
  820. begin
  821. S:=SharedLibFiles.GetFirst;
  822. if FindLibraryFile(s,target_info.staticClibprefix,target_info.staticClibext,s2) then
  823. begin
  824. LinkRes.Add(GetShortName(s2));
  825. continue;
  826. end;
  827. if pos(target_info.sharedlibprefix,s)=1 then
  828. s:=copy(s,length(target_info.sharedlibprefix)+1,255);
  829. if s<>'c' then
  830. begin
  831. i:=Pos(target_info.sharedlibext,S);
  832. if i>0 then
  833. Delete(S,i,255);
  834. LinkRes.Add('-l'+s);
  835. end
  836. else
  837. begin
  838. LinkRes.Add('-l'+s);
  839. linklibc:=true;
  840. end;
  841. end;
  842. { be sure that libc is the last lib }
  843. if linklibc then
  844. LinkRes.Add('-lc');
  845. LinkRes.Add(')');
  846. end;
  847. { Write and Close response }
  848. linkres.writetodisk;
  849. LinkRes.Free;
  850. WriteResponseFile:=True;
  851. end;
  852. function TLinkerWin32.MakeExecutable:boolean;
  853. var
  854. binstr,
  855. cmdstr : string;
  856. success : boolean;
  857. i : longint;
  858. AsBinStr : string[80];
  859. StripStr,
  860. RelocStr,
  861. AppTypeStr,
  862. ImageBaseStr : string[40];
  863. begin
  864. if not(cs_link_extern in aktglobalswitches) then
  865. Message1(exec_i_linking,current_module.exefilename^);
  866. { Create some replacements }
  867. RelocStr:='';
  868. AppTypeStr:='';
  869. ImageBaseStr:='';
  870. StripStr:='';
  871. FindExe('asw',AsBinStr);
  872. if RelocSection then
  873. { Using short form to avoid problems with 128 char limitation under Dos. }
  874. RelocStr:='-b base.$$$';
  875. if apptype=app_gui then
  876. AppTypeStr:='--subsystem windows';
  877. if assigned(DLLImageBase) then
  878. ImageBaseStr:='--image-base=0x'+DLLImageBase^;
  879. if (cs_link_strip in aktglobalswitches) then
  880. StripStr:='-s';
  881. { Write used files and libraries }
  882. WriteResponseFile(false);
  883. { Call linker }
  884. success:=false;
  885. for i:=1 to 3 do
  886. begin
  887. SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
  888. if binstr<>'' then
  889. begin
  890. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
  891. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  892. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  893. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  894. Replace(cmdstr,'$ASBIN',AsbinStr);
  895. Replace(cmdstr,'$RELOC',RelocStr);
  896. Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
  897. Replace(cmdstr,'$STRIP',StripStr);
  898. if not DefFile.Empty {and UseDefFileForExport} then
  899. begin
  900. DefFile.WriteFile;
  901. Replace(cmdstr,'$DEF','-d '+maybequoted(deffile.fname));
  902. end
  903. else
  904. Replace(cmdstr,'$DEF','');
  905. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
  906. if not success then
  907. break;
  908. end;
  909. end;
  910. { Post process }
  911. if success then
  912. success:=PostProcessExecutable(current_module.exefilename^,false);
  913. { Remove ReponseFile }
  914. if (success) and not(cs_link_extern in aktglobalswitches) then
  915. begin
  916. RemoveFile(outputexedir+Info.ResName);
  917. RemoveFile('base.$$$');
  918. RemoveFile('exp.$$$');
  919. RemoveFile('deffile.$$$');
  920. end;
  921. MakeExecutable:=success; { otherwise a recursive call to link method }
  922. end;
  923. Function TLinkerWin32.MakeSharedLibrary:boolean;
  924. var
  925. binstr,
  926. cmdstr : string;
  927. success : boolean;
  928. i : longint;
  929. AsBinStr : string[80];
  930. StripStr,
  931. RelocStr,
  932. AppTypeStr,
  933. ImageBaseStr : string[40];
  934. begin
  935. MakeSharedLibrary:=false;
  936. if not(cs_link_extern in aktglobalswitches) then
  937. Message1(exec_i_linking,current_module.sharedlibfilename^);
  938. { Create some replacements }
  939. RelocStr:='';
  940. AppTypeStr:='';
  941. ImageBaseStr:='';
  942. StripStr:='';
  943. FindExe('asw',AsBinStr);
  944. if RelocSection then
  945. { Using short form to avoid problems with 128 char limitation under Dos. }
  946. RelocStr:='-b base.$$$';
  947. if apptype=app_gui then
  948. AppTypeStr:='--subsystem windows';
  949. if assigned(DLLImageBase) then
  950. ImageBaseStr:='--image-base=0x'+DLLImageBase^;
  951. if (cs_link_strip in aktglobalswitches) then
  952. StripStr:='-s';
  953. { Write used files and libraries }
  954. WriteResponseFile(true);
  955. { Call linker }
  956. success:=false;
  957. for i:=1 to 3 do
  958. begin
  959. SplitBinCmd(Info.DllCmd[i],binstr,cmdstr);
  960. if binstr<>'' then
  961. begin
  962. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
  963. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  964. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  965. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  966. Replace(cmdstr,'$ASBIN',AsbinStr);
  967. Replace(cmdstr,'$RELOC',RelocStr);
  968. Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
  969. Replace(cmdstr,'$STRIP',StripStr);
  970. if not DefFile.Empty {and UseDefFileForExport} then
  971. begin
  972. DefFile.WriteFile;
  973. Replace(cmdstr,'$DEF','-d '+maybequoted(deffile.fname));
  974. end
  975. else
  976. Replace(cmdstr,'$DEF','');
  977. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
  978. if not success then
  979. break;
  980. end;
  981. end;
  982. { Post process }
  983. if success then
  984. success:=PostProcessExecutable(current_module.sharedlibfilename^,true);
  985. { Remove ReponseFile }
  986. if (success) and not(cs_link_extern in aktglobalswitches) then
  987. begin
  988. RemoveFile(outputexedir+Info.ResName);
  989. RemoveFile('base.$$$');
  990. RemoveFile('exp.$$$');
  991. end;
  992. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  993. end;
  994. function tlinkerwin32.postprocessexecutable(const fn : string;isdll:boolean):boolean;
  995. type
  996. tdosheader = packed record
  997. e_magic : word;
  998. e_cblp : word;
  999. e_cp : word;
  1000. e_crlc : word;
  1001. e_cparhdr : word;
  1002. e_minalloc : word;
  1003. e_maxalloc : word;
  1004. e_ss : word;
  1005. e_sp : word;
  1006. e_csum : word;
  1007. e_ip : word;
  1008. e_cs : word;
  1009. e_lfarlc : word;
  1010. e_ovno : word;
  1011. e_res : array[0..3] of word;
  1012. e_oemid : word;
  1013. e_oeminfo : word;
  1014. e_res2 : array[0..9] of word;
  1015. e_lfanew : longint;
  1016. end;
  1017. tpeheader = packed record
  1018. PEMagic : array[0..3] of char;
  1019. Machine : word;
  1020. NumberOfSections : word;
  1021. TimeDateStamp : longint;
  1022. PointerToSymbolTable : longint;
  1023. NumberOfSymbols : longint;
  1024. SizeOfOptionalHeader : word;
  1025. Characteristics : word;
  1026. Magic : word;
  1027. MajorLinkerVersion : byte;
  1028. MinorLinkerVersion : byte;
  1029. SizeOfCode : longint;
  1030. SizeOfInitializedData : longint;
  1031. SizeOfUninitializedData : longint;
  1032. AddressOfEntryPoint : longint;
  1033. BaseOfCode : longint;
  1034. BaseOfData : longint;
  1035. ImageBase : longint;
  1036. SectionAlignment : longint;
  1037. FileAlignment : longint;
  1038. MajorOperatingSystemVersion : word;
  1039. MinorOperatingSystemVersion : word;
  1040. MajorImageVersion : word;
  1041. MinorImageVersion : word;
  1042. MajorSubsystemVersion : word;
  1043. MinorSubsystemVersion : word;
  1044. Reserved1 : longint;
  1045. SizeOfImage : longint;
  1046. SizeOfHeaders : longint;
  1047. CheckSum : longint;
  1048. Subsystem : word;
  1049. DllCharacteristics : word;
  1050. SizeOfStackReserve : longint;
  1051. SizeOfStackCommit : longint;
  1052. SizeOfHeapReserve : longint;
  1053. SizeOfHeapCommit : longint;
  1054. LoaderFlags : longint;
  1055. NumberOfRvaAndSizes : longint;
  1056. DataDirectory : array[1..$80] of byte;
  1057. end;
  1058. tcoffsechdr=packed record
  1059. name : array[0..7] of char;
  1060. vsize : longint;
  1061. rvaofs : longint;
  1062. datalen : longint;
  1063. datapos : longint;
  1064. relocpos : longint;
  1065. lineno1 : longint;
  1066. nrelocs : word;
  1067. lineno2 : word;
  1068. flags : longint;
  1069. end;
  1070. psecfill=^TSecfill;
  1071. TSecfill=record
  1072. fillpos,
  1073. fillsize : longint;
  1074. next : psecfill;
  1075. end;
  1076. var
  1077. f : file;
  1078. cmdstr : string;
  1079. dosheader : tdosheader;
  1080. peheader : tpeheader;
  1081. firstsecpos,
  1082. maxfillsize,
  1083. l,peheaderpos : longint;
  1084. coffsec : tcoffsechdr;
  1085. secroot,hsecroot : psecfill;
  1086. zerobuf : pointer;
  1087. begin
  1088. postprocessexecutable:=false;
  1089. { when -s is used or it's a dll then quit }
  1090. if (cs_link_extern in aktglobalswitches) then
  1091. begin
  1092. case apptype of
  1093. app_gui :
  1094. cmdstr:='--subsystem gui';
  1095. app_cui :
  1096. cmdstr:='--subsystem console';
  1097. end;
  1098. if dllversion<>'' then
  1099. cmdstr:=cmdstr+' --version '+dllversion;
  1100. cmdstr:=cmdstr+' --input '+fn;
  1101. cmdstr:=cmdstr+' --stack '+tostr(stacksize);
  1102. DoExec(FindUtil('postw32'),cmdstr,false,false);
  1103. postprocessexecutable:=true;
  1104. exit;
  1105. end;
  1106. { open file }
  1107. assign(f,fn);
  1108. {$I-}
  1109. reset(f,1);
  1110. if ioresult<>0 then
  1111. Message1(execinfo_f_cant_open_executable,fn);
  1112. { read headers }
  1113. blockread(f,dosheader,sizeof(tdosheader));
  1114. peheaderpos:=dosheader.e_lfanew;
  1115. seek(f,peheaderpos);
  1116. blockread(f,peheader,sizeof(tpeheader));
  1117. { write info }
  1118. Message1(execinfo_x_codesize,tostr(peheader.SizeOfCode));
  1119. Message1(execinfo_x_initdatasize,tostr(peheader.SizeOfInitializedData));
  1120. Message1(execinfo_x_uninitdatasize,tostr(peheader.SizeOfUninitializedData));
  1121. { change stack size (PM) }
  1122. { I am not sure that the default value is adequate !! }
  1123. peheader.SizeOfStackReserve:=stacksize;
  1124. { change the header }
  1125. { sub system }
  1126. { gui=2 }
  1127. { cui=3 }
  1128. case apptype of
  1129. app_gui :
  1130. peheader.Subsystem:=2;
  1131. app_cui :
  1132. peheader.Subsystem:=3;
  1133. end;
  1134. if dllversion<>'' then
  1135. begin
  1136. peheader.MajorImageVersion:=dllmajor;
  1137. peheader.MinorImageVersion:=dllminor;
  1138. end;
  1139. { reset timestamp }
  1140. peheader.TimeDateStamp:=0;
  1141. { write header back }
  1142. seek(f,peheaderpos);
  1143. blockwrite(f,peheader,sizeof(tpeheader));
  1144. if ioresult<>0 then
  1145. Message1(execinfo_f_cant_process_executable,fn);
  1146. seek(f,peheaderpos);
  1147. blockread(f,peheader,sizeof(tpeheader));
  1148. { write the value after the change }
  1149. Message1(execinfo_x_stackreserve,tostr(peheader.SizeOfStackReserve));
  1150. Message1(execinfo_x_stackcommit,tostr(peheader.SizeOfStackCommit));
  1151. { read section info }
  1152. maxfillsize:=0;
  1153. firstsecpos:=0;
  1154. secroot:=nil;
  1155. for l:=1 to peheader.NumberOfSections do
  1156. begin
  1157. blockread(f,coffsec,sizeof(tcoffsechdr));
  1158. if coffsec.datapos>0 then
  1159. begin
  1160. if secroot=nil then
  1161. firstsecpos:=coffsec.datapos;
  1162. new(hsecroot);
  1163. hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
  1164. hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
  1165. hsecroot^.next:=secroot;
  1166. secroot:=hsecroot;
  1167. if secroot^.fillsize>maxfillsize then
  1168. maxfillsize:=secroot^.fillsize;
  1169. end;
  1170. end;
  1171. if firstsecpos>0 then
  1172. begin
  1173. l:=firstsecpos-filepos(f);
  1174. if l>maxfillsize then
  1175. maxfillsize:=l;
  1176. end
  1177. else
  1178. l:=0;
  1179. { get zero buffer }
  1180. getmem(zerobuf,maxfillsize);
  1181. fillchar(zerobuf^,maxfillsize,0);
  1182. { zero from sectioninfo until first section }
  1183. blockwrite(f,zerobuf^,l);
  1184. { zero section alignments }
  1185. while assigned(secroot) do
  1186. begin
  1187. seek(f,secroot^.fillpos);
  1188. blockwrite(f,zerobuf^,secroot^.fillsize);
  1189. hsecroot:=secroot;
  1190. secroot:=secroot^.next;
  1191. dispose(hsecroot);
  1192. end;
  1193. freemem(zerobuf,maxfillsize);
  1194. close(f);
  1195. {$I+}
  1196. if ioresult<>0 then;
  1197. postprocessexecutable:=true;
  1198. end;
  1199. {****************************************************************************
  1200. TDLLScannerWin32
  1201. ****************************************************************************}
  1202. procedure tDLLScannerWin32.GetDefExt(var N:longint;var P:pStr4);
  1203. begin
  1204. N:=sizeof(DefaultDLLExtensions)div sizeof(DefaultDLLExtensions[1]);
  1205. pointer(P):=@DefaultDLLExtensions;
  1206. end;
  1207. function tDLLScannerWin32.DOSstubOK(var x:cardinal):boolean;
  1208. begin
  1209. blockread(f,TheWord,2,loaded);
  1210. if loaded<>2 then
  1211. DOSstubOK:=false
  1212. else
  1213. begin
  1214. DOSstubOK:=(TheWord='MZ');
  1215. seek(f,$3C);
  1216. blockread(f,x,4,loaded);
  1217. if(loaded<>4)or(longint(x)>filesize(f))then
  1218. DOSstubOK:=false;
  1219. end;
  1220. end;
  1221. function TDLLScannerWin32.FindDLL(const s:string;var founddll:string):boolean;
  1222. var
  1223. sysdir : string;
  1224. Found : boolean;
  1225. begin
  1226. Found:=false;
  1227. { Look for DLL in:
  1228. 1. Current dir
  1229. 2. Library Path
  1230. 3. windir,windir/system,windir/system32 }
  1231. Found:=FindFile(s,'.'+source_info.DirSep,founddll);
  1232. if (not found) then
  1233. Found:=librarysearchpath.FindFile(s,founddll);
  1234. if (not found) then
  1235. begin
  1236. sysdir:=FixPath(GetEnv('windir'),false);
  1237. Found:=FindFile(s,sysdir+';'+sysdir+'system'+source_info.DirSep+';'+sysdir+'system32'+source_info.DirSep,founddll);
  1238. end;
  1239. if (not found) then
  1240. begin
  1241. message1(exec_w_libfile_not_found,s);
  1242. FoundDll:=s;
  1243. end;
  1244. FindDll:=Found;
  1245. end;
  1246. function tDLLScannerWin32.ExtractDllName(Const Name : string) : string;
  1247. var n : string;
  1248. begin
  1249. n:=Upper(SplitExtension(Name));
  1250. if (n='.DLL') or (n='.DRV') or (n='.EXE') then
  1251. ExtractDllName:=Name
  1252. else
  1253. ExtractDllName:=Name+target_info.sharedlibext;
  1254. end;
  1255. function tDLLScannerWin32.isSuitableFileType(x:cardinal):longbool;
  1256. begin
  1257. seek(f,x);
  1258. blockread(f,TheWord,2,loaded);
  1259. isSuitableFileType:=(loaded=2)and(TheWord='PE');
  1260. end;
  1261. function tDLLScannerWin32.GetEdata(HeaderEntry:cardinal):longbool;
  1262. type
  1263. TObjInfo=packed record
  1264. ObjName:array[0..7]of char;
  1265. VirtSize,
  1266. VirtAddr,
  1267. RawSize,
  1268. RawOffset,
  1269. Reloc,
  1270. LineNum:cardinal;
  1271. RelCount,
  1272. LineCount:word;
  1273. flags:cardinal;
  1274. end;
  1275. var
  1276. i:cardinal;
  1277. ObjOfs:cardinal;
  1278. Obj:TObjInfo;
  1279. APE_obj,APE_Optsize:word;
  1280. ExportRVA:cardinal;
  1281. delta:cardinal;
  1282. const
  1283. IMAGE_SCN_CNT_CODE=$00000020;
  1284. var
  1285. _d:dirstr;
  1286. _n:namestr;
  1287. _e:extstr;
  1288. function isUsedFunction(name:pchar):longbool;
  1289. var
  1290. hp:tExternalsItem;
  1291. begin
  1292. isUsedFunction:=false;
  1293. hp:=tExternalsItem(current_module.Externals.first);
  1294. while assigned(hp)do
  1295. begin
  1296. if(assigned(hp.data))and(not hp.found)then
  1297. if hp.data^=StrPas(name)then
  1298. begin
  1299. isUsedFunction:=true;
  1300. hp.found:=true;
  1301. exit;
  1302. end;
  1303. hp:=tExternalsItem(hp.next);
  1304. end;
  1305. end;
  1306. procedure Store(index:cardinal;name:pchar;isData:longbool);
  1307. begin
  1308. if not isUsedFunction(name)then
  1309. exit;
  1310. if not(current_module.uses_imports) then
  1311. begin
  1312. current_module.uses_imports:=true;
  1313. importlib.preparelib(current_module.modulename^);
  1314. end;
  1315. if IsData then
  1316. importlib.importvariable(name,_n,name)
  1317. else
  1318. importlib.importprocedure(name,_n,index,name);
  1319. end;
  1320. procedure ProcessEdata;
  1321. type
  1322. a8=array[0..7]of char;
  1323. function GetSectionName(rva:cardinal;var Flags:cardinal):a8;
  1324. var
  1325. i:cardinal;
  1326. LocObjOfs:cardinal;
  1327. LocObj:TObjInfo;
  1328. begin
  1329. GetSectionName:='';
  1330. Flags:=0;
  1331. LocObjOfs:=APE_OptSize+HeaderOffset+24;
  1332. for i:=1 to APE_obj do
  1333. begin
  1334. seek(f,LocObjOfs);
  1335. blockread(f,LocObj,sizeof(LocObj));
  1336. if(rva>=LocObj.VirtAddr)and(rva<=LocObj.VirtAddr+LocObj.RawSize)then
  1337. begin
  1338. GetSectionName:=a8(LocObj.ObjName);
  1339. Flags:=LocObj.flags;
  1340. end;
  1341. end;
  1342. end;
  1343. var
  1344. j,Fl:cardinal;
  1345. ulongval,procEntry:cardinal;
  1346. Ordinal:word;
  1347. isData:longbool;
  1348. ExpDir:packed record
  1349. flag,
  1350. stamp:cardinal;
  1351. Major,
  1352. Minor:word;
  1353. Name,
  1354. Base,
  1355. NumFuncs,
  1356. NumNames,
  1357. AddrFuncs,
  1358. AddrNames,
  1359. AddrOrds:cardinal;
  1360. end;
  1361. begin
  1362. with Obj do
  1363. begin
  1364. seek(f,RawOffset+delta);
  1365. blockread(f,ExpDir,sizeof(ExpDir));
  1366. fsplit(impname,_d,_n,_e);
  1367. for j:=0 to pred(ExpDir.NumNames)do
  1368. begin
  1369. seek(f,RawOffset-VirtAddr+ExpDir.AddrOrds+j*2);
  1370. blockread(f,Ordinal,2);
  1371. seek(f,RawOffset-VirtAddr+ExpDir.AddrFuncs+cardinal(Ordinal)*4);
  1372. blockread(f,ProcEntry,4);
  1373. seek(f,RawOffset-VirtAddr+ExpDir.AddrNames+j*4);
  1374. blockread(f,ulongval,4);
  1375. seek(f,RawOffset-VirtAddr+ulongval);
  1376. blockread(f,cstring,sizeof(cstring));
  1377. isData:=GetSectionName(procentry,Fl)='';
  1378. if not isData then
  1379. isData:=Fl and IMAGE_SCN_CNT_CODE<>IMAGE_SCN_CNT_CODE;
  1380. Store(succ(Ordinal),cstring,isData);
  1381. end;
  1382. end;
  1383. end;
  1384. begin
  1385. GetEdata:=false;
  1386. seek(f,HeaderEntry+120);
  1387. blockread(f,ExportRVA,4);
  1388. seek(f,HeaderEntry+6);
  1389. blockread(f,APE_Obj,2);
  1390. seek(f,HeaderEntry+20);
  1391. blockread(f,APE_OptSize,2);
  1392. ObjOfs:=APE_OptSize+HeaderOffset+24;
  1393. for i:=1 to APE_obj do
  1394. begin
  1395. seek(f,ObjOfs);
  1396. blockread(f,Obj,sizeof(Obj));
  1397. inc(ObjOfs,sizeof(Obj));
  1398. with Obj do
  1399. if(VirtAddr<=ExportRva)and(ExportRva<VirtAddr+VirtSize)then
  1400. begin
  1401. delta:=ExportRva-VirtAddr;
  1402. ProcessEdata;
  1403. GetEdata:=true;
  1404. end;
  1405. end;
  1406. end;
  1407. function tDLLScannerWin32.scan(const binname:string):longbool;
  1408. var
  1409. OldFileMode:longint;
  1410. foundimp : string;
  1411. NN:longint;PP:pStr4;
  1412. begin
  1413. Scan:=false;
  1414. { is there already an import library the we will use that one }
  1415. if FindLibraryFile(binname,target_info.staticClibprefix,target_info.staticClibext,foundimp) then
  1416. exit;
  1417. { check if we can find the dll }
  1418. GetDefExt(NN,PP);
  1419. if not FindDll(DLLName(binname,NN,PP),impname) then
  1420. exit;
  1421. { read the dll file }
  1422. assign(f,impname);
  1423. OldFileMode:=filemode;
  1424. filemode:=0;
  1425. reset(f,1);
  1426. filemode:=OldFileMode;
  1427. if not DOSstubOK(HeaderOffset)then
  1428. scan:=false
  1429. else if not isSuitableFileType(HeaderOffset)then
  1430. scan:=false
  1431. else
  1432. scan:=GetEdata(HeaderOffset);
  1433. close(f);
  1434. end;
  1435. {*****************************************************************************
  1436. Initialize
  1437. *****************************************************************************}
  1438. initialization
  1439. {$ifdef i386}
  1440. RegisterExternalLinker(system_i386_win32_info,TLinkerWin32);
  1441. RegisterImport(system_i386_win32,TImportLibWin32);
  1442. RegisterExport(system_i386_win32,TExportLibWin32);
  1443. RegisterDLLScanner(system_i386_win32,TDLLScannerWin32);
  1444. RegisterAr(ar_gnu_arw_info);
  1445. RegisterRes(res_gnu_windres_info);
  1446. RegisterTarget(system_i386_win32_info);
  1447. {$endif i386}
  1448. end.
  1449. {
  1450. $Log$
  1451. Revision 1.39 2002-08-12 15:08:44 carl
  1452. + stab register indexes for powerpc (moved from gdb to cpubase)
  1453. + tprocessor enumeration moved to cpuinfo
  1454. + linker in target_info is now a class
  1455. * many many updates for m68k (will soon start to compile)
  1456. - removed some ifdef or correct them for correct cpu
  1457. Revision 1.38 2002/08/11 14:32:32 peter
  1458. * renamed current_library to objectlibrary
  1459. Revision 1.37 2002/08/11 13:24:20 peter
  1460. * saving of asmsymbols in ppu supported
  1461. * asmsymbollist global is removed and moved into a new class
  1462. tasmlibrarydata that will hold the info of a .a file which
  1463. corresponds with a single module. Added librarydata to tmodule
  1464. to keep the library info stored for the module. In the future the
  1465. objectfiles will also be stored to the tasmlibrarydata class
  1466. * all getlabel/newasmsymbol and friends are moved to the new class
  1467. Revision 1.36 2002/07/26 21:15:46 florian
  1468. * rewrote the system handling
  1469. Revision 1.35 2002/07/01 18:46:35 peter
  1470. * internal linker
  1471. * reorganized aasm layer
  1472. Revision 1.34 2002/05/18 13:34:27 peter
  1473. * readded missing revisions
  1474. Revision 1.33 2002/05/16 19:46:53 carl
  1475. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1476. + try to fix temp allocation (still in ifdef)
  1477. + generic constructor calls
  1478. + start of tassembler / tmodulebase class cleanup
  1479. Revision 1.31 2002/04/22 18:19:22 carl
  1480. - remove use_bound_instruction field
  1481. Revision 1.30 2002/04/21 15:43:58 carl
  1482. * change stack size to 256K
  1483. Revision 1.29 2002/04/20 21:43:18 carl
  1484. * fix stack size for some targets
  1485. + add offset to parameters from frame pointer info.
  1486. - remove some unused stuff
  1487. Revision 1.28 2002/04/15 19:16:57 carl
  1488. - remove size_of_pointer field
  1489. Revision 1.27 2002/04/05 17:49:09 carl
  1490. * fix compilation problems
  1491. * fix range check error
  1492. Revision 1.26 2002/04/04 19:06:14 peter
  1493. * removed unused units
  1494. * use tlocation.size in cg.a_*loc*() routines
  1495. Revision 1.25 2002/04/04 18:25:30 carl
  1496. + added wdosx patch from Pavel
  1497. Revision 1.24 2002/04/02 17:11:39 peter
  1498. * tlocation,treference update
  1499. * LOC_CONSTANT added for better constant handling
  1500. * secondadd splitted in multiple routines
  1501. * location_force_reg added for loading a location to a register
  1502. of a specified size
  1503. * secondassignment parses now first the right and then the left node
  1504. (this is compatible with Kylix). This saves a lot of push/pop especially
  1505. with string operations
  1506. * adapted some routines to use the new cg methods
  1507. Revision 1.23 2002/01/29 21:27:34 peter
  1508. * default alignment changed to 4 bytes for locals and static const,var
  1509. Revision 1.22 2002/01/19 11:53:07 peter
  1510. * fixed managledname
  1511. }