t_win.pas 56 KB

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