t_win32.pas 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720
  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 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 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('+GetShortName(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('+GetShortName(HPath.Str)+')');
  832. HPath:=TStringListItem(HPath.Next);
  833. end;
  834. { add objectfiles, start with prt0 always }
  835. LinkRes.Add('INPUT(');
  836. if isdll then
  837. LinkRes.AddFileName(GetShortName(FindObjectFile('wdllprt0','')))
  838. else
  839. LinkRes.AddFileName(GetShortName(FindObjectFile('wprt0','')));
  840. if cs_profile in aktmoduleswitches then
  841. LinkRes.AddFileName(GetShortName(FindObjectFile('mcount','')));
  842. while not ObjectFiles.Empty do
  843. begin
  844. s:=ObjectFiles.GetFirst;
  845. if s<>'' then
  846. LinkRes.AddFileName(GetShortName(s));
  847. end;
  848. { add libaries required for profiling }
  849. if cs_profile in aktmoduleswitches then
  850. begin
  851. LinkRes.Add('-lgmon');
  852. LinkRes.Add('-lkernel32');
  853. LinkRes.Add('-lmsvcrt');
  854. end;
  855. LinkRes.Add(')');
  856. { Write staticlibraries }
  857. if not StaticLibFiles.Empty then
  858. begin
  859. LinkRes.Add('GROUP(');
  860. While not StaticLibFiles.Empty do
  861. begin
  862. S:=StaticLibFiles.GetFirst;
  863. LinkRes.AddFileName(GetShortName(s));
  864. end;
  865. LinkRes.Add(')');
  866. end;
  867. { Write sharedlibraries }
  868. if not SharedLibFiles.Empty then
  869. begin
  870. LinkRes.Add('INPUT(') ;
  871. While not SharedLibFiles.Empty do
  872. begin
  873. S:=SharedLibFiles.GetFirst;
  874. if FindLibraryFile(s,target_info.staticClibprefix,target_info.staticClibext,s2) then
  875. begin
  876. LinkRes.Add(GetShortName(s2));
  877. continue;
  878. end;
  879. if pos(target_info.sharedlibprefix,s)=1 then
  880. s:=copy(s,length(target_info.sharedlibprefix)+1,255);
  881. if s<>'c' then
  882. begin
  883. i:=Pos(target_info.sharedlibext,S);
  884. if i>0 then
  885. Delete(S,i,255);
  886. LinkRes.Add('-l'+s);
  887. end
  888. else
  889. begin
  890. LinkRes.Add('-l'+s);
  891. linklibc:=true;
  892. end;
  893. end;
  894. { be sure that libc is the last lib }
  895. if linklibc then
  896. LinkRes.Add('-lc');
  897. LinkRes.Add(')');
  898. end;
  899. { Write and Close response }
  900. linkres.writetodisk;
  901. LinkRes.Free;
  902. WriteResponseFile:=True;
  903. end;
  904. function TLinkerWin32.MakeExecutable:boolean;
  905. var
  906. binstr,
  907. cmdstr : string;
  908. success : boolean;
  909. i : longint;
  910. AsBinStr : string[80];
  911. StripStr,
  912. RelocStr,
  913. AppTypeStr,
  914. ImageBaseStr : string[40];
  915. begin
  916. if not(cs_link_extern in aktglobalswitches) then
  917. Message1(exec_i_linking,current_module.exefilename^);
  918. { Create some replacements }
  919. RelocStr:='';
  920. AppTypeStr:='';
  921. ImageBaseStr:='';
  922. StripStr:='';
  923. FindExe('asw',AsBinStr);
  924. if RelocSection then
  925. { Using short form to avoid problems with 128 char limitation under Dos. }
  926. RelocStr:='-b base.$$$';
  927. if apptype=app_gui then
  928. AppTypeStr:='--subsystem windows';
  929. if assigned(DLLImageBase) then
  930. ImageBaseStr:='--image-base=0x'+DLLImageBase^;
  931. if (cs_link_strip in aktglobalswitches) then
  932. StripStr:='-s';
  933. { Write used files and libraries }
  934. WriteResponseFile(false);
  935. { Call linker }
  936. success:=false;
  937. for i:=1 to 3 do
  938. begin
  939. SplitBinCmd(Info.ExeCmd[i],binstr,cmdstr);
  940. if binstr<>'' then
  941. begin
  942. Replace(cmdstr,'$EXE',maybequoted(current_module.exefilename^));
  943. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  944. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  945. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  946. Replace(cmdstr,'$ASBIN',AsbinStr);
  947. Replace(cmdstr,'$RELOC',RelocStr);
  948. Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
  949. Replace(cmdstr,'$STRIP',StripStr);
  950. if not DefFile.Empty {and UseDefFileForExport} then
  951. begin
  952. DefFile.WriteFile;
  953. Replace(cmdstr,'$DEF','-d '+maybequoted(deffile.fname));
  954. end
  955. else
  956. Replace(cmdstr,'$DEF','');
  957. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
  958. if not success then
  959. break;
  960. end;
  961. end;
  962. { Post process }
  963. if success then
  964. success:=PostProcessExecutable(current_module.exefilename^,false);
  965. { Remove ReponseFile }
  966. if (success) and not(cs_link_extern in aktglobalswitches) then
  967. begin
  968. RemoveFile(outputexedir+Info.ResName);
  969. RemoveFile('base.$$$');
  970. RemoveFile('exp.$$$');
  971. RemoveFile('deffile.$$$');
  972. end;
  973. MakeExecutable:=success; { otherwise a recursive call to link method }
  974. end;
  975. Function TLinkerWin32.MakeSharedLibrary:boolean;
  976. var
  977. binstr,
  978. cmdstr : string;
  979. success : boolean;
  980. i : longint;
  981. AsBinStr : string[80];
  982. StripStr,
  983. RelocStr,
  984. AppTypeStr,
  985. ImageBaseStr : string[40];
  986. begin
  987. MakeSharedLibrary:=false;
  988. if not(cs_link_extern in aktglobalswitches) then
  989. Message1(exec_i_linking,current_module.sharedlibfilename^);
  990. { Create some replacements }
  991. RelocStr:='';
  992. AppTypeStr:='';
  993. ImageBaseStr:='';
  994. StripStr:='';
  995. FindExe('asw',AsBinStr);
  996. if RelocSection then
  997. { Using short form to avoid problems with 128 char limitation under Dos. }
  998. RelocStr:='-b base.$$$';
  999. if apptype=app_gui then
  1000. AppTypeStr:='--subsystem windows';
  1001. if assigned(DLLImageBase) then
  1002. ImageBaseStr:='--image-base=0x'+DLLImageBase^;
  1003. if (cs_link_strip in aktglobalswitches) then
  1004. StripStr:='-s';
  1005. { Write used files and libraries }
  1006. WriteResponseFile(true);
  1007. { Call linker }
  1008. success:=false;
  1009. for i:=1 to 3 do
  1010. begin
  1011. SplitBinCmd(Info.DllCmd[i],binstr,cmdstr);
  1012. if binstr<>'' then
  1013. begin
  1014. Replace(cmdstr,'$EXE',maybequoted(current_module.sharedlibfilename^));
  1015. Replace(cmdstr,'$OPT',Info.ExtraOptions);
  1016. Replace(cmdstr,'$RES',maybequoted(outputexedir+Info.ResName));
  1017. Replace(cmdstr,'$APPTYPE',AppTypeStr);
  1018. Replace(cmdstr,'$ASBIN',AsbinStr);
  1019. Replace(cmdstr,'$RELOC',RelocStr);
  1020. Replace(cmdstr,'$IMAGEBASE',ImageBaseStr);
  1021. Replace(cmdstr,'$STRIP',StripStr);
  1022. if not DefFile.Empty {and UseDefFileForExport} then
  1023. begin
  1024. DefFile.WriteFile;
  1025. Replace(cmdstr,'$DEF','-d '+maybequoted(deffile.fname));
  1026. end
  1027. else
  1028. Replace(cmdstr,'$DEF','');
  1029. success:=DoExec(FindUtil(binstr),cmdstr,(i=1),false);
  1030. if not success then
  1031. break;
  1032. end;
  1033. end;
  1034. { Post process }
  1035. if success then
  1036. success:=PostProcessExecutable(current_module.sharedlibfilename^,true);
  1037. { Remove ReponseFile }
  1038. if (success) and not(cs_link_extern in aktglobalswitches) then
  1039. begin
  1040. RemoveFile(outputexedir+Info.ResName);
  1041. RemoveFile('base.$$$');
  1042. RemoveFile('exp.$$$');
  1043. end;
  1044. MakeSharedLibrary:=success; { otherwise a recursive call to link method }
  1045. end;
  1046. function tlinkerwin32.postprocessexecutable(const fn : string;isdll:boolean):boolean;
  1047. type
  1048. tdosheader = packed record
  1049. e_magic : word;
  1050. e_cblp : word;
  1051. e_cp : word;
  1052. e_crlc : word;
  1053. e_cparhdr : word;
  1054. e_minalloc : word;
  1055. e_maxalloc : word;
  1056. e_ss : word;
  1057. e_sp : word;
  1058. e_csum : word;
  1059. e_ip : word;
  1060. e_cs : word;
  1061. e_lfarlc : word;
  1062. e_ovno : word;
  1063. e_res : array[0..3] of word;
  1064. e_oemid : word;
  1065. e_oeminfo : word;
  1066. e_res2 : array[0..9] of word;
  1067. e_lfanew : longint;
  1068. end;
  1069. tpeheader = packed record
  1070. PEMagic : array[0..3] of char;
  1071. Machine : word;
  1072. NumberOfSections : word;
  1073. TimeDateStamp : longint;
  1074. PointerToSymbolTable : longint;
  1075. NumberOfSymbols : longint;
  1076. SizeOfOptionalHeader : word;
  1077. Characteristics : word;
  1078. Magic : word;
  1079. MajorLinkerVersion : byte;
  1080. MinorLinkerVersion : byte;
  1081. SizeOfCode : longint;
  1082. SizeOfInitializedData : longint;
  1083. SizeOfUninitializedData : longint;
  1084. AddressOfEntryPoint : longint;
  1085. BaseOfCode : longint;
  1086. BaseOfData : longint;
  1087. ImageBase : longint;
  1088. SectionAlignment : longint;
  1089. FileAlignment : longint;
  1090. MajorOperatingSystemVersion : word;
  1091. MinorOperatingSystemVersion : word;
  1092. MajorImageVersion : word;
  1093. MinorImageVersion : word;
  1094. MajorSubsystemVersion : word;
  1095. MinorSubsystemVersion : word;
  1096. Reserved1 : longint;
  1097. SizeOfImage : longint;
  1098. SizeOfHeaders : longint;
  1099. CheckSum : longint;
  1100. Subsystem : word;
  1101. DllCharacteristics : word;
  1102. SizeOfStackReserve : longint;
  1103. SizeOfStackCommit : longint;
  1104. SizeOfHeapReserve : longint;
  1105. SizeOfHeapCommit : longint;
  1106. LoaderFlags : longint;
  1107. NumberOfRvaAndSizes : longint;
  1108. DataDirectory : array[1..$80] of byte;
  1109. end;
  1110. tcoffsechdr=packed record
  1111. name : array[0..7] of char;
  1112. vsize : longint;
  1113. rvaofs : longint;
  1114. datalen : longint;
  1115. datapos : longint;
  1116. relocpos : longint;
  1117. lineno1 : longint;
  1118. nrelocs : word;
  1119. lineno2 : word;
  1120. flags : longint;
  1121. end;
  1122. psecfill=^TSecfill;
  1123. TSecfill=record
  1124. fillpos,
  1125. fillsize : longint;
  1126. next : psecfill;
  1127. end;
  1128. var
  1129. f : file;
  1130. cmdstr : string;
  1131. dosheader : tdosheader;
  1132. peheader : tpeheader;
  1133. firstsecpos,
  1134. maxfillsize,
  1135. l,peheaderpos : longint;
  1136. coffsec : tcoffsechdr;
  1137. secroot,hsecroot : psecfill;
  1138. zerobuf : pointer;
  1139. begin
  1140. postprocessexecutable:=false;
  1141. { when -s is used or it's a dll then quit }
  1142. if (cs_link_extern in aktglobalswitches) then
  1143. begin
  1144. case apptype of
  1145. app_gui :
  1146. cmdstr:='--subsystem gui';
  1147. app_cui :
  1148. cmdstr:='--subsystem console';
  1149. end;
  1150. if dllversion<>'' then
  1151. cmdstr:=cmdstr+' --version '+dllversion;
  1152. cmdstr:=cmdstr+' --input '+fn;
  1153. cmdstr:=cmdstr+' --stack '+tostr(stacksize);
  1154. DoExec(FindUtil('postw32'),cmdstr,false,false);
  1155. postprocessexecutable:=true;
  1156. exit;
  1157. end;
  1158. { open file }
  1159. assign(f,fn);
  1160. {$I-}
  1161. reset(f,1);
  1162. if ioresult<>0 then
  1163. Message1(execinfo_f_cant_open_executable,fn);
  1164. { read headers }
  1165. blockread(f,dosheader,sizeof(tdosheader));
  1166. peheaderpos:=dosheader.e_lfanew;
  1167. seek(f,peheaderpos);
  1168. blockread(f,peheader,sizeof(tpeheader));
  1169. { write info }
  1170. Message1(execinfo_x_codesize,tostr(peheader.SizeOfCode));
  1171. Message1(execinfo_x_initdatasize,tostr(peheader.SizeOfInitializedData));
  1172. Message1(execinfo_x_uninitdatasize,tostr(peheader.SizeOfUninitializedData));
  1173. { change stack size (PM) }
  1174. { I am not sure that the default value is adequate !! }
  1175. peheader.SizeOfStackReserve:=stacksize;
  1176. { change the header }
  1177. { sub system }
  1178. { gui=2 }
  1179. { cui=3 }
  1180. case apptype of
  1181. app_gui :
  1182. peheader.Subsystem:=2;
  1183. app_cui :
  1184. peheader.Subsystem:=3;
  1185. end;
  1186. if dllversion<>'' then
  1187. begin
  1188. peheader.MajorImageVersion:=dllmajor;
  1189. peheader.MinorImageVersion:=dllminor;
  1190. end;
  1191. { reset timestamp }
  1192. peheader.TimeDateStamp:=0;
  1193. { write header back }
  1194. seek(f,peheaderpos);
  1195. blockwrite(f,peheader,sizeof(tpeheader));
  1196. if ioresult<>0 then
  1197. Message1(execinfo_f_cant_process_executable,fn);
  1198. seek(f,peheaderpos);
  1199. blockread(f,peheader,sizeof(tpeheader));
  1200. { write the value after the change }
  1201. Message1(execinfo_x_stackreserve,tostr(peheader.SizeOfStackReserve));
  1202. Message1(execinfo_x_stackcommit,tostr(peheader.SizeOfStackCommit));
  1203. { read section info }
  1204. maxfillsize:=0;
  1205. firstsecpos:=0;
  1206. secroot:=nil;
  1207. for l:=1 to peheader.NumberOfSections do
  1208. begin
  1209. blockread(f,coffsec,sizeof(tcoffsechdr));
  1210. if coffsec.datapos>0 then
  1211. begin
  1212. if secroot=nil then
  1213. firstsecpos:=coffsec.datapos;
  1214. new(hsecroot);
  1215. hsecroot^.fillpos:=coffsec.datapos+coffsec.vsize;
  1216. hsecroot^.fillsize:=coffsec.datalen-coffsec.vsize;
  1217. hsecroot^.next:=secroot;
  1218. secroot:=hsecroot;
  1219. if secroot^.fillsize>maxfillsize then
  1220. maxfillsize:=secroot^.fillsize;
  1221. end;
  1222. end;
  1223. if firstsecpos>0 then
  1224. begin
  1225. l:=firstsecpos-filepos(f);
  1226. if l>maxfillsize then
  1227. maxfillsize:=l;
  1228. end
  1229. else
  1230. l:=0;
  1231. { get zero buffer }
  1232. getmem(zerobuf,maxfillsize);
  1233. fillchar(zerobuf^,maxfillsize,0);
  1234. { zero from sectioninfo until first section }
  1235. blockwrite(f,zerobuf^,l);
  1236. { zero section alignments }
  1237. while assigned(secroot) do
  1238. begin
  1239. seek(f,secroot^.fillpos);
  1240. blockwrite(f,zerobuf^,secroot^.fillsize);
  1241. hsecroot:=secroot;
  1242. secroot:=secroot^.next;
  1243. dispose(hsecroot);
  1244. end;
  1245. freemem(zerobuf,maxfillsize);
  1246. close(f);
  1247. {$I+}
  1248. if ioresult<>0 then;
  1249. postprocessexecutable:=true;
  1250. end;
  1251. {****************************************************************************
  1252. TDLLScannerWin32
  1253. ****************************************************************************}
  1254. procedure tDLLScannerWin32.GetDefExt(var N:longint;var P:pStr4);
  1255. begin
  1256. N:=sizeof(DefaultDLLExtensions)div sizeof(DefaultDLLExtensions[1]);
  1257. pointer(P):=@DefaultDLLExtensions;
  1258. end;
  1259. function tDLLScannerWin32.DOSstubOK(var x:cardinal):boolean;
  1260. begin
  1261. blockread(f,TheWord,2,loaded);
  1262. if loaded<>2 then
  1263. DOSstubOK:=false
  1264. else
  1265. begin
  1266. DOSstubOK:=(TheWord='MZ');
  1267. seek(f,$3C);
  1268. blockread(f,x,4,loaded);
  1269. if(loaded<>4)or(longint(x)>filesize(f))then
  1270. DOSstubOK:=false;
  1271. end;
  1272. end;
  1273. function TDLLScannerWin32.FindDLL(const s:string;var founddll:string):boolean;
  1274. var
  1275. sysdir : string;
  1276. Found : boolean;
  1277. begin
  1278. Found:=false;
  1279. { Look for DLL in:
  1280. 1. Current dir
  1281. 2. Library Path
  1282. 3. windir,windir/system,windir/system32 }
  1283. Found:=FindFile(s,'.'+source_info.DirSep,founddll);
  1284. if (not found) then
  1285. Found:=librarysearchpath.FindFile(s,founddll);
  1286. if (not found) then
  1287. begin
  1288. sysdir:=FixPath(GetEnv('windir'),false);
  1289. Found:=FindFile(s,sysdir+';'+sysdir+'system'+source_info.DirSep+';'+sysdir+'system32'+source_info.DirSep,founddll);
  1290. end;
  1291. if (not found) then
  1292. begin
  1293. message1(exec_w_libfile_not_found,s);
  1294. FoundDll:=s;
  1295. end;
  1296. FindDll:=Found;
  1297. end;
  1298. function tDLLScannerWin32.ExtractDllName(Const Name : string) : string;
  1299. var n : string;
  1300. begin
  1301. n:=Upper(SplitExtension(Name));
  1302. if (n='.DLL') or (n='.DRV') or (n='.EXE') then
  1303. ExtractDllName:=Name
  1304. else
  1305. ExtractDllName:=Name+target_info.sharedlibext;
  1306. end;
  1307. function tDLLScannerWin32.isSuitableFileType(x:cardinal):longbool;
  1308. begin
  1309. seek(f,x);
  1310. blockread(f,TheWord,2,loaded);
  1311. isSuitableFileType:=(loaded=2)and(TheWord='PE');
  1312. end;
  1313. function tDLLScannerWin32.GetEdata(HeaderEntry:cardinal):longbool;
  1314. type
  1315. TObjInfo=packed record
  1316. ObjName:array[0..7]of char;
  1317. VirtSize,
  1318. VirtAddr,
  1319. RawSize,
  1320. RawOffset,
  1321. Reloc,
  1322. LineNum:cardinal;
  1323. RelCount,
  1324. LineCount:word;
  1325. flags:cardinal;
  1326. end;
  1327. var
  1328. i:cardinal;
  1329. ObjOfs:cardinal;
  1330. Obj:TObjInfo;
  1331. APE_obj,APE_Optsize:word;
  1332. ExportRVA:cardinal;
  1333. delta:cardinal;
  1334. const
  1335. IMAGE_SCN_CNT_CODE=$00000020;
  1336. var
  1337. _d:dirstr;
  1338. _n:namestr;
  1339. _e:extstr;
  1340. function isUsedFunction(name:pchar):longbool;
  1341. var
  1342. hp:tExternalsItem;
  1343. begin
  1344. isUsedFunction:=false;
  1345. hp:=tExternalsItem(current_module.Externals.first);
  1346. while assigned(hp)do
  1347. begin
  1348. if(assigned(hp.data))and(not hp.found)then
  1349. if hp.data^=StrPas(name)then
  1350. begin
  1351. isUsedFunction:=true;
  1352. hp.found:=true;
  1353. exit;
  1354. end;
  1355. hp:=tExternalsItem(hp.next);
  1356. end;
  1357. end;
  1358. procedure Store(index:cardinal;name:pchar;isData:longbool);
  1359. begin
  1360. if not isUsedFunction(name)then
  1361. exit;
  1362. if not(current_module.uses_imports) then
  1363. begin
  1364. current_module.uses_imports:=true;
  1365. importlib.preparelib(current_module.modulename^);
  1366. end;
  1367. if IsData then
  1368. timportlibwin32(importlib).importvariable_str(name,_n,name)
  1369. else
  1370. importlib.importprocedure(name,_n,index,name);
  1371. end;
  1372. procedure ProcessEdata;
  1373. type
  1374. a8=array[0..7]of char;
  1375. function GetSectionName(rva:cardinal;var Flags:cardinal):a8;
  1376. var
  1377. i:cardinal;
  1378. LocObjOfs:cardinal;
  1379. LocObj:TObjInfo;
  1380. begin
  1381. GetSectionName:='';
  1382. Flags:=0;
  1383. LocObjOfs:=APE_OptSize+HeaderOffset+24;
  1384. for i:=1 to APE_obj do
  1385. begin
  1386. seek(f,LocObjOfs);
  1387. blockread(f,LocObj,sizeof(LocObj));
  1388. if(rva>=LocObj.VirtAddr)and(rva<=LocObj.VirtAddr+LocObj.RawSize)then
  1389. begin
  1390. GetSectionName:=a8(LocObj.ObjName);
  1391. Flags:=LocObj.flags;
  1392. end;
  1393. end;
  1394. end;
  1395. var
  1396. j,Fl:cardinal;
  1397. ulongval,procEntry:cardinal;
  1398. Ordinal:word;
  1399. isData:longbool;
  1400. ExpDir:packed record
  1401. flag,
  1402. stamp:cardinal;
  1403. Major,
  1404. Minor:word;
  1405. Name,
  1406. Base,
  1407. NumFuncs,
  1408. NumNames,
  1409. AddrFuncs,
  1410. AddrNames,
  1411. AddrOrds:cardinal;
  1412. end;
  1413. begin
  1414. with Obj do
  1415. begin
  1416. seek(f,RawOffset+delta);
  1417. blockread(f,ExpDir,sizeof(ExpDir));
  1418. fsplit(impname,_d,_n,_e);
  1419. for j:=0 to pred(ExpDir.NumNames)do
  1420. begin
  1421. seek(f,RawOffset-VirtAddr+ExpDir.AddrOrds+j*2);
  1422. blockread(f,Ordinal,2);
  1423. seek(f,RawOffset-VirtAddr+ExpDir.AddrFuncs+cardinal(Ordinal)*4);
  1424. blockread(f,ProcEntry,4);
  1425. seek(f,RawOffset-VirtAddr+ExpDir.AddrNames+j*4);
  1426. blockread(f,ulongval,4);
  1427. seek(f,RawOffset-VirtAddr+ulongval);
  1428. blockread(f,cstring,sizeof(cstring));
  1429. isData:=GetSectionName(procentry,Fl)='';
  1430. if not isData then
  1431. isData:=Fl and IMAGE_SCN_CNT_CODE<>IMAGE_SCN_CNT_CODE;
  1432. Store(succ(Ordinal),cstring,isData);
  1433. end;
  1434. end;
  1435. end;
  1436. begin
  1437. GetEdata:=false;
  1438. seek(f,HeaderEntry+120);
  1439. blockread(f,ExportRVA,4);
  1440. seek(f,HeaderEntry+6);
  1441. blockread(f,APE_Obj,2);
  1442. seek(f,HeaderEntry+20);
  1443. blockread(f,APE_OptSize,2);
  1444. ObjOfs:=APE_OptSize+HeaderOffset+24;
  1445. for i:=1 to APE_obj do
  1446. begin
  1447. seek(f,ObjOfs);
  1448. blockread(f,Obj,sizeof(Obj));
  1449. inc(ObjOfs,sizeof(Obj));
  1450. with Obj do
  1451. if(VirtAddr<=ExportRva)and(ExportRva<VirtAddr+VirtSize)then
  1452. begin
  1453. delta:=ExportRva-VirtAddr;
  1454. ProcessEdata;
  1455. GetEdata:=true;
  1456. end;
  1457. end;
  1458. end;
  1459. function tDLLScannerWin32.scan(const binname:string):longbool;
  1460. var
  1461. OldFileMode:longint;
  1462. foundimp : string;
  1463. NN:longint;PP:pStr4;
  1464. begin
  1465. Scan:=false;
  1466. { is there already an import library the we will use that one }
  1467. if FindLibraryFile(binname,target_info.staticClibprefix,target_info.staticClibext,foundimp) then
  1468. exit;
  1469. { check if we can find the dll }
  1470. GetDefExt(NN,PP);
  1471. if not FindDll(DLLName(binname,NN,PP),impname) then
  1472. exit;
  1473. { read the dll file }
  1474. assign(f,impname);
  1475. OldFileMode:=filemode;
  1476. filemode:=0;
  1477. reset(f,1);
  1478. filemode:=OldFileMode;
  1479. if not DOSstubOK(HeaderOffset)then
  1480. scan:=false
  1481. else if not isSuitableFileType(HeaderOffset)then
  1482. scan:=false
  1483. else
  1484. scan:=GetEdata(HeaderOffset);
  1485. close(f);
  1486. end;
  1487. {*****************************************************************************
  1488. Initialize
  1489. *****************************************************************************}
  1490. initialization
  1491. {$ifdef i386}
  1492. RegisterExternalLinker(system_i386_win32_info,TLinkerWin32);
  1493. RegisterImport(system_i386_win32,TImportLibWin32);
  1494. RegisterExport(system_i386_win32,TExportLibWin32);
  1495. RegisterDLLScanner(system_i386_win32,TDLLScannerWin32);
  1496. RegisterAr(ar_gnu_arw_info);
  1497. RegisterRes(res_gnu_windres_info);
  1498. RegisterTarget(system_i386_win32_info);
  1499. {$endif i386}
  1500. end.
  1501. {
  1502. $Log$
  1503. Revision 1.4 2002-11-15 01:59:02 peter
  1504. * merged changes from 1.0.7 up to 04-11
  1505. - -V option for generating bug report tracing
  1506. - more tracing for option parsing
  1507. - errors for cdecl and high()
  1508. - win32 import stabs
  1509. - win32 records<=8 are returned in eax:edx (turned off by default)
  1510. - heaptrc update
  1511. - more info for temp management in .s file with EXTDEBUG
  1512. Revision 1.3 2002/10/05 12:43:29 carl
  1513. * fixes for Delphi 6 compilation
  1514. (warning : Some features do not work under Delphi)
  1515. Revision 1.2 2002/09/09 17:34:17 peter
  1516. * tdicationary.replace added to replace and item in a dictionary. This
  1517. is only allowed for the same name
  1518. * varsyms are inserted in symtable before the types are parsed. This
  1519. fixes the long standing "var longint : longint" bug
  1520. - consume_idlist and idstringlist removed. The loops are inserted
  1521. at the callers place and uses the symtable for duplicate id checking
  1522. Revision 1.1 2002/09/06 15:03:50 carl
  1523. * moved files to systems directory
  1524. Revision 1.40 2002/09/03 16:26:29 daniel
  1525. * Make Tprocdef.defs protected
  1526. Revision 1.39 2002/08/12 15:08:44 carl
  1527. + stab register indexes for powerpc (moved from gdb to cpubase)
  1528. + tprocessor enumeration moved to cpuinfo
  1529. + linker in target_info is now a class
  1530. * many many updates for m68k (will soon start to compile)
  1531. - removed some ifdef or correct them for correct cpu
  1532. Revision 1.38 2002/08/11 14:32:32 peter
  1533. * renamed current_library to objectlibrary
  1534. Revision 1.37 2002/08/11 13:24:20 peter
  1535. * saving of asmsymbols in ppu supported
  1536. * asmsymbollist global is removed and moved into a new class
  1537. tasmlibrarydata that will hold the info of a .a file which
  1538. corresponds with a single module. Added librarydata to tmodule
  1539. to keep the library info stored for the module. In the future the
  1540. objectfiles will also be stored to the tasmlibrarydata class
  1541. * all getlabel/newasmsymbol and friends are moved to the new class
  1542. Revision 1.36 2002/07/26 21:15:46 florian
  1543. * rewrote the system handling
  1544. Revision 1.35 2002/07/01 18:46:35 peter
  1545. * internal linker
  1546. * reorganized aasm layer
  1547. Revision 1.34 2002/05/18 13:34:27 peter
  1548. * readded missing revisions
  1549. Revision 1.33 2002/05/16 19:46:53 carl
  1550. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1551. + try to fix temp allocation (still in ifdef)
  1552. + generic constructor calls
  1553. + start of tassembler / tmodulebase class cleanup
  1554. Revision 1.31 2002/04/22 18:19:22 carl
  1555. - remove use_bound_instruction field
  1556. Revision 1.30 2002/04/21 15:43:58 carl
  1557. * change stack size to 256K
  1558. Revision 1.29 2002/04/20 21:43:18 carl
  1559. * fix stack size for some targets
  1560. + add offset to parameters from frame pointer info.
  1561. - remove some unused stuff
  1562. Revision 1.28 2002/04/15 19:16:57 carl
  1563. - remove size_of_pointer field
  1564. Revision 1.27 2002/04/05 17:49:09 carl
  1565. * fix compilation problems
  1566. * fix range check error
  1567. Revision 1.26 2002/04/04 19:06:14 peter
  1568. * removed unused units
  1569. * use tlocation.size in cg.a_*loc*() routines
  1570. Revision 1.25 2002/04/04 18:25:30 carl
  1571. + added wdosx patch from Pavel
  1572. Revision 1.24 2002/04/02 17:11:39 peter
  1573. * tlocation,treference update
  1574. * LOC_CONSTANT added for better constant handling
  1575. * secondadd splitted in multiple routines
  1576. * location_force_reg added for loading a location to a register
  1577. of a specified size
  1578. * secondassignment parses now first the right and then the left node
  1579. (this is compatible with Kylix). This saves a lot of push/pop especially
  1580. with string operations
  1581. * adapted some routines to use the new cg methods
  1582. Revision 1.23 2002/01/29 21:27:34 peter
  1583. * default alignment changed to 4 bytes for locals and static const,var
  1584. Revision 1.22 2002/01/19 11:53:07 peter
  1585. * fixed managledname
  1586. }