t_win32.pas 59 KB

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