t_win32.pas 59 KB

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