t_win32.pas 55 KB

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