t_win32.pas 58 KB

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