t_win32.pas 54 KB

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