t_win32.pas 57 KB

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