t_win32.pas 54 KB

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