t_win32.pas 57 KB

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