t_win32.pas 58 KB

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