t_win32.pas 60 KB

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