t_win32.pas 59 KB

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