PageRenderTime 131ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 2ms

/src/sys/dotnet/perwapi/PERWAPI.cs

https://bitbucket.org/bedlaczech/fan-1.0
C# | 13234 lines | 8246 code | 1818 blank | 3170 comment | 1527 complexity | 6cf790997bbe38881aabbe059f2403ff MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. /*
  2. * PERWAPI - An API for Reading and Writing PE Files
  3. *
  4. * Copyright (c) Diane Corney, Queensland University of Technology, 2004.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the PERWAPI Copyright as included with this
  8. * distribution in the file PERWAPIcopyright.rtf.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY as is explained in the copyright notice.
  12. *
  13. * The author may be contacted at d.corney@qut.edu.au
  14. *
  15. * Version Date: 26/01/07
  16. *
  17. * Contributions Made By:
  18. *
  19. * Douglas Stockwell - Developed support for PDB files.
  20. * Andrew Bacon - Integrated PDB file support and developed automatic
  21. * stack depth calculations.
  22. *
  23. * Placed in Subversion repository by John Gough on 2-Mar-2007
  24. *
  25. */
  26. using System;
  27. using System.IO;
  28. using System.Collections;
  29. using SCG = System.Collections.Generic;
  30. using System.Text;
  31. using System.Security.Permissions;
  32. using System.Diagnostics;
  33. using System.Diagnostics.SymbolStore;
  34. using System.Runtime.InteropServices;
  35. using QUT;
  36. namespace PERWAPI {
  37. /// <summary>
  38. /// Diagnostic
  39. /// </summary>
  40. public class Diag {
  41. /// <summary>
  42. /// Flag for diagnostic output.
  43. /// </summary>
  44. public static bool DiagOn = false;
  45. }
  46. /// <summary>
  47. /// Facilities for outputting hexadecimal strings
  48. /// </summary>
  49. public class Hex {
  50. readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
  51. '8','9','A','B','C','D','E','F'};
  52. readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
  53. readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
  54. 0x0000000000FF0000, 0x00000000FF000000,
  55. 0x000000FF00000000, 0x0000FF0000000000,
  56. 0x00FF000000000000, 0xFF00000000000000 };
  57. readonly static uint nibble0Mask = 0x0000000F;
  58. readonly static uint nibble1Mask = 0x000000F0;
  59. /// <summary>
  60. /// Derives a hexademical string for a byte value
  61. /// </summary>
  62. /// <param name="b">the byte value</param>
  63. /// <returns>hex string for the byte value</returns>
  64. public static String Byte(int b) {
  65. char[] str = new char[2];
  66. uint num = (uint)b;
  67. uint b1 = num & nibble0Mask;
  68. uint b2 = (num & nibble1Mask) >> 4;
  69. str[0] = hexDigit[b2];
  70. str[1] = hexDigit[b1];
  71. return new String(str);
  72. }
  73. /// <summary>
  74. /// Derives a hexademical string for a short value
  75. /// </summary>
  76. /// <param name="b">the short value</param>
  77. /// <returns>hex string for the short value</returns>
  78. public static String Short(int b) {
  79. char[] str = new char[4];
  80. uint num1 = (uint)b & iByteMask[0];
  81. uint num2 = ((uint)b & iByteMask[1]) >> 8;
  82. uint b1 = num1 & nibble0Mask;
  83. uint b2 = (num1 & nibble1Mask) >> 4;
  84. uint b3 = num2 & nibble0Mask;
  85. uint b4 = (num2 & nibble1Mask) >> 4;
  86. str[0] = hexDigit[b4];
  87. str[1] = hexDigit[b3];
  88. str[2] = hexDigit[b2];
  89. str[3] = hexDigit[b1];
  90. return new String(str);
  91. }
  92. /// <summary>
  93. /// Derives a hexademical string for an int value
  94. /// </summary>
  95. /// <param name="val">the int value</param>
  96. /// <returns>hex string for the int value</returns>
  97. public static String Int(int val) {
  98. char[] str = new char[8];
  99. uint num = (uint)val;
  100. int strIx = 7;
  101. for (int i=0; i < iByteMask.Length; i++) {
  102. uint b = num & iByteMask[i];
  103. b >>= (i*8);
  104. uint b1 = b & nibble0Mask;
  105. uint b2 = (b & nibble1Mask) >> 4;
  106. str[strIx--] = hexDigit[b1];
  107. str[strIx--] = hexDigit[b2];
  108. }
  109. return new String(str);
  110. }
  111. /// <summary>
  112. /// Derives a hexademical string for an unsigned int value
  113. /// </summary>
  114. /// <param name="num">the unsigned int value</param>
  115. /// <returns>hex string for the unsigned int value</returns>
  116. public static String Int(uint num) {
  117. char[] str = new char[8];
  118. int strIx = 7;
  119. for (int i=0; i < iByteMask.Length; i++) {
  120. uint b = num & iByteMask[i];
  121. b >>= (i*8);
  122. uint b1 = b & nibble0Mask;
  123. uint b2 = (b & nibble1Mask) >> 4;
  124. str[strIx--] = hexDigit[b1];
  125. str[strIx--] = hexDigit[b2];
  126. }
  127. return new String(str);
  128. }
  129. /// <summary>
  130. /// Derives a hexademical string for a long value
  131. /// </summary>
  132. /// <param name="lnum">the long value</param>
  133. /// <returns>hex string for the long value</returns>
  134. public static String Long(long lnum) {
  135. ulong num = (ulong)lnum;
  136. return Long(num);
  137. }
  138. /// <summary>
  139. /// Derives a hexademical string for an unsigned long value
  140. /// </summary>
  141. /// <param name="num">the unsigned long value</param>
  142. /// <returns>hex string for the unsigned long value</returns>
  143. public static String Long(ulong num) {
  144. char[] str = new char[16];
  145. int strIx = 15;
  146. for (int i=0; i < lByteMask.Length; i++) {
  147. ulong b = num & lByteMask[i];
  148. b >>= (i*8);
  149. ulong b1 = b & nibble0Mask;
  150. ulong b2 = (b & nibble1Mask) >> 4;
  151. str[strIx--] = hexDigit[b1];
  152. str[strIx--] = hexDigit[b2];
  153. }
  154. return new String(str);
  155. }
  156. }
  157. /// <summary>
  158. /// Exception for features yet to be implemented
  159. /// </summary>
  160. public class NotYetImplementedException : System.Exception {
  161. /// <summary>
  162. /// constructor
  163. /// </summary>
  164. /// <param name="msg"></param>
  165. public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
  166. }
  167. /// <summary>
  168. /// Error in a type signature
  169. /// </summary>
  170. public class TypeSignatureException : System.Exception {
  171. /// <summary>
  172. /// constructor
  173. /// </summary>
  174. /// <param name="msg"></param>
  175. public TypeSignatureException(string msg) : base(msg) { }
  176. }
  177. /// <summary>
  178. /// Error with a CIL instruction
  179. /// </summary>
  180. public class InstructionException : System.Exception {
  181. IType iType;
  182. uint op;
  183. internal InstructionException(IType iType, uint op) {
  184. this.iType = iType;
  185. this.op = op;
  186. }
  187. internal string AddMethodName(string name) {
  188. string istr = " ";
  189. switch (iType) {
  190. case (IType.fieldOp) : istr += (FieldOp)op; break;
  191. case (IType.methOp) : istr += (MethodOp)op; break;
  192. case (IType.specialOp) : istr += (SpecialOp)op; break;
  193. case (IType.typeOp) : istr += (TypeOp)op; break;
  194. default : break;
  195. }
  196. return "NullPointer in instruction" + istr + " for method " + name;
  197. }
  198. }
  199. /// <summary>
  200. /// Error with descriptor types
  201. /// </summary>
  202. public class DescriptorException : System.Exception {
  203. /// <summary>
  204. /// exception
  205. /// </summary>
  206. /// <param name="msg"></param>
  207. public DescriptorException(string msg):
  208. base("Descriptor for " + msg + " already exists") { }
  209. /// <summary>
  210. /// exception
  211. /// </summary>
  212. public DescriptorException() :
  213. base("Descriptor is a Def when a Ref is required") { }
  214. }
  215. /// <summary>
  216. /// Error for invalid PE file
  217. /// </summary>
  218. public class PEFileException : System.Exception {
  219. /// <summary>
  220. /// PEFile exception constructor
  221. /// </summary>
  222. /// <param name="msg"></param>
  223. public PEFileException(string msg) : base("Error in PE File: " + msg) { }
  224. }
  225. /// <summary>
  226. /// When the maximum stack depth could not be found dynamically.
  227. /// </summary>
  228. public class CouldNotFindMaxStackDepth : System.Exception {
  229. /// <summary>
  230. /// Constructor
  231. /// </summary>
  232. public CouldNotFindMaxStackDepth() : base("Not able to find the maximum stack depth.") { }
  233. }
  234. /// <summary>
  235. /// When the stack depth is not valid for the current position.
  236. /// </summary>
  237. public class InvalidStackDepth : System.Exception {
  238. /// <summary>
  239. /// Constructor
  240. /// </summary>
  241. public InvalidStackDepth(string msg) : base("Invalid stack depth reached: " + msg) { }
  242. }
  243. /**************************************************************************/
  244. // Various Enumerations for PEFiles
  245. /// <summary>
  246. /// flags for the assembly (.corflags)
  247. /// </summary>
  248. public enum CorFlags {
  249. /// <summary>
  250. /// IL only
  251. /// </summary>
  252. CF_IL_ONLY = 1,
  253. /// <summary>
  254. /// 32 bits
  255. /// </summary>
  256. CF_32_BITREQUIRED = 2,
  257. /// <summary>
  258. /// strong name signed
  259. /// </summary>
  260. CF_STRONGNAMESIGNED = 8,
  261. /// <summary>
  262. /// track debug data
  263. /// </summary>
  264. CF_TRACKDEBUGDATA = 0x10000
  265. }
  266. /// <summary>
  267. /// subsystem for the assembly (.subsystem)
  268. /// </summary>
  269. public enum SubSystem {
  270. /// <summary>
  271. /// native subsystem
  272. /// </summary>
  273. Native = 1,
  274. /// <summary>
  275. /// gui app
  276. /// </summary>
  277. Windows_GUI = 2,
  278. /// <summary>
  279. /// console app
  280. /// </summary>
  281. Windows_CUI = 3,
  282. /// <summary>
  283. /// os2 console
  284. /// </summary>
  285. OS2_CUI = 5,
  286. /// <summary>
  287. /// posix console
  288. /// </summary>
  289. POSIX_CUI = 7,
  290. /// <summary>
  291. /// native windows
  292. /// </summary>
  293. Native_Windows = 8,
  294. /// <summary>
  295. /// CE gui
  296. /// </summary>
  297. Windows_CE_GUI = 9
  298. }
  299. /// <summary>
  300. /// Hash algorithms for the assembly
  301. /// </summary>
  302. public enum HashAlgorithmType {
  303. /// <summary>
  304. /// No hash algorithm
  305. /// </summary>
  306. None,
  307. /// <summary>
  308. /// SHA1
  309. /// </summary>
  310. SHA1 = 0x8004
  311. }
  312. /// <summary>
  313. /// Attributes for this assembly
  314. /// </summary>
  315. public enum AssemAttr {
  316. /// <summary>
  317. /// Public key assembly attribute
  318. /// </summary>
  319. PublicKey = 0x01,
  320. /// <summary>
  321. /// retargetable assembly
  322. /// </summary>
  323. Retargetable = 0x100,
  324. /// <summary>
  325. /// JIT tracking
  326. /// </summary>
  327. EnableJITCompileTracking = 0x8000,
  328. /// <summary>
  329. /// Disable JIT compile optimizer
  330. /// </summary>
  331. DisableJITCompileOptimizer = 0x4000}
  332. /// <summary>
  333. /// Method call conventions
  334. /// </summary>
  335. [FlagsAttribute]
  336. public enum CallConv {
  337. /// <summary>
  338. /// default cc
  339. /// </summary>
  340. Default,
  341. /// <summary>
  342. /// cdecl
  343. /// </summary>
  344. Cdecl,
  345. /// <summary>
  346. /// stdcall
  347. /// </summary>
  348. Stdcall,
  349. /// <summary>
  350. /// this call
  351. /// </summary>
  352. Thiscall,
  353. /// <summary>
  354. /// fast call
  355. /// </summary>
  356. Fastcall,
  357. /// <summary>
  358. /// var arg
  359. /// </summary>
  360. Vararg,
  361. /// <summary>
  362. /// generic
  363. /// </summary>
  364. Generic = 0x10,
  365. /// <summary>
  366. /// instance
  367. /// </summary>
  368. Instance = 0x20,
  369. /// <summary>
  370. /// explicit instance
  371. /// </summary>
  372. InstanceExplicit = 0x60 }
  373. /// <summary>
  374. /// Method Types for Events and Properties
  375. /// </summary>
  376. public enum MethodType {
  377. /// <summary>
  378. /// setter
  379. /// </summary>
  380. Setter = 0x01,
  381. /// <summary>
  382. /// getter
  383. /// </summary>
  384. Getter,
  385. /// <summary>
  386. /// other
  387. /// </summary>
  388. Other = 0x04,
  389. /// <summary>
  390. /// add on
  391. /// </summary>
  392. AddOn = 0x08,
  393. /// <summary>
  394. /// remove on
  395. /// </summary>
  396. RemoveOn = 0x10,
  397. /// <summary>
  398. /// Fire
  399. /// </summary>
  400. Fire = 0x20 }
  401. /// <summary>
  402. /// Type custom modifier
  403. /// </summary>
  404. public enum CustomModifier {
  405. /// <summary>
  406. /// mod req
  407. /// </summary>
  408. modreq = 0x1F,
  409. /// <summary>
  410. /// mod opt
  411. /// </summary>
  412. modopt };
  413. /// <summary>
  414. /// Attibutes for a class
  415. /// </summary>
  416. [FlagsAttribute]
  417. public enum TypeAttr {
  418. Private, Public, NestedPublic, NestedPrivate,
  419. NestedFamily, NestedAssembly, NestedFamAndAssem, NestedFamOrAssem,
  420. SequentialLayout, ExplicitLayout = 0x10, Interface = 0x20,
  421. Abstract = 0x80, PublicAbstract = 0x81, Sealed = 0x100,
  422. PublicSealed = 0x101, SpecialName = 0x400, RTSpecialName = 0x800,
  423. Import = 0x1000, Serializable = 0x2000, UnicodeClass = 0x10000,
  424. AutoClass = 0x20000, BeforeFieldInit = 0x100000 }
  425. /// <summary>
  426. /// Attributes for a field
  427. /// </summary>
  428. [FlagsAttribute]
  429. public enum FieldAttr {
  430. Default, Private, FamAndAssem, Assembly,
  431. Family, FamOrAssem, Public, Static = 0x10, PublicStatic = 0x16,
  432. Initonly = 0x20, Literal = 0x40, Notserialized = 0x80,
  433. SpecialName = 0x200, RTSpecialName = 0x400 }
  434. /// <summary>
  435. /// Attributes for a method
  436. /// </summary>
  437. [FlagsAttribute]
  438. public enum MethAttr {
  439. Default, Private, FamAndAssem, Assembly,
  440. Family, FamOrAssem, Public, Static = 0x0010, PublicStatic = 0x16,
  441. Final = 0x0020, PublicStaticFinal = 0x36, Virtual = 0x0040,
  442. PrivateVirtual, PublicVirtual = 0x0046, HideBySig = 0x0080,
  443. NewSlot = 0x0100, Abstract = 0x0400, SpecialName = 0x0800,
  444. RTSpecialName = 0x1000, SpecialRTSpecialName = 0x1800,
  445. RequireSecObject = 0x8000}
  446. /// <summary>
  447. /// Attributes for .pinvokeimpl method declarations
  448. /// </summary>
  449. [FlagsAttribute]
  450. public enum PInvokeAttr {
  451. ansi = 2, unicode = 4, autochar = 6,
  452. lasterr = 0x040, winapi = 0x100, cdecl = 0x200, stdcall = 0x300,
  453. thiscall = 0x400, fastcall = 0x500 }
  454. /// <summary>
  455. /// Implementation attributes for a method
  456. /// </summary>
  457. [FlagsAttribute]
  458. public enum ImplAttr {
  459. IL, Native, OPTIL, Runtime, Unmanaged,
  460. ForwardRef = 0x10, PreserveSig = 0x0080, InternalCall = 0x1000,
  461. Synchronised = 0x0020, Synchronized = 0x0020, NoInLining = 0x0008}
  462. /// <summary>
  463. /// Modes for a parameter
  464. /// </summary>
  465. [FlagsAttribute]
  466. public enum ParamAttr { Default, In, Out, Opt = 4 }
  467. /// <summary>
  468. /// Flags for a generic parameter
  469. /// </summary>
  470. [Flags]
  471. public enum GenericParamAttr {
  472. NonVariant,
  473. Covariant,
  474. Contravariant,
  475. ReferenceType = 0x4,
  476. RequireDefaultCtor = 0x10 }
  477. /// <summary>
  478. /// Which version of PE file to build
  479. /// </summary>
  480. public enum NetVersion {
  481. Everett, /* version 1.1.4322 */
  482. Whidbey40, /* version 2.0.40607 beta 1*/
  483. Whidbey41, /* version 2.0.41202 */
  484. Whidbey50, /* version 2.0.50215 beta2*/
  485. Version2 /* version 2.0.50727.0 */
  486. }
  487. /// <summary>
  488. /// CIL instructions
  489. /// </summary>
  490. public enum Op {
  491. nop, breakOp, ldarg_0, ldarg_1, ldarg_2, ldarg_3, ldloc_0, ldloc_1, ldloc_2,
  492. ldloc_3, stloc_0, stloc_1, stloc_2, stloc_3,
  493. ldnull = 0x14, ldc_i4_m1, ldc_i4_0, ldc_i4_1, ldc_i4_2, ldc_i4_3,
  494. ldc_i4_4, ldc_i4_5, ldc_i4_6, ldc_i4_7, ldc_i4_8, dup = 0x25, pop,
  495. ret = 0x2A, ldind_i1 = 0x46, ldind_u1, ldind_i2, ldind_u2, ldind_i4,
  496. ldind_u4, ldind_i8, ldind_i, ldind_r4, ldind_r8, ldind_ref, stind_ref,
  497. stind_i1, stind_i2, stind_i4, stind_i8, stind_r4, stind_r8, add, sub, mul,
  498. div, div_un, rem, rem_un, and, or, xor, shl, shr, shr_un, neg, not,
  499. conv_i1, conv_i2, conv_i4, conv_i8, conv_r4, conv_r8, conv_u4, conv_u8,
  500. conv_r_un = 0x76, throwOp = 0x7A, conv_ovf_i1_un = 0x82, conv_ovf_i2_un,
  501. conv_ovf_i4_un, conv_ovf_i8_un, conf_ovf_u1_un, conv_ovf_u2_un,
  502. conv_ovf_u4_un, conv_ovf_u8_un, conv_ovf_i_un, conv_ovf_u_un,
  503. ldlen = 0x8E, ldelem_i1 = 0x90, ldelem_u1, ldelem_i2, ldelem_u2,
  504. ldelem_i4, ldelem_u4, ldelem_i8, ldelem_i, ldelem_r4, ldelem_r8,
  505. ldelem_ref, stelem_i, stelem_i1, stelem_i2, stelem_i4, stelem_i8,
  506. stelem_r4, stelem_r8, stelem_ref, conv_ovf_i1 = 0xb3, conv_ovf_u1,
  507. conv_ovf_i2, conv_ovf_u2, conv_ovf_i4, conv_ovf_u4, conv_ovf_i8,
  508. conv_ovf_u8, ckfinite = 0xC3, conv_u2 = 0xD1, conv_u1, conv_i,
  509. conv_ovf_i, conv_ovf_u, add_ovf, add_ovf_un, mul_ovf, mul_ovf_un,
  510. sub_ovf, sub_ovf_un, endfinally, stind_i = 0xDF, conv_u,
  511. arglist = 0xFE00, ceq, cgt, cgt_un, clt, clt_un, localloc = 0xFE0F,
  512. endfilter = 0xFE11, volatile_ = 0xFE13, tail_, cpblk = 0xFE17, initblk,
  513. rethrow = 0xFE1A, refanytype = 0xFE1D, readOnly}
  514. /// <summary>
  515. /// CIL instructions requiring an integer parameter
  516. /// </summary>
  517. public enum IntOp {
  518. ldarg_s = 0x0E, ldarga_s, starg_s, ldloc_s, ldloca_s,
  519. stloc_s, ldc_i4_s = 0x1F, ldc_i4, ldarg = 0xFE09,
  520. ldarga, starg, ldloc, ldloca, stloc, unaligned = 0xFE12 }
  521. /// <summary>
  522. /// CIL instructions requiring a field parameter
  523. /// </summary>
  524. public enum FieldOp {
  525. ldfld = 0x7B, ldflda, stfld, ldsfld, ldsflda,
  526. stsfld, ldtoken = 0xD0 }
  527. /// <summary>
  528. /// CIL instructions requiring a method parameter
  529. /// </summary>
  530. public enum MethodOp {
  531. jmp = 0x27, call, callvirt = 0x6F, newobj = 0x73,
  532. ldtoken = 0xD0, ldftn = 0xFE06, ldvirtfn }
  533. /// <summary>
  534. /// CIL instructions requiring a type parameter
  535. /// </summary>
  536. public enum TypeOp {
  537. cpobj = 0x70, ldobj, castclass = 0x74, isinst,
  538. unbox = 0x79, stobj = 0x81, box = 0x8C, newarr,
  539. ldelema = 0x8F, ldelem_any = 0xA3, stelem_any, unbox_any,
  540. refanyval = 0xC2, mkrefany = 0xC6,
  541. ldtoken = 0xD0, initobj = 0xFE15, constrained, sizeOf = 0xFE1C }
  542. /// <summary>
  543. /// CIL branch instructions
  544. /// </summary>
  545. public enum BranchOp {
  546. br_s = 0x2B, brfalse_s, brtrue_s, beq_s, bge_s, bgt_s, ble_s,
  547. blt_s, bne_un_s, bge_un_s, bgt_un_s, ble_un_s, blt_un_s,
  548. br, brfalse, brtrue, beq, bge, bgt, ble, blt, bne_un, bge_un, bgt_un, ble_un, blt_un,
  549. leave = 0xDD, leave_s }
  550. public enum SpecialOp {
  551. ldc_i8 = 0x21, ldc_r4, ldc_r8, calli = 0x29,
  552. Switch = 0x45, ldstr = 0x72 }
  553. /// <summary>
  554. /// Index for all the tables in the meta data
  555. /// </summary>
  556. public enum MDTable {
  557. Module, TypeRef, TypeDef, Field = 0x04, Method = 0x06,
  558. Param = 0x08, InterfaceImpl, MemberRef, Constant, CustomAttribute,
  559. FieldMarshal, DeclSecurity, ClassLayout, FieldLayout, StandAloneSig,
  560. EventMap, Event = 0x14, PropertyMap, Property = 0x17, MethodSemantics,
  561. MethodImpl, ModuleRef, TypeSpec, ImplMap, FieldRVA, Assembly = 0x20,
  562. AssemblyProcessor, AssemblyOS, AssemblyRef, AssemblyRefProcessor,
  563. AssemblyRefOS, File, ExportedType, ManifestResource, NestedClass,
  564. GenericParam, MethodSpec, GenericParamConstraint, MaxMDTable }
  565. public enum NativeTypeIx {
  566. Void = 0x01, Boolean, I1, U1, I2, U2, I4, U4,
  567. I8, U8, R4, R8, SysChar, Variant, Currency, Ptr, Decimal, Date, BStr,
  568. LPStr, LPWStr, LPTStr, FixedSysString, ObjectRef, IUnknown, IDispatch,
  569. Struct, Intf, SafeArray, FixedArray, Int, UInt, NestedStruct, ByValStr,
  570. AnsiBStr, TBStr, VariantBool, Func, AsAny = 0x28, Array = 0x2A, LPStruct,
  571. CustomMarshaller, Error }
  572. public enum SafeArrayType {
  573. int16 = 2, int32, float32, float64,
  574. currency, date, bstr, dispatch, error, boolean, variant, unknown,
  575. Decimal, int8 = 16, uint8, uint16, uint32, Int = 22, UInt,
  576. record = 0x24,
  577. MAX = 0x50
  578. }
  579. internal enum CIx {
  580. TypeDefOrRef, HasConstant, HasCustomAttr, HasFieldMarshal,
  581. HasDeclSecurity, MemberRefParent, HasSemantics, MethodDefOrRef,
  582. MemberForwarded, Implementation, CustomAttributeType, ResolutionScope,
  583. TypeOrMethodDef, MaxCIx }
  584. internal enum MapType { eventMap, propertyMap, nestedClass }
  585. public enum ElementType : byte {
  586. End, Void, Boolean, Char, I1, U1, I2, U2, I4, U4,
  587. I8, U8, R4, R8, String, Ptr, ByRef, ValueType, Class, Var, Array, GenericInst,
  588. TypedByRef, I = 0x18, U, FnPtr = 0x1B, Object, SZArray, MVar, CmodReqd,
  589. CmodOpt, Internal, Modifier = 0x40, Sentinel, Pinned = 0x45, ClassType = 0x50 }
  590. public enum SecurityAction {
  591. Request = 0x01, Demand, Assert, Deny, PermitOnly,
  592. LinkDemand, InheritanceDemand, RequestMinimum, RequestOptional, RequestRefuse,
  593. PreJITGrant, PreJITDeny, NonCASDemand, NonCASLinkDemand, NonCASInheritanceDemand }
  594. internal enum IType {
  595. op, methOp, fieldOp, typeOp, specialOp, int8Op, uint8Op, uint16Op,
  596. int32Op, branchOp }
  597. /**************************************************************************/
  598. /// <summary>
  599. /// Abstract class to represent a row of the Meta Data Tables
  600. /// </summary>
  601. public abstract class TableRow {
  602. internal PEReader buffer;
  603. private uint row = 0;
  604. /// <summary>
  605. /// The index of the Meta Data Table containing this element
  606. /// </summary>
  607. protected MDTable tabIx;
  608. /*-------------------- Constructors ---------------------------------*/
  609. internal TableRow() { }
  610. internal TableRow(PEReader buff, uint ix, MDTable tableIx) {
  611. buffer = buff;
  612. row = ix;
  613. tabIx = tableIx;
  614. }
  615. /// <summary>
  616. /// The row number of this element in the Meta Data Table
  617. /// </summary>
  618. public uint Row {
  619. get { return row; }
  620. set { row = value; }
  621. }
  622. }
  623. /****************************************************/
  624. /// <summary>
  625. /// Base class for all Meta Data table elements
  626. /// </summary>
  627. public abstract class MetaDataElement : TableRow, IComparable {
  628. /// <summary>
  629. /// The list of custom attributes associated with this meta data element
  630. /// </summary>
  631. protected ArrayList customAttributes;
  632. protected bool done = false;
  633. protected bool sortTable = false;
  634. internal bool unresolved = false;
  635. /*-------------------- Constructors ---------------------------------*/
  636. internal MetaDataElement() { }
  637. /// <summary>
  638. /// Get any custom attributes associated with this meta data element
  639. /// </summary>
  640. /// <returns>Array of custom attribute descriptors</returns>
  641. public CustomAttribute[] GetCustomAttributes() {
  642. if (customAttributes == null) return new CustomAttribute[0];
  643. return (CustomAttribute[])customAttributes.ToArray(typeof(CustomAttribute));
  644. }
  645. /// <summary>
  646. /// Associate some custom attribute(s) with this meta data element
  647. /// </summary>
  648. /// <param name="cas">list of custom attributes</param>
  649. public void SetCustomAttributes(CustomAttribute[] cas) {
  650. if (cas == null)
  651. customAttributes = null;
  652. else
  653. customAttributes = new ArrayList(cas);
  654. }
  655. internal virtual bool isDef() { return false; }
  656. internal virtual void Resolve(PEReader buff) { }
  657. internal virtual void ResolveDetails(PEReader buff) { }
  658. internal virtual uint GetCodedIx(CIx code) { return 0; }
  659. internal bool NeedToSort() { return sortTable; }
  660. internal virtual uint SortKey() {
  661. throw new PEFileException("Trying to sort table of " + this);
  662. //return 0;
  663. }
  664. /// <summary>
  665. /// Add a custom attribute to this item
  666. /// </summary>
  667. /// <param name="ctorMeth">the constructor method for this attribute</param>
  668. /// <param name="val">the byte value of the parameters</param>
  669. public void AddCustomAttribute(Method ctorMeth, byte[] val) {
  670. if (customAttributes == null) {
  671. customAttributes = new ArrayList();
  672. }
  673. customAttributes.Add(new CustomAttribute(this,ctorMeth,val));
  674. }
  675. /// <summary>
  676. /// Add a custom attribute to this item
  677. /// </summary>
  678. /// <param name="ctorMeth">the constructor method for this attribute</param>
  679. /// <param name="cVals">the constant values of the parameters</param>
  680. public void AddCustomAttribute(Method ctorMeth, Constant[] cVals) {
  681. if (customAttributes == null) {
  682. customAttributes = new ArrayList();
  683. }
  684. customAttributes.Add(new CustomAttribute(this,ctorMeth,cVals));
  685. }
  686. /// <summary>
  687. /// Associate a custom attribute with this meta data element
  688. /// </summary>
  689. public void AddCustomAttribute(CustomAttribute ca) {
  690. if (customAttributes == null) {
  691. customAttributes = new ArrayList();
  692. }
  693. customAttributes.Add(ca);
  694. }
  695. internal uint Token() {
  696. if (Row == 0) throw new Exception("Meta data token is zero!!");
  697. return (((uint)tabIx << 24) | Row);
  698. }
  699. internal void BuildMDTables(MetaDataOut md) {
  700. if (done) return;
  701. done = true;
  702. if (Diag.DiagOn) Console.WriteLine("In BuildMDTables");
  703. BuildTables(md);
  704. if (customAttributes != null) {
  705. for (int i=0; i < customAttributes.Count; i++) {
  706. CustomAttribute ca = (CustomAttribute)customAttributes[i];
  707. ca.BuildTables(md);
  708. }
  709. }
  710. }
  711. internal virtual void BuildTables(MetaDataOut md) { }
  712. internal virtual void BuildSignatures(MetaDataOut md) {
  713. done = false;
  714. }
  715. internal virtual void BuildCILInfo(CILWriter output) { }
  716. internal virtual void AddToTable(MetaDataOut md) {
  717. md.AddToTable(tabIx,this);
  718. }
  719. internal virtual void Write(PEWriter output) { }
  720. internal virtual void Write(CILWriter output) {
  721. throw new Exception("CIL backend not yet fully implemented - " + GetType().ToString());
  722. }
  723. internal virtual string NameString() { return "NoName"; }
  724. internal void DescriptorError(MetaDataElement elem) {
  725. throw new DescriptorException(elem.NameString());
  726. }
  727. #region IComparable Members
  728. public int CompareTo(object obj) {
  729. uint otherKey = ((MetaDataElement)obj).SortKey();
  730. uint thisKey = SortKey();
  731. if (thisKey == otherKey) {
  732. if (this is GenericParam) {
  733. if (((GenericParam)this).Index < ((GenericParam)obj).Index)
  734. return -1;
  735. else
  736. return 1;
  737. }
  738. return 0;
  739. }
  740. if (thisKey < otherKey) return -1;
  741. return 1;
  742. }
  743. #endregion
  744. }
  745. /**************************************************************************/
  746. /// <summary>
  747. /// Layout information for a class (.class [sequential | explicit])
  748. /// </summary>
  749. internal class ClassLayout : MetaDataElement {
  750. ClassDef parent;
  751. ushort packSize = 0;
  752. uint classSize = 0;
  753. uint parentIx = 0;
  754. /*-------------------- Constructors ---------------------------------*/
  755. internal ClassLayout(int pack, int cSize, ClassDef par) {
  756. packSize = (ushort)pack;
  757. classSize = (uint)cSize;
  758. parent = par;
  759. tabIx = MDTable.ClassLayout;
  760. }
  761. internal ClassLayout(ushort pack, uint cSize, ClassDef par) {
  762. packSize = pack;
  763. classSize = cSize;
  764. parent = par;
  765. tabIx = MDTable.ClassLayout;
  766. }
  767. internal ClassLayout(PEReader buff) {
  768. packSize = buff.ReadUInt16();
  769. classSize = buff.ReadUInt32();
  770. parentIx = buff.GetIndex(MDTable.TypeDef);
  771. tabIx = MDTable.ClassLayout;
  772. }
  773. internal static ClassLayout FindLayout(PEReader buff, ClassDef paren, uint classIx) {
  774. buff.SetElementPosition(MDTable.ClassLayout,0);
  775. for (int i=0; i < buff.GetTableSize(MDTable.ClassLayout); i++) {
  776. ushort packSize = buff.ReadUInt16();
  777. uint classSize = buff.ReadUInt32();
  778. if (buff.GetIndex(MDTable.TypeDef) == classIx)
  779. return new ClassLayout(packSize,classSize,paren);
  780. }
  781. return null;
  782. }
  783. internal static void Read(PEReader buff, TableRow[] layouts) {
  784. for (int i=0; i < layouts.Length; i++ ) {
  785. layouts[i] = new ClassLayout(buff);
  786. }
  787. }
  788. internal override void Resolve(PEReader buff) {
  789. parent = (ClassDef)buff.GetElement(MDTable.TypeDef,parentIx);
  790. if (parent != null) parent.Layout = this;
  791. }
  792. /*------------------------- public set and get methods --------------------------*/
  793. public void SetPack(int pack) { packSize = (ushort)pack; }
  794. public int GetPack() { return (int)packSize; }
  795. public void SetSize(int size) { classSize = (uint)size; }
  796. public int GetSize() { return (int)classSize; }
  797. /*----------------------------- internal functions ------------------------------*/
  798. internal sealed override void BuildTables(MetaDataOut md) {
  799. md.AddToTable(tabIx,this);
  800. }
  801. internal static uint Size(MetaData md) {
  802. return 6 + md.TableIndexSize(MDTable.TypeDef);
  803. }
  804. internal sealed override void Write(PEWriter output) {
  805. output.Write(packSize);
  806. output.Write(classSize);
  807. output.WriteIndex(MDTable.TypeDef,parent.Row);
  808. }
  809. }
  810. /**************************************************************************/
  811. /// <summary>
  812. /// Summary description for ConstantElem.
  813. /// </summary>
  814. internal class ConstantElem : MetaDataElement {
  815. MetaDataElement parent;
  816. Constant cValue;
  817. uint valIx = 0, parentIx = 0;
  818. /*-------------------- Constructors ---------------------------------*/
  819. internal ConstantElem(MetaDataElement parent, Constant val) {
  820. this.parent = parent;
  821. cValue = val;
  822. sortTable = true;
  823. tabIx = MDTable.Constant;
  824. }
  825. internal ConstantElem(PEReader buff) {
  826. byte constType = buff.ReadByte();
  827. byte pad = buff.ReadByte();
  828. parentIx = buff.GetCodedIndex(CIx.HasConstant);
  829. //valIx = buff.GetBlobIx();
  830. cValue = buff.GetBlobConst(constType);
  831. sortTable = true;
  832. tabIx = MDTable.Constant;
  833. }
  834. internal override void Resolve(PEReader buff) {
  835. parent = buff.GetCodedElement(CIx.HasConstant,parentIx);
  836. if (parent != null) {
  837. if (parent is Param) ((Param)parent).AddDefaultValue(cValue);
  838. else if (parent is FieldDef) ((FieldDef)parent).AddValue(cValue);
  839. else ((Property)parent).AddInitValue(cValue);
  840. }
  841. }
  842. internal static void Read(PEReader buff, TableRow[] consts) {
  843. for (int i=0; i < consts.Length; i++)
  844. consts[i] = new ConstantElem(buff);
  845. }
  846. /*----------------------------- internal functions ------------------------------*/
  847. internal override uint SortKey() {
  848. return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasConstant])
  849. | parent.GetCodedIx(CIx.HasConstant);
  850. }
  851. internal sealed override void BuildTables(MetaDataOut md) {
  852. md.AddToTable(MDTable.Constant,this);
  853. valIx = cValue.GetBlobIndex(md);
  854. }
  855. internal static uint Size(MetaData md) {
  856. return 2 + md.CodedIndexSize(CIx.HasConstant) + md.BlobIndexSize();
  857. }
  858. internal sealed override void Write(PEWriter output) {
  859. output.Write(cValue.GetTypeIndex());
  860. output.Write((byte)0);
  861. output.WriteCodedIndex(CIx.HasConstant,parent);
  862. output.BlobIndex(valIx);
  863. }
  864. }
  865. /**************************************************************************/
  866. /// <summary>
  867. /// Descriptor for a Custom Attribute (.custom)
  868. /// </summary>
  869. public class CustomAttribute : MetaDataElement {
  870. internal static readonly ushort prolog = 0x0001;
  871. private static readonly int initSize = 5;
  872. MetaDataElement parent;
  873. Method type;
  874. uint valIx, parentIx, typeIx;
  875. Constant[] argVals, vals;
  876. public byte[] byteVal;
  877. ushort numNamed = 0;
  878. string[] names;
  879. bool[] isField;
  880. bool changed = false;
  881. /*-------------------- Constructors ---------------------------------*/
  882. internal CustomAttribute(MetaDataElement paren, Method constrType,
  883. Constant[] val) {
  884. parent = paren;
  885. type = constrType;
  886. argVals = val;
  887. changed = true;
  888. sortTable = true;
  889. tabIx = MDTable.CustomAttribute;
  890. }
  891. internal CustomAttribute(MetaDataElement paren, Method constrType,
  892. byte[] val) {
  893. parent = paren;
  894. type = constrType;
  895. tabIx = MDTable.CustomAttribute;
  896. byteVal = val;
  897. sortTable = true;
  898. changed = true;
  899. }
  900. internal CustomAttribute(PEReader buff) {
  901. parentIx = buff.GetCodedIndex(CIx.HasCustomAttr);
  902. typeIx = buff.GetCodedIndex(CIx.CustomAttributeType);
  903. valIx = buff.GetBlobIx();
  904. sortTable = true;
  905. tabIx = MDTable.CustomAttribute;
  906. }
  907. internal static void Read(PEReader buff, TableRow[] attrs) {
  908. for (int i=0; i < attrs.Length; i++) {
  909. attrs[i] = new CustomAttribute(buff);
  910. }
  911. }
  912. internal override void Resolve(PEReader buff) {
  913. parent = buff.GetCodedElement(CIx.HasCustomAttr,parentIx);
  914. if (parent == null) return;
  915. parent.AddCustomAttribute(this);
  916. type = (Method)buff.GetCodedElement(CIx.CustomAttributeType,typeIx);
  917. byteVal = buff.GetBlob(valIx);
  918. }
  919. /*------------------------- public set and get methods --------------------------*/
  920. public void AddFieldOrProp(string name, Constant val, bool isFld) {
  921. if ((byteVal != null) && !changed) DecodeCustomAttributeBlob();
  922. if (numNamed == 0) {
  923. names = new string[initSize];
  924. vals = new Constant[initSize];
  925. isField = new bool[initSize];
  926. } else if (numNamed >= names.Length) {
  927. string[] tmpNames = names;
  928. Constant[] tmpVals = vals;
  929. bool[] tmpField = isField;
  930. names = new String[names.Length + initSize];
  931. vals = new Constant[vals.Length + initSize];
  932. isField = new bool[isField.Length + initSize];
  933. for (int i = 0; i < numNamed; i++) {
  934. names[i] = tmpNames[i];
  935. vals[i] = tmpVals[i];
  936. isField[i] = tmpField[i];
  937. }
  938. }
  939. names[numNamed] = name;
  940. vals[numNamed] = val;
  941. isField[numNamed++] = isFld;
  942. changed = true;
  943. }
  944. public Constant[] Args {
  945. get {
  946. if (!changed && (byteVal != null)) {
  947. try {
  948. DecodeCustomAttributeBlob();
  949. } catch {
  950. }
  951. }
  952. return argVals;
  953. }
  954. set {
  955. argVals = value;
  956. changed = true;
  957. }
  958. }
  959. public string[] GetNames() {
  960. return names;
  961. }
  962. public bool[] GetIsField() {
  963. return isField;
  964. }
  965. public Constant[] GetNamedArgs() {
  966. return vals;
  967. }
  968. /*----------------------------- internal functions ------------------------------*/
  969. internal void DecodeCustomAttributeBlob() {
  970. MemoryStream caBlob = new MemoryStream(byteVal);
  971. BinaryReader blob = new BinaryReader(caBlob,System.Text.Encoding.UTF8);
  972. if (blob.ReadUInt16() != CustomAttribute.prolog) throw new PEFileException("Invalid Custom Attribute Blob");
  973. Type[] parTypes = type.GetParTypes();
  974. argVals = new Constant[parTypes.Length];
  975. for (int i=0; i < parTypes.Length; i++) {
  976. Type argType = parTypes[i];
  977. bool arrayConst = argType is Array;
  978. if (arrayConst) argType = ((ZeroBasedArray)(parTypes[i])).ElemType();
  979. bool boxed = argType is SystemClass;
  980. int eType = argType.GetTypeIndex();
  981. if (arrayConst) {
  982. Constant[] elems = new Constant[blob.ReadUInt32()];
  983. for (int j=0; j < elems.Length; j++) {
  984. if (boxed) {
  985. eType = blob.ReadByte();
  986. elems[j] = new BoxedSimpleConst((SimpleConstant)PEReader.ReadConst(eType,blob));
  987. } else {
  988. elems[j] = PEReader.ReadConst(eType,blob);
  989. }
  990. }
  991. argVals[i] = new ArrayConst(elems);
  992. } else if (boxed) {
  993. argVals[i] = new BoxedSimpleConst((SimpleConstant)PEReader.ReadConst(blob.ReadByte(),blob));
  994. } else {
  995. argVals[i] = PEReader.ReadConst(eType,blob);
  996. }
  997. }
  998. uint numNamed = 0;
  999. if (blob.BaseStream.Position != byteVal.Length)
  1000. numNamed = blob.ReadUInt16();
  1001. if (numNamed > 0) {
  1002. names = new string[numNamed];
  1003. vals = new Constant[numNamed];
  1004. isField = new bool[numNamed];
  1005. for (int i=0; i < numNamed; i++) {
  1006. isField[i] = blob.ReadByte() == 0x53;
  1007. int eType = blob.ReadByte();
  1008. names[i] = blob.ReadString();
  1009. vals[i] = PEReader.ReadConst(eType,blob);
  1010. }
  1011. }
  1012. }
  1013. internal void AddFieldOrProps(string[] names, Constant[] vals, bool[] isField) {
  1014. this.names = names;
  1015. this.vals = vals;
  1016. this.isField = isField;
  1017. numNamed = (ushort)names.Length;
  1018. }
  1019. internal void SetBytes(byte[] bytes) {
  1020. this.byteVal = bytes;
  1021. }
  1022. internal Method GetCAType() {
  1023. return type;
  1024. }
  1025. internal override uint SortKey() {
  1026. return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasCustomAttr])
  1027. | parent.GetCodedIx(CIx.HasCustomAttr);
  1028. }
  1029. internal sealed override void BuildTables(MetaDataOut md) {
  1030. md.AddToTable(tabIx,this);
  1031. type.BuildMDTables(md);
  1032. // more adding to tables if data is not bytes
  1033. if (changed || (byteVal == null)) {
  1034. MemoryStream str = new MemoryStream();
  1035. BinaryWriter bw = new BinaryWriter(str);
  1036. bw.Write((ushort)1);
  1037. if (argVals != null) {
  1038. for (int i=0; i < argVals.Length; i++) {
  1039. argVals[i].Write(bw);
  1040. }
  1041. }
  1042. bw.Write(numNamed);
  1043. for (int i=0; i < numNamed; i++) {
  1044. if (isField[i]) bw.Write(Field.FieldTag);
  1045. else bw.Write(Property.PropertyTag);
  1046. bw.Write(vals[i].GetTypeIndex());
  1047. bw.Write(names[i]); // check this is the right format!!!
  1048. vals[i].Write(bw);
  1049. }
  1050. byteVal = str.ToArray();
  1051. }
  1052. valIx = md.AddToBlobHeap(byteVal);
  1053. }
  1054. internal static uint Size(MetaData md) {
  1055. return md.CodedIndexSize(CIx.HasCustomAttr) + md.CodedIndexSize(CIx.CustomAttributeType) + md.BlobIndexSize();
  1056. }
  1057. internal sealed override void Write(PEWriter output) {
  1058. output.WriteCodedIndex(CIx.HasCustomAttr,parent);
  1059. output.WriteCodedIndex(CIx.CustomAttributeType,type);
  1060. output.BlobIndex(valIx);
  1061. }
  1062. }
  1063. /**************************************************************************/
  1064. /// <summary>
  1065. /// Descriptor for security permissions for a class or a method NOT YET IMPLEMENTED
  1066. /// </summary>
  1067. public class DeclSecurity : MetaDataElement {
  1068. SecurityAction action;
  1069. MetaDataElement parent;
  1070. uint parentIx = 0, permissionIx;
  1071. byte[] permissionSet;
  1072. /*-------------------- Constructors ---------------------------------*/
  1073. internal DeclSecurity(MetaDataElement paren, SecurityAction act, byte[] perSet) {
  1074. parent = paren;
  1075. action = act;
  1076. permissionSet = perSet;
  1077. sortTable = true;
  1078. tabIx = MDTable.DeclSecurity;
  1079. }
  1080. internal DeclSecurity(PEReader buff) {
  1081. action = (SecurityAction)buff.ReadUInt16();
  1082. parentIx = buff.GetCodedIndex(CIx.HasDeclSecurity);
  1083. permissionSet = buff.GetBlob();
  1084. sortTable = true;
  1085. tabIx = MDTable.DeclSecurity;
  1086. }
  1087. internal static void Read(PEReader buff, TableRow[] secs) {
  1088. for (int i=0; i < secs.Length; i++)
  1089. secs[i] = new DeclSecurity(buff);
  1090. }
  1091. internal static DeclSecurity FindSecurity(PEReader buff, MetaDataElement paren, uint codedParIx) {
  1092. buff.SetElementPosition(MDTable.DeclSecurity,0);
  1093. for (int i=0; i < buff.GetTableSize(MDTable.DeclSecurity); i++) {
  1094. uint act = buff.ReadUInt16();
  1095. if (buff.GetCodedIndex(CIx.HasDeclSecurity) == codedParIx)
  1096. return new DeclSecurity(paren,(SecurityAction)act,buff.GetBlob());
  1097. uint junk = buff.GetBlobIx();
  1098. }
  1099. return null;
  1100. }
  1101. internal override void Resolve(PEReader buff) {
  1102. parent = buff.GetCodedElement(CIx.HasDeclSecurity,parentIx);
  1103. if (parent != null) {
  1104. if (parent is ClassDef) ((ClassDef)parent).AddSecurity(this);
  1105. if (parent is Assembly) ((Assembly)parent).AddSecurity(this);
  1106. if (parent is MethodDef) ((MethodDef)parent).AddSecurity(this);
  1107. }
  1108. }
  1109. internal override uint SortKey() {
  1110. return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.HasDeclSecurity])
  1111. | parent.GetCodedIx(CIx.HasDeclSecurity);
  1112. }
  1113. internal sealed override void BuildTables(MetaDataOut md) {
  1114. md.AddToTable(MDTable.DeclSecurity, this);
  1115. permissionIx = md.AddToBlobHeap(permissionSet);
  1116. }
  1117. internal static uint Size(MetaData md) {
  1118. return 2 + md.CodedIndexSize(CIx.HasDeclSecurity) + md.BlobIndexSize();
  1119. }
  1120. internal sealed override void Write(PEWriter output) {
  1121. output.Write((UInt16)action); // or should this be 2 bytes??
  1122. output.WriteCodedIndex(CIx.HasDeclSecurity,parent);
  1123. output.BlobIndex(permissionIx);
  1124. }
  1125. }
  1126. /**************************************************************************/
  1127. /// <summary>
  1128. /// Descriptor for a class defined in another module of THIS assembly
  1129. /// and exported (.class extern)
  1130. /// </summary>
  1131. internal class ExternClass : MetaDataElement {
  1132. MetaDataElement implementation;
  1133. uint flags, typeDefId = 0;
  1134. uint implIx = 0, nameIx = 0, nameSpaceIx = 0;
  1135. string nameSpace, name;
  1136. /*-------------------- Constructors ---------------------------------*/
  1137. internal ExternClass(TypeAttr attr, string ns, string name, MetaDataElement paren) {
  1138. flags = (uint)attr;
  1139. nameSpace = ns;
  1140. this.name = name;
  1141. implementation = paren;
  1142. tabIx = MDTable.ExportedType;
  1143. }
  1144. public ExternClass(PEReader buff) {
  1145. flags = buff.ReadUInt32();
  1146. typeDefId = buff.ReadUInt32();
  1147. name = buff.GetString();
  1148. nameSpace = buff.GetString();
  1149. implIx = buff.GetCodedIndex(CIx.Implementation);
  1150. tabIx = MDTable.ExportedType;
  1151. }
  1152. internal static void Read(PEReader buff, TableRow[] eClasses) {
  1153. for (int i=0; i < eClasses.Length; i++)
  1154. eClasses[i] = new ExternClass(buff);
  1155. }
  1156. internal static void GetClassRefs(PEReader buff, TableRow[] eClasses) {
  1157. for (uint i=0; i < eClasses.Length; i++) {
  1158. uint junk = buff.ReadUInt32();
  1159. junk = buff.ReadUInt32();
  1160. string name = buff.GetString();
  1161. string nameSpace = buff.GetString();
  1162. uint implIx = buff.GetCodedIndex(CIx.Implementation);
  1163. eClasses[i] = new ClassRef(implIx,nameSpace,name);
  1164. eClasses[i].Row = i+1;
  1165. }
  1166. }
  1167. internal override void Resolve(PEReader buff) {
  1168. implementation = buff.GetCodedElement(CIx.Implementation,implIx);
  1169. while (implementation is ExternClass)
  1170. implementation = ((ExternClass)implementation).implementation;
  1171. ((ModuleFile)implementation).fileModule.AddExternClass(this);
  1172. }
  1173. internal string NameSpace() { return nameSpace; }
  1174. internal string Name() { return name; }
  1175. internal sealed override void BuildTables(MetaDataOut md) {
  1176. md.AddToTable(MDTable.ExportedType,this);
  1177. nameSpaceIx = md.AddToStringsHeap(nameSpace);
  1178. nameIx = md.AddToStringsHeap(name);
  1179. if (implementation is ModuleRef) {
  1180. ModuleFile mFile = ((ModuleRef)implementation).modFile;
  1181. mFile.BuildMDTables(md);
  1182. implementation = mFile;
  1183. }
  1184. }
  1185. internal static uint Size(MetaData md) {
  1186. return 8 + 2* md.StringsIndexSize() + md.CodedIndexSize(CIx.Implementation);
  1187. }
  1188. internal sealed override void Write(PEWriter output) {
  1189. output.Write(flags);
  1190. output.Write(0);
  1191. output.StringsIndex(nameIx);
  1192. output.StringsIndex(nameSpaceIx);
  1193. output.WriteCodedIndex(CIx.Implementation,implementation);
  1194. }
  1195. internal sealed override uint GetCodedIx(CIx code) {
  1196. switch (code) {
  1197. case (CIx.HasCustomAttr) : return 17;
  1198. case (CIx.Implementation) : return 2;
  1199. }
  1200. return 0;
  1201. }
  1202. }
  1203. /**************************************************************************/
  1204. /// <summary>
  1205. /// Base class for Event and Property descriptors
  1206. /// </summary>
  1207. public abstract class Feature : MetaDataElement {
  1208. private static readonly int INITSIZE = 5;
  1209. private static readonly ushort specialName = 0x200;
  1210. private static readonly ushort rtsSpecialName = 0x400;
  1211. private static readonly ushort noSpecialName = 0xFDFF;
  1212. private static readonly ushort noRTSSpecialName = 0xFBFF;
  1213. protected ClassDef parent;
  1214. protected ushort flags = 0;
  1215. protected string name;
  1216. protected int tide = 0;
  1217. protected uint nameIx;
  1218. protected MethodSemantics[] methods = new MethodSemantics[INITSIZE];
  1219. /*-------------------- Constructors ---------------------------------*/
  1220. internal Feature(string name, ClassDef par) {
  1221. parent = par;
  1222. this.name = name;
  1223. }
  1224. internal Feature() { }
  1225. internal static string[] GetFeatureNames(PEReader buff, MDTable tabIx, MDTable mapTabIx,
  1226. ClassDef theClass, uint classIx) {
  1227. buff.SetElementPosition(mapTabIx,0);
  1228. uint start = 0, end = 0, i = 0;
  1229. for (; (i < buff.GetTableSize(tabIx)) && (start == 0); i++) {
  1230. if (buff.GetIndex(MDTable.TypeDef) == classIx) {
  1231. start = buff.GetIndex(tabIx);
  1232. }
  1233. }
  1234. if (start == 0) return null;
  1235. if (i < buff.GetTableSize(mapTabIx)) {
  1236. uint junk = buff.GetIndex(MDTable.TypeDef);
  1237. end = buff.GetIndex(tabIx);
  1238. } else
  1239. end = buff.GetTableSize(tabIx);
  1240. if (tabIx == MDTable.Event)
  1241. theClass.eventIx = start;
  1242. else
  1243. theClass.propIx = start;
  1244. string[] names = new string[end-start];
  1245. buff.SetElementPosition(tabIx,start);
  1246. for (i=start; i < end; i++) {
  1247. uint junk = buff.ReadUInt16();
  1248. names[i] = buff.GetString();
  1249. if (tabIx == MDTable.Event)
  1250. junk = buff.GetCodedIndex(CIx.TypeDefOrRef);
  1251. else
  1252. junk = buff.GetBlobIx();
  1253. }
  1254. return names;
  1255. }
  1256. /*------------------------- public set and get methods --------------------------*/
  1257. /// <summary>
  1258. /// Set the specialName attribute for this Event or Property
  1259. /// </summary>
  1260. public void SetSpecialName() { flags |= specialName; }
  1261. public bool HasSpecialName() { return (flags & specialName) != 0; }
  1262. public void ClearSpecialName() { flags &= noSpecialName; }
  1263. /// <summary>
  1264. /// Set the RTSpecialName attribute for this Event or Property
  1265. /// </summary>
  1266. public void SetRTSpecialName() { flags |= rtsSpecialName; }
  1267. public bool HasRTSSpecialName() { return (flags & rtsSpecialName) != 0; }
  1268. public void ClearRTSSpecialName() { flags &= noRTSSpecialName; }
  1269. public string Name() { return name; }
  1270. public void SetName(string nam) { name = nam; }
  1271. internal void AddMethod(MethodSemantics meth) {
  1272. if (tide == methods.Length) {
  1273. MethodSemantics[] mTmp = methods;
  1274. methods = new MethodSemantics[tide * 2];
  1275. for (int i=0; i < tide; i++) {
  1276. methods[i] = mTmp[i];
  1277. }
  1278. }
  1279. methods[tide++] = meth;
  1280. }
  1281. public void AddMethod(MethodDef meth, MethodType mType) {
  1282. AddMethod(new MethodSemantics(mType,meth,this));
  1283. }
  1284. public MethodDef GetMethod(MethodType mType) {
  1285. for (int i=0; i < tide; i++) {
  1286. if (methods[i].GetMethodType() == mType)
  1287. return methods[i].GetMethod();
  1288. }
  1289. return null;
  1290. }
  1291. public void RemoveMethod(MethodDef meth) {
  1292. bool found = false;
  1293. for (int i=0; i < tide; i++) {
  1294. if (found)
  1295. methods[i-1] = methods[i];
  1296. else if (methods[i].GetMethod() == meth)
  1297. found = true;
  1298. }
  1299. }
  1300. public void RemoveMethod(MethodType mType) {
  1301. bool found = false;
  1302. for (int i=0; i < tide; i++) {
  1303. if (found)
  1304. methods[i-1] = methods[i];
  1305. else if (methods[i].GetMethodType() == mType)
  1306. found = true;
  1307. }
  1308. }
  1309. internal void SetParent(ClassDef paren) {
  1310. parent = paren;
  1311. }
  1312. internal ClassDef GetParent() {
  1313. return parent;
  1314. }
  1315. }
  1316. /*****************************************************************************/
  1317. /// <summary>
  1318. /// Descriptor for an event
  1319. /// </summary>
  1320. public class Event : Feature {
  1321. Type eventType;
  1322. uint typeIx = 0;
  1323. /*-------------------- Constructors ---------------------------------*/
  1324. internal Event(string name, Type eType, ClassDef parent)
  1325. : base(name, parent) {
  1326. eventType = eType;
  1327. tabIx = MDTable.Event;
  1328. }
  1329. internal Event(PEReader buff) {
  1330. flags = buff.ReadUInt16();
  1331. name = buff.GetString();
  1332. typeIx = buff.GetCodedIndex(CIx.TypeDefOrRef);
  1333. tabIx = MDTable.Event;
  1334. }
  1335. internal static void Read(PEReader buff, TableRow[] events) {
  1336. for (int i=0; i < events.Length; i++)
  1337. events[i] = new Event(buff);
  1338. }
  1339. internal static string[] ReadNames(PEReader buff, ClassDef theClass, uint classIx) {
  1340. return Feature.GetFeatureNames(buff,MDTable.Event,MDTable.EventMap,theClass,classIx);
  1341. }
  1342. internal override void Resolve(PEReader buff) {
  1343. eventType = (Type)buff.GetCodedElement(CIx.TypeDefOrRef,typeIx);
  1344. }
  1345. /*------------------------- public set and get methods --------------------------*/
  1346. public Type GetEventType() { return eventType; }
  1347. /*----------------------------- internal functions ------------------------------*/
  1348. internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) {
  1349. throw new NotYetImplementedException("Merge for Events");
  1350. }
  1351. internal sealed override void BuildTables(MetaDataOut md) {
  1352. md.AddToTable(MDTable.Event,this);
  1353. nameIx = md.AddToStringsHeap(name);
  1354. eventType.BuildMDTables(md);
  1355. for (int i=0; i < tide; i++) {
  1356. methods[i].BuildMDTables(md);
  1357. }
  1358. }
  1359. internal override void BuildCILInfo(CILWriter output) {
  1360. eventType.BuildCILInfo(output);
  1361. }
  1362. internal static uint Size(MetaData md) {
  1363. return 2 + md.StringsIndexSize() + md.CodedIndexSize(CIx.TypeDefOrRef);
  1364. }
  1365. internal sealed override void Write(PEWriter output) {
  1366. output.Write(flags);
  1367. output.StringsIndex(nameIx);
  1368. output.WriteCodedIndex(CIx.TypeDefOrRef,eventType);
  1369. }
  1370. internal override void Write(CILWriter output) {
  1371. throw new NotYetImplementedException("Write CIL for event");
  1372. }
  1373. internal sealed override uint GetCodedIx(CIx code) {
  1374. switch (code) {
  1375. case (CIx.HasCustomAttr) : return 10;
  1376. case (CIx.HasSemantics) : return 0;
  1377. }
  1378. return 0;
  1379. }
  1380. }
  1381. /**************************************************************************/
  1382. /// <summary>
  1383. /// Descriptor for the Property of a class
  1384. /// </summary>
  1385. public class Property : Feature {
  1386. internal static readonly byte PropertyTag = 0x8;
  1387. Constant constVal;
  1388. uint typeBlobIx = 0;
  1389. Type[] parList;
  1390. Type returnType;
  1391. uint numPars = 0;
  1392. /*-------------------- Constructors ---------------------------------*/
  1393. internal Property(string name, Type retType, Type[] pars, ClassDef parent) : base(name, parent) {
  1394. returnType = retType;
  1395. parList = pars;
  1396. if (pars != null) numPars = (uint)pars.Length;
  1397. tabIx = MDTable.Property;
  1398. }
  1399. internal Property(PEReader buff) {
  1400. flags = buff.ReadUInt16();
  1401. name = buff.GetString();
  1402. typeBlobIx = buff.GetBlobIx();
  1403. tabIx = MDTable.Property;
  1404. }
  1405. internal static void Read(PEReader buff, TableRow[] props) {
  1406. for (int i=0; i < props.Length; i++)
  1407. props[i] = new Property(buff);
  1408. }
  1409. internal static string[] ReadNames(PEReader buff, ClassDef theClass, uint classIx) {
  1410. return Feature.GetFeatureNames(buff,MDTable.Property,MDTable.PropertyMap,theClass,classIx);
  1411. }
  1412. internal sealed override void Resolve(PEReader buff) {
  1413. buff.ReadPropertySig(typeBlobIx,this);
  1414. }
  1415. /// <summary>
  1416. /// Add an initial value for this property
  1417. /// </summary>
  1418. /// <param name="constVal">the initial value for this property</param>
  1419. public void AddInitValue(Constant constVal) {
  1420. this.constVal = constVal;
  1421. }
  1422. public Constant GetInitValue() { return constVal; }
  1423. public void RemoveInitValue() { constVal = null; }
  1424. public Type GetPropertyType() { return returnType; }
  1425. public void SetPropertyType(Type pType) { returnType = pType; }
  1426. public Type[] GetPropertyParams() { return parList; }
  1427. public void SetPropertyParams(Type[] parTypes) {
  1428. parList = parTypes;
  1429. if (parList != null) numPars = (uint)parList.Length;
  1430. }
  1431. internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) {
  1432. throw new NotYetImplementedException("Merge for Properties");
  1433. }
  1434. internal sealed override void BuildTables(MetaDataOut md) {
  1435. md.AddToTable(MDTable.Property,this);
  1436. nameIx = md.AddToStringsHeap(name);
  1437. for (int i=0; i < numPars; i++)
  1438. parList[i].BuildMDTables(md);
  1439. for (int i=0; i < tide; i++)
  1440. methods[i].BuildMDTables(md);
  1441. if (constVal != null) {
  1442. ConstantElem constElem = new ConstantElem(this,constVal);
  1443. constElem.BuildMDTables(md);
  1444. }
  1445. }
  1446. internal sealed override void BuildSignatures(MetaDataOut md) {
  1447. MemoryStream sig = new MemoryStream();
  1448. sig.WriteByte(PropertyTag);
  1449. MetaDataOut.CompressNum(numPars,sig);
  1450. returnType.TypeSig(sig);
  1451. for (int i=0; i < numPars; i++) {
  1452. parList[i].BuildSignatures(md);
  1453. parList[i].TypeSig(sig);
  1454. }
  1455. typeBlobIx = md.AddToBlobHeap(sig.ToArray());
  1456. done = false;
  1457. }
  1458. internal override void BuildCILInfo(CILWriter output) {
  1459. returnType.BuildCILInfo(output);
  1460. for (int i=0; i < numPars; i++) {
  1461. parList[i].BuildCILInfo(output);
  1462. }
  1463. }
  1464. internal static uint Size(MetaData md) {
  1465. return 2 + md.StringsIndexSize() + md.BlobIndexSize();
  1466. }
  1467. internal sealed override void Write(PEWriter output) {
  1468. output.Write(flags);
  1469. output.StringsIndex(nameIx);
  1470. output.BlobIndex(typeBlobIx);
  1471. }
  1472. internal override void Write(CILWriter output) {
  1473. throw new NotYetImplementedException("Write CIL for property");
  1474. }
  1475. internal sealed override uint GetCodedIx(CIx code) {
  1476. switch (code) {
  1477. case (CIx.HasCustomAttr) : return 9;
  1478. case (CIx.HasConstant) : return 2;
  1479. case (CIx.HasSemantics) : return 1;
  1480. }
  1481. return 0;
  1482. }
  1483. }
  1484. /**************************************************************************/
  1485. /// <summary>
  1486. /// Descriptor for layout information for a field
  1487. /// </summary>
  1488. public class FieldLayout : MetaDataElement {
  1489. FieldDef field;
  1490. uint offset, fieldIx = 0;
  1491. /*-------------------- Constructors ---------------------------------*/
  1492. internal FieldLayout(FieldDef field, uint offset) {
  1493. this.field = field;
  1494. this.offset = offset;
  1495. tabIx = MDTable.FieldLayout;
  1496. }
  1497. internal FieldLayout(PEReader buff) {
  1498. offset = buff.ReadUInt32();
  1499. fieldIx = buff.GetIndex(MDTable.Field);
  1500. tabIx = MDTable.FieldLayout;
  1501. }
  1502. internal static void Read(PEReader buff, TableRow[] layouts) {
  1503. for (int i=0; i < layouts.Length; i++)
  1504. layouts[i] = new FieldLayout(buff);
  1505. }
  1506. internal sealed override void Resolve(PEReader buff) {
  1507. field = (FieldDef)buff.GetElement(MDTable.Field,fieldIx);
  1508. field.SetOffset(offset);
  1509. }
  1510. internal sealed override void BuildTables(MetaDataOut md) {
  1511. md.AddToTable(MDTable.FieldLayout,this);
  1512. }
  1513. internal static uint Size(MetaData md) {
  1514. return 4 + md.TableIndexSize(MDTable.Field);
  1515. }
  1516. internal sealed override void Write(PEWriter output) {
  1517. output.Write(offset);
  1518. output.WriteIndex(MDTable.Field,field.Row);
  1519. }
  1520. }
  1521. /*****************************************************************************/
  1522. /// <summary>
  1523. /// Marshalling information for a field or param
  1524. /// </summary>
  1525. public class FieldMarshal : MetaDataElement {
  1526. MetaDataElement field;
  1527. NativeType nt;
  1528. uint ntIx, parentIx;
  1529. /*-------------------- Added by Carlo Kok ---------------------------------*/
  1530. private SafeArrayType safeArraySubType;
  1531. public SafeArrayType SafeArraySubType { get { return safeArraySubType; ; } set { safeArraySubType = value; } }
  1532. private string safeArrayUserDefinedSubType;
  1533. public string SafeArrayUserDefinedSubType { get { return safeArrayUserDefinedSubType; } set { safeArrayUserDefinedSubType = value; } }
  1534. private NativeTypeIx arraySubType = (NativeTypeIx)0x50; // default, important
  1535. public NativeTypeIx ArraySubType { get { return arraySubType; } set { arraySubType = value; } }
  1536. private int sizeConst = -1;
  1537. public int SizeConst { get { return sizeConst; } set { sizeConst = value; } }
  1538. private int sizeParamIndex = -1;
  1539. public int SizeParamIndex { get { return sizeParamIndex; } set { sizeParamIndex = value; } }
  1540. private string customMarshallingType;
  1541. public string CustomMarshallingType { get { return customMarshallingType; } set { customMarshallingType = value; } }
  1542. private string customMarshallingCookie;
  1543. public string CustomMarshallingCookie { get { return customMarshallingCookie; } set { customMarshallingCookie = value; } }
  1544. /*-------------------- Constructors ---------------------------------*/
  1545. internal FieldMarshal(MetaDataElement field, NativeType nType) {
  1546. this.field = field;
  1547. this.nt = nType;
  1548. sortTable = true;
  1549. tabIx = MDTable.FieldMarshal;
  1550. }
  1551. internal FieldMarshal(PEReader buff) {
  1552. parentIx = buff.GetCodedIndex(CIx.HasFieldMarshal);
  1553. ntIx = buff.GetBlobIx();
  1554. sortTable = true;
  1555. tabIx = MDTable.FieldMarshal;
  1556. }
  1557. internal static void Read(PEReader buff, TableRow[] fMarshal) {
  1558. for (int i=0; i < fMarshal.Length; i++)
  1559. fMarshal[i] = new FieldMarshal(buff);
  1560. }
  1561. internal override void Resolve(PEReader buff) {
  1562. field = buff.GetCodedElement(CIx.HasFieldMarshal,parentIx);
  1563. nt = buff.GetBlobNativeType(ntIx);
  1564. if (field is FieldDef) {
  1565. ((FieldDef)field).SetMarshalType(nt);
  1566. } else {
  1567. ((Param)field).SetMarshalType(nt);
  1568. }
  1569. }
  1570. internal override uint SortKey() {
  1571. return (field.Row << MetaData.CIxShiftMap[(uint)CIx.HasFieldMarshal])
  1572. | field.GetCodedIx(CIx.HasFieldMarshal);
  1573. }
  1574. internal sealed override void BuildTables(MetaDataOut md) {
  1575. md.AddToTable(MDTable.FieldMarshal,this);
  1576. ntIx = md.AddToBlobHeap(nt.ToBlob());
  1577. }
  1578. internal static uint Size(MetaData md) {
  1579. return md.CodedIndexSize(CIx.HasFieldMarshal) + md.BlobIndexSize();
  1580. }
  1581. internal sealed override void Write(PEWriter output) {
  1582. output.WriteCodedIndex(CIx.HasFieldMarshal,field);
  1583. output.BlobIndex(ntIx);
  1584. }
  1585. }
  1586. /**************************************************************************/
  1587. /// <summary>
  1588. /// Descriptor for the address of a field's value in the PE file
  1589. /// </summary>
  1590. public class FieldRVA : MetaDataElement {
  1591. FieldDef field;
  1592. DataConstant data;
  1593. uint rva = 0, fieldIx = 0;
  1594. /*-------------------- Constructors ---------------------------------*/
  1595. internal FieldRVA(FieldDef field, DataConstant data) {
  1596. this.field = field;
  1597. this.data = data;
  1598. tabIx = MDTable.FieldRVA;
  1599. }
  1600. internal FieldRVA(PEReader buff) {
  1601. rva = buff.ReadUInt32();
  1602. fieldIx = buff.GetIndex(MDTable.Field);
  1603. tabIx = MDTable.FieldRVA;
  1604. }
  1605. internal static void Read(PEReader buff, TableRow[] fRVAs) {
  1606. for (int i=0; i < fRVAs.Length; i++)
  1607. fRVAs[i] = new FieldRVA(buff);
  1608. }
  1609. internal sealed override void Resolve(PEReader buff) {
  1610. field = (FieldDef)buff.GetElement(MDTable.Field,fieldIx);
  1611. field.AddDataValue(buff.GetDataConstant(rva,field.GetFieldType()));
  1612. }
  1613. internal sealed override void BuildTables(MetaDataOut md) {
  1614. md.AddToTable(MDTable.FieldRVA,this);
  1615. md.AddData(data);
  1616. }
  1617. internal static uint Size(MetaData md) {
  1618. return 4 + md.TableIndexSize(MDTable.Field);
  1619. }
  1620. internal sealed override void Write(PEWriter output) {
  1621. output.WriteDataRVA(data.DataOffset);
  1622. output.WriteIndex(MDTable.Field,field.Row);
  1623. }
  1624. }
  1625. /**************************************************************************/
  1626. public abstract class FileRef : MetaDataElement {
  1627. protected static readonly uint HasMetaData = 0x0;
  1628. protected static readonly uint HasNoMetaData = 0x1;
  1629. protected uint nameIx = 0, hashIx = 0;
  1630. protected byte[] hashBytes;
  1631. protected string name;
  1632. protected bool entryPoint = false;
  1633. protected uint flags;
  1634. /*-------------------- Constructors ---------------------------------*/
  1635. internal FileRef(string name, byte[] hashBytes) {
  1636. this.hashBytes = hashBytes;
  1637. this.name = name;
  1638. tabIx = MDTable.File;
  1639. }
  1640. internal FileRef(PEReader buff) {
  1641. flags = buff.ReadUInt32();
  1642. name = buff.GetString();
  1643. hashBytes = buff.GetBlob();
  1644. tabIx = MDTable.File;
  1645. }
  1646. internal static void Read(PEReader buff, TableRow[] files) {
  1647. for (int i=0; i < files.Length; i++) {
  1648. uint flags = buff.ReadUInt32();
  1649. if (flags == HasMetaData)
  1650. files[i] = new ModuleFile(buff.GetString(),buff.GetBlob());
  1651. else
  1652. files[i] = new ResourceFile(buff.GetString(),buff.GetBlob());
  1653. }
  1654. }
  1655. public string Name() { return name; }
  1656. public byte[] GetHash() { return hashBytes; }
  1657. internal sealed override void BuildTables(MetaDataOut md) {
  1658. md.AddToTable(MDTable.File,this);
  1659. nameIx = md.AddToStringsHeap(name);
  1660. hashIx = md.AddToBlobHeap(hashBytes);
  1661. if (entryPoint) md.SetEntryPoint(this);
  1662. }
  1663. internal static uint Size(MetaData md) {
  1664. return 4 + md.StringsIndexSize() + md.BlobIndexSize();
  1665. }
  1666. internal sealed override void Write(PEWriter output) {
  1667. output.Write(flags);
  1668. output.StringsIndex(nameIx);
  1669. output.BlobIndex(hashIx);
  1670. }
  1671. internal sealed override uint GetCodedIx(CIx code) {
  1672. switch (code) {
  1673. case (CIx.HasCustomAttr) : return 16;
  1674. case (CIx.Implementation) : return 0;
  1675. }
  1676. return 0;
  1677. }
  1678. }
  1679. /**************************************************************************/
  1680. /// <summary>
  1681. /// Descriptor for a file referenced in THIS assembly/module (.file)
  1682. /// </summary>
  1683. internal class ModuleFile : FileRef {
  1684. internal ModuleRef fileModule;
  1685. internal ModuleFile(string name, byte[] hashBytes, bool entryPoint) : base(name,hashBytes){
  1686. flags = HasMetaData;
  1687. this.entryPoint = entryPoint;
  1688. }
  1689. internal ModuleFile(string name, byte[] hashBytes) : base(name,hashBytes) {
  1690. flags = HasMetaData;
  1691. }
  1692. internal void SetEntryPoint() { entryPoint = true; }
  1693. internal void SetHash(byte[] hashVal) { hashBytes = hashVal; }
  1694. }
  1695. /**************************************************************************/
  1696. /// <summary>
  1697. /// Descriptor for a file containing a managed resource
  1698. /// </summary>
  1699. public class ResourceFile : FileRef {
  1700. static ArrayList files = new ArrayList();
  1701. /*-------------------- Constructors ---------------------------------*/
  1702. public ResourceFile(string name, byte[] hashValue) : base(name,hashValue) {
  1703. flags = HasNoMetaData;
  1704. files.Add(this);
  1705. }
  1706. public static ResourceFile GetFile(string name) {
  1707. for (int i=0; i < files.Count; i++) {
  1708. if (((ResourceFile)files[i]).name.Equals(name))
  1709. return (ResourceFile)files[i];
  1710. }
  1711. return null;
  1712. }
  1713. }
  1714. /**************************************************************************/
  1715. /// <summary>
  1716. /// Descriptor for
  1717. /// </summary>
  1718. public class GenericParam : Type {
  1719. private static readonly byte VAR = 0x13;
  1720. private static readonly byte MVAR = 0x1E;
  1721. ushort flags, index, kind = 0;
  1722. uint parentIx, nameIx;
  1723. string name;
  1724. MetaDataElement parent;
  1725. private ArrayList constraints = new ArrayList();
  1726. internal static bool extraField = true;
  1727. /*-------------------- Constructors ---------------------------------*/
  1728. private GenericParam(uint index, byte elemIx) : base(elemIx) {
  1729. this.index = (ushort)index;
  1730. sortTable = true;
  1731. }
  1732. internal GenericParam(string name, MetaDataElement parent, int index) : base(VAR) {
  1733. this.name = name;
  1734. this.parent = parent;
  1735. this.index = (ushort)index;
  1736. if (parent is Method) typeIndex = MVAR;
  1737. sortTable = true;
  1738. tabIx = MDTable.GenericParam;
  1739. }
  1740. internal GenericParam(PEReader buff) : base(VAR) {
  1741. index = buff.ReadUInt16();
  1742. flags = buff.ReadUInt16();
  1743. parentIx = buff.GetCodedIndex(CIx.TypeOrMethodDef);
  1744. name = buff.GetString();
  1745. if (extraField) kind = buff.ReadUInt16();
  1746. sortTable = true;
  1747. tabIx = MDTable.GenericParam;
  1748. // resolve generic param immediately for signature resolution
  1749. parent = buff.GetCodedElement(CIx.TypeOrMethodDef,parentIx);
  1750. if (parent != null) {
  1751. if (parent is MethodDef) {
  1752. typeIndex = MVAR;
  1753. ((MethodDef)parent).AddGenericParam(this);
  1754. } else {
  1755. ((ClassDef)parent).AddGenericParam(this);
  1756. }
  1757. }
  1758. }
  1759. internal GenericParam(string name) : base(MVAR) {
  1760. this.name = name;
  1761. sortTable = true;
  1762. tabIx = MDTable.GenericParam;
  1763. }
  1764. internal static GenericParam AnonMethPar(uint ix) {
  1765. return new GenericParam(ix,MVAR);
  1766. }
  1767. internal static GenericParam AnonClassPar(uint ix) {
  1768. return new GenericParam(ix,VAR);
  1769. }
  1770. internal static void Read(PEReader buff, TableRow[] gpars) {
  1771. for (int i=0; i < gpars.Length; i++)
  1772. gpars[i] = new GenericParam(buff);
  1773. }
  1774. /*------------------------- public set and get methods --------------------------*/
  1775. /// <summary>
  1776. /// Set the attribute for this generic parameter
  1777. /// </summary>
  1778. /// <param name="attr">the attribute</param>
  1779. public void SetAttribute(GenericParamAttr attr) {
  1780. flags = (ushort)attr;
  1781. }
  1782. /// <summary>
  1783. /// Get the attribute for this generic parameter
  1784. /// </summary>
  1785. public GenericParamAttr GetAttribute() {
  1786. return (GenericParamAttr) flags;
  1787. }
  1788. /// <summary>
  1789. /// Add a type constraint to this generic parameter
  1790. /// </summary>
  1791. /// <param name="cType">class constraining the parameter type</param>
  1792. public void AddConstraint(Class cType) {
  1793. constraints.Add(cType);
  1794. }
  1795. /// <summary>
  1796. /// Remove a constraint from this generic parameter
  1797. /// </summary>
  1798. /// <param name="cType">class type of constraint</param>
  1799. public void RemoveConstraint(Class cType) {
  1800. for (int i=0; i < constraints.Count; i++) {
  1801. if (constraints[i] == cType) {
  1802. constraints.RemoveAt(i);
  1803. return;
  1804. }
  1805. }
  1806. }
  1807. /// <summary>
  1808. /// Return a constraint from the list
  1809. /// </summary>
  1810. /// <param name="i">constraint index</param>
  1811. /// <returns></returns>
  1812. public Class GetConstraint(int i) {
  1813. return (Class)constraints[i];
  1814. }
  1815. /// <summary>
  1816. /// Get the number of constrains on this GenericParam
  1817. /// </summary>
  1818. /// <returns></returns>
  1819. public int GetConstraintCount() {
  1820. return constraints.Count;
  1821. }
  1822. /// <summary>
  1823. /// Get the name of this generic parameter
  1824. /// </summary>
  1825. /// <returns>generic parameter name</returns>
  1826. public string GetName() { return name; }
  1827. public MetaDataElement GetParent() { return parent; }
  1828. public Class[] GetClassConstraints() {
  1829. return (Class[])constraints.ToArray(typeof(Class)); // KJG 20-May-2005
  1830. }
  1831. /*----------------------------- internal functions ------------------------------*/
  1832. internal uint Index {
  1833. get { return index; }
  1834. set { index = (ushort)value; }
  1835. }
  1836. internal void SetClassParam(Class paren, int ix) {
  1837. typeIndex = VAR;
  1838. parent = paren;
  1839. index = (ushort)ix;
  1840. }
  1841. internal void SetMethParam(Method paren,int ix) {
  1842. typeIndex = MVAR;
  1843. parent = paren;
  1844. index = (ushort)ix;
  1845. }
  1846. internal void CheckParent(MethodDef paren, PEReader buff) {
  1847. if (paren == buff.GetCodedElement(CIx.TypeOrMethodDef,parentIx)) {
  1848. parent = paren;
  1849. paren.InsertGenericParam(this);
  1850. }
  1851. }
  1852. internal override void TypeSig(MemoryStream str) {
  1853. str.WriteByte(typeIndex);
  1854. str.WriteByte((byte)index);
  1855. }
  1856. internal static uint Size(MetaData md) {
  1857. if (extraField)
  1858. return 6 + md.CodedIndexSize(CIx.TypeOrMethodDef) + md.StringsIndexSize();
  1859. else
  1860. return 4 + md.CodedIndexSize(CIx.TypeOrMethodDef) + md.StringsIndexSize();
  1861. }
  1862. internal override Type AddTypeSpec(MetaDataOut md) {
  1863. // check that this generic parameter belongs to the "current" method ??
  1864. GenericParTypeSpec tSpec = new GenericParTypeSpec(this);
  1865. md.AddToTable(MDTable.TypeSpec,tSpec);
  1866. return tSpec;
  1867. }
  1868. internal override uint SortKey() {
  1869. return (parent.Row << MetaData.CIxShiftMap[(uint)CIx.TypeOrMethodDef])
  1870. | parent.GetCodedIx(CIx.TypeOrMethodDef);
  1871. }
  1872. internal override void BuildTables(MetaDataOut md) {
  1873. if (parent is MethodRef || parent is ClassRef) return; // don't add it - fix by CK
  1874. md.AddToTable(MDTable.GenericParam,this);
  1875. nameIx = md.AddToStringsHeap(name);
  1876. for (int i=0; i < constraints.Count; i++) {
  1877. Class cClass = (Class)constraints[i];
  1878. constraints[i] = new GenericParamConstraint(this,cClass);
  1879. if (cClass is ClassRef) cClass.BuildMDTables(md);
  1880. // Fix by CK - should be BuildTables too??
  1881. if (cClass is ClassSpec) md.AddToTable(MDTable.TypeSpec, cClass);
  1882. }
  1883. }
  1884. internal override void BuildCILInfo(CILWriter output) {
  1885. for (int i = 0; i < constraints.Count; i++) {
  1886. Class cClass = (Class)constraints[i];
  1887. if (!cClass.isDef()) {
  1888. cClass.BuildCILInfo(output);
  1889. }
  1890. }
  1891. }
  1892. internal void AddConstraints(MetaDataOut md) {
  1893. for (int i=0; i < constraints.Count; i++) {
  1894. md.AddToTable(MDTable.GenericParamConstraint,(GenericParamConstraint)constraints[i]);
  1895. }
  1896. }
  1897. internal override void Write(PEWriter output) {
  1898. output.Write(index);
  1899. output.Write(flags);
  1900. output.WriteCodedIndex(CIx.TypeOrMethodDef,parent);
  1901. output.StringsIndex(nameIx);
  1902. if (extraField) output.Write(kind);
  1903. }
  1904. }
  1905. /**************************************************************************/
  1906. /// <summary>
  1907. /// Descriptor for GenericParamConstraint
  1908. /// </summary>
  1909. public class GenericParamConstraint : MetaDataElement {
  1910. uint parentIx, constraintIx;
  1911. GenericParam parent;
  1912. Class constraint;
  1913. /*-------------------- Constructors ---------------------------------*/
  1914. public GenericParamConstraint(GenericParam parent, Class constraint) {
  1915. this.parent = parent;
  1916. this.constraint = constraint;
  1917. tabIx = MDTable.GenericParamConstraint;
  1918. }
  1919. internal GenericParamConstraint(PEReader buff) {
  1920. parentIx = buff.GetIndex(MDTable.GenericParam);
  1921. constraintIx = buff.GetCodedIndex(CIx.TypeDefOrRef);
  1922. tabIx = MDTable.GenericParamConstraint;
  1923. }
  1924. internal static void Read(PEReader buff, TableRow[] gpars) {
  1925. for (int i=0; i < gpars.Length; i++)
  1926. gpars[i] = new GenericParamConstraint(buff);
  1927. }
  1928. internal override void Resolve(PEReader buff) {
  1929. parent = (GenericParam)buff.GetElement(MDTable.GenericParam,parentIx);
  1930. parent.AddConstraint((Class)buff.GetCodedElement(CIx.TypeDefOrRef,constraintIx));
  1931. }
  1932. internal static uint Size(MetaData md) {
  1933. return md.TableIndexSize(MDTable.GenericParam) + md.CodedIndexSize(CIx.TypeDefOrRef);
  1934. }
  1935. internal override void Write(PEWriter output) {
  1936. output.WriteIndex(MDTable.GenericParam,parent.Row);
  1937. output.WriteCodedIndex(CIx.TypeDefOrRef,constraint);
  1938. }
  1939. }
  1940. /**************************************************************************/
  1941. /// <summary>
  1942. /// Descriptor for an Instantiation of a generic method
  1943. /// </summary>
  1944. public class MethodSpec : Method {
  1945. Method methParent;
  1946. uint instIx;
  1947. Type[] instTypes;
  1948. internal static byte GENERICINST = 0x0A;
  1949. /*-------------------- Constructors ---------------------------------*/
  1950. public MethodSpec(Method mParent, Type[] instTypes) : base(null) {
  1951. this.methParent = mParent;
  1952. this.instTypes = instTypes;
  1953. tabIx = MDTable.MethodSpec;
  1954. }
  1955. internal MethodSpec(PEReader buff) : base(null) {
  1956. parentIx = buff.GetCodedIndex(CIx.MethodDefOrRef);
  1957. instIx = buff.GetBlobIx();
  1958. tabIx = MDTable.MethodSpec;
  1959. this.unresolved = true;
  1960. }
  1961. internal static void Read(PEReader buff, TableRow[] specs) {
  1962. for (int i=0; i < specs.Length; i++)
  1963. specs[i] = new MethodSpec(buff);
  1964. }
  1965. internal override void Resolve(PEReader buff) {
  1966. methParent = (Method)buff.GetCodedElement(CIx.MethodDefOrRef,parentIx);
  1967. buff.currentMethodScope = methParent; // set scopes - Fix by CK
  1968. buff.currentClassScope = (Class)methParent.GetParent();
  1969. instTypes = buff.ReadMethSpecSig(instIx);
  1970. this.unresolved = false;
  1971. buff.currentMethodScope = null;
  1972. buff.currentClassScope = null;
  1973. }
  1974. internal override void TypeSig(MemoryStream str) {
  1975. str.WriteByte(GENERICINST);
  1976. MetaDataOut.CompressNum((uint)instTypes.Length,str);
  1977. for (int i=0; i < instTypes.Length; i++) {
  1978. instTypes[i].TypeSig(str);
  1979. }
  1980. }
  1981. internal static uint Size(MetaData md) {
  1982. return md.CodedIndexSize(CIx.MethodDefOrRef) + md.BlobIndexSize();
  1983. }
  1984. internal override void BuildTables(MetaDataOut md) {
  1985. md.AddToTable(MDTable.MethodSpec,this);
  1986. if (!(methParent is MethodDef)) // Never build a method def
  1987. methParent.BuildMDTables(md);
  1988. for (int i=0; i < instTypes.Length; i++) {
  1989. instTypes[i].BuildMDTables(md);
  1990. }
  1991. }
  1992. internal override void BuildSignatures(MetaDataOut md) {
  1993. MemoryStream outSig = new MemoryStream();
  1994. TypeSig(outSig);
  1995. instIx = md.AddToBlobHeap(outSig.ToArray());
  1996. }
  1997. internal override void Write(PEWriter output) {
  1998. output.WriteCodedIndex(CIx.MethodDefOrRef,methParent);
  1999. output.BlobIndex(instIx);
  2000. }
  2001. /*-------------------- Public Methods ------------------------------*/
  2002. public Type[] GetGenericParamTypes() { // KJG 15 July 2005
  2003. return instTypes;
  2004. }
  2005. public Method GetMethParent() { // KJG 15 July 2005
  2006. return methParent;
  2007. }
  2008. }
  2009. /**************************************************************************/
  2010. /// <summary>
  2011. /// Descriptor for pinvoke information for a method
  2012. /// </summary>
  2013. public class ImplMap : MetaDataElement {
  2014. private static readonly ushort NoMangle = 0x01;
  2015. ushort flags;
  2016. MethodDef meth;
  2017. string importName;
  2018. uint iNameIx, scopeIx = 0, memForIndex = 0;
  2019. ModuleRef importScope;
  2020. /*-------------------- Constructors ---------------------------------*/
  2021. internal ImplMap(ushort flag, MethodDef implMeth, string iName, ModuleRef mScope) {
  2022. flags = flag;
  2023. meth = implMeth;
  2024. importName = iName;
  2025. importScope = mScope;
  2026. tabIx = MDTable.ImplMap;
  2027. if (iName == null) flags |= NoMangle;
  2028. sortTable = true;
  2029. //throw(new NotYetImplementedException("PInvoke "));
  2030. }
  2031. internal ImplMap(PEReader buff) {
  2032. flags = buff.ReadUInt16();
  2033. memForIndex = buff.GetCodedIndex(CIx.MemberForwarded);
  2034. importName = buff.GetString();
  2035. scopeIx = buff.GetIndex(MDTable.ModuleRef);
  2036. sortTable = true;
  2037. tabIx = MDTable.ImplMap;
  2038. }
  2039. internal static void Read(PEReader buff, TableRow[] impls) {
  2040. for (int i=0; i < impls.Length; i++)
  2041. impls[i] = new ImplMap(buff);
  2042. }
  2043. internal override void Resolve(PEReader buff) {
  2044. meth = (MethodDef)buff.GetCodedElement(CIx.MemberForwarded,memForIndex);
  2045. importScope = (ModuleRef)buff.GetElement(MDTable.ModuleRef,scopeIx);
  2046. if (meth != null) meth.AddPInvokeInfo(this);
  2047. }
  2048. internal override uint SortKey() {
  2049. return (meth.Row << MetaData.CIxShiftMap[(uint)CIx.MemberForwarded])
  2050. | meth.GetCodedIx(CIx.MemberForwarded);
  2051. }
  2052. internal sealed override void BuildTables(MetaDataOut md) {
  2053. md.AddToTable(MDTable.ImplMap,this);
  2054. iNameIx = md.AddToStringsHeap(importName);
  2055. importScope.BuildMDTables(md);
  2056. }
  2057. internal static uint Size(MetaData md) {
  2058. return 2+ md.CodedIndexSize(CIx.MemberForwarded) +
  2059. md.StringsIndexSize() + md.TableIndexSize(MDTable.ModuleRef);
  2060. }
  2061. internal sealed override void Write(PEWriter output) {
  2062. output.Write(flags);
  2063. output.WriteCodedIndex(CIx.MemberForwarded,meth);
  2064. output.StringsIndex(iNameIx);
  2065. output.WriteIndex(MDTable.ModuleRef,importScope.Row);
  2066. }
  2067. }
  2068. /**************************************************************************/
  2069. /// <summary>
  2070. /// Descriptor for interface implemented by a class
  2071. /// </summary>
  2072. public class InterfaceImpl: MetaDataElement {
  2073. ClassDef theClass;
  2074. Class theInterface;
  2075. uint classIx = 0, interfacesIndex = 0;
  2076. /*-------------------- Constructors ---------------------------------*/
  2077. internal InterfaceImpl(ClassDef theClass, Class theInterface) {
  2078. this.theClass = theClass;
  2079. this.theInterface = theInterface;
  2080. tabIx = MDTable.InterfaceImpl;
  2081. }
  2082. internal InterfaceImpl(ClassDef theClass, TableRow theInterface) {
  2083. this.theClass = theClass;
  2084. this.theInterface = (Class)theInterface;
  2085. tabIx = MDTable.InterfaceImpl;
  2086. }
  2087. internal InterfaceImpl(PEReader buff) {
  2088. classIx = buff.GetIndex(MDTable.TypeDef);
  2089. interfacesIndex = buff.GetCodedIndex(CIx.TypeDefOrRef);
  2090. tabIx = MDTable.InterfaceImpl;
  2091. }
  2092. internal override void Resolve(PEReader buff) {
  2093. theClass = (ClassDef)buff.GetElement(MDTable.TypeDef,classIx);
  2094. theInterface = (Class)buff.GetCodedElement(CIx.TypeDefOrRef,interfacesIndex);
  2095. theClass.AddImplementedInterface(this);
  2096. }
  2097. internal static void Read(PEReader buff, TableRow[] impls) {
  2098. for (int i=0; i < impls.Length; i++)
  2099. impls[i] = new InterfaceImpl(buff);
  2100. }
  2101. internal ClassDef TheClass() { return theClass; }
  2102. internal Class TheInterface() { return theInterface; }
  2103. internal sealed override void BuildTables(MetaDataOut md) {
  2104. md.AddToTable(MDTable.InterfaceImpl,this);
  2105. if (!theInterface.isDef()) theInterface.BuildMDTables(md);
  2106. if (theInterface is ClassSpec) md.AddToTable(MDTable.TypeSpec,theInterface);
  2107. }
  2108. internal static uint Size(MetaData md) {
  2109. return md.TableIndexSize(MDTable.TypeDef) +
  2110. md.CodedIndexSize(CIx.TypeDefOrRef);
  2111. }
  2112. internal sealed override void Write(PEWriter output) {
  2113. output.WriteIndex(MDTable.TypeDef,theClass.Row);
  2114. output.WriteCodedIndex(CIx.TypeDefOrRef,theInterface);
  2115. }
  2116. internal sealed override uint GetCodedIx(CIx code) { return 5; }
  2117. }
  2118. /**************************************************************************/
  2119. /// <summary>
  2120. /// Descriptor for resources used in this PE file NOT YET IMPLEMENTED
  2121. /// </summary>
  2122. public class ManifestResource : MetaDataElement {
  2123. private static readonly uint PublicResource = 0x1;
  2124. private static readonly uint PrivateResource = 0x2;
  2125. string mrName;
  2126. MetaDataElement impl; // can be AssemblyRef, ResourceFile or ModuleFile
  2127. uint fileOffset = 0;
  2128. uint nameIx = 0, implIx = 0;
  2129. uint flags = 0;
  2130. PEFile pefile;
  2131. byte[] resourceBytes;
  2132. /*-------------------- Constructors ---------------------------------*/
  2133. internal ManifestResource(PEFile pefile, string name, byte[] resBytes, bool isPub) {
  2134. InitResource(pefile,name,isPub);
  2135. this.resourceBytes = resBytes;
  2136. }
  2137. internal ManifestResource(PEFile pefile, string name, MetaDataElement fileRef, uint offset, bool isPub) {
  2138. InitResource(pefile,name,isPub);
  2139. impl = fileRef;
  2140. fileOffset = offset;
  2141. }
  2142. internal ManifestResource(PEFile pefile, ManifestResource mres, bool isPub) {
  2143. this.pefile = pefile;
  2144. mrName = mres.mrName;
  2145. flags = mres.flags;
  2146. this.impl = mres.impl;
  2147. this.fileOffset = mres.fileOffset;
  2148. this.resourceBytes = mres.resourceBytes;
  2149. }
  2150. internal ManifestResource(PEReader buff) {
  2151. fileOffset = buff.ReadUInt32();
  2152. flags = buff.ReadUInt32();
  2153. mrName = buff.GetString();
  2154. implIx = buff.GetCodedIndex(CIx.Implementation);
  2155. tabIx = MDTable.ManifestResource;
  2156. }
  2157. private void InitResource(PEFile pefile, string name, bool isPub) {
  2158. this.pefile = pefile;
  2159. mrName = name;
  2160. if (isPub) flags = PublicResource;
  2161. else flags = PrivateResource;
  2162. tabIx = MDTable.ManifestResource;
  2163. }
  2164. internal static void Read(PEReader buff, TableRow[] mrs) {
  2165. for (int i=0; i < mrs.Length; i++)
  2166. mrs[i] = new ManifestResource(buff);
  2167. }
  2168. internal override void Resolve(PEReader buff) {
  2169. impl = buff.GetCodedElement(CIx.Implementation,implIx);
  2170. if (impl == null) {
  2171. if (!buff.skipBody)
  2172. resourceBytes = buff.GetResource(fileOffset);
  2173. }
  2174. }
  2175. /*------------------------- public set and get methods --------------------------*/
  2176. public string Name {
  2177. get { return mrName; }
  2178. set { mrName = value; }
  2179. }
  2180. public byte[] ResourceBytes {
  2181. get { return resourceBytes; }
  2182. set { resourceBytes = value; }
  2183. }
  2184. public AssemblyRef ResourceAssembly {
  2185. get { if (impl is AssemblyRef) return (AssemblyRef)impl; return null;}
  2186. set { impl = value; }
  2187. }
  2188. public ResourceFile ResFile {
  2189. get { if (impl is ResourceFile) return (ResourceFile) impl; return null;}
  2190. set { impl = value; }
  2191. }
  2192. public ModuleRef ResourceModule {
  2193. get { if (impl is ModuleFile) return ((ModuleFile)impl).fileModule; return null;}
  2194. set { impl = value.modFile; }
  2195. }
  2196. public uint FileOffset {
  2197. get { return fileOffset; }
  2198. set { fileOffset = value; }
  2199. }
  2200. public bool IsPublic {
  2201. get {
  2202. return flags == PublicResource;
  2203. }
  2204. set {
  2205. if (value)
  2206. flags = PublicResource;
  2207. else
  2208. flags = PrivateResource;
  2209. }
  2210. }
  2211. /*----------------------------- internal functions ------------------------------*/
  2212. internal sealed override void BuildTables(MetaDataOut md) {
  2213. md.AddToTable(MDTable.ManifestResource,this);
  2214. nameIx = md.AddToStringsHeap(mrName);
  2215. if (resourceBytes != null) {
  2216. if (impl != null)
  2217. throw new Exception("ERROR: Manifest Resource has byte value and file reference");
  2218. fileOffset = md.AddResource(resourceBytes);
  2219. } else {
  2220. if (impl == null)
  2221. throw new Exception("ERROR: Manifest Resource has no implementation or value");
  2222. impl.BuildMDTables(md);
  2223. }
  2224. }
  2225. internal static uint Size(MetaData md) {
  2226. return 8 + md.StringsIndexSize() +
  2227. md.CodedIndexSize(CIx.Implementation);
  2228. }
  2229. internal sealed override void Write(PEWriter output) {
  2230. output.Write(fileOffset);
  2231. output.Write(flags);
  2232. output.StringsIndex(nameIx);
  2233. output.WriteCodedIndex(CIx.Implementation,impl);
  2234. }
  2235. internal sealed override uint GetCodedIx(CIx code) { return 18; }
  2236. }
  2237. /**************************************************************************/
  2238. /// <summary>
  2239. /// Base class for elements in the PropertyMap, EventMap and
  2240. /// NestedClass MetaData tables
  2241. /// </summary>
  2242. public class MapElem : MetaDataElement {
  2243. ClassDef theClass, parent;
  2244. uint elemIx, classIx, endIx = 0;
  2245. /*-------------------- Constructors ---------------------------------*/
  2246. internal MapElem(ClassDef classDef, uint elIx, MDTable tableIx) {
  2247. theClass = classDef;
  2248. elemIx = elIx;
  2249. tabIx = tableIx;
  2250. sortTable = tabIx == MDTable.NestedClass;
  2251. }
  2252. internal MapElem(ClassDef classDef, ClassDef paren, MDTable tableIx) {
  2253. theClass = classDef;
  2254. parent = paren;
  2255. tabIx = tableIx;
  2256. sortTable = tabIx == MDTable.NestedClass;
  2257. }
  2258. internal MapElem(PEReader buff, MDTable tab) {
  2259. tabIx = tab;
  2260. classIx = buff.GetIndex(MDTable.TypeDef);
  2261. elemIx = buff.GetIndex(tab);
  2262. sortTable = tabIx == MDTable.NestedClass;
  2263. }
  2264. internal static void Read(PEReader buff, TableRow[] maps, MDTable tab) {
  2265. if (tab == MDTable.NestedClass) {
  2266. for (int i=0; i < maps.Length; i++) {
  2267. //maps[i] = new MapElem(buff,tab);
  2268. uint nestClassIx = buff.GetIndex(MDTable.TypeDef);
  2269. uint enclClassIx = buff.GetIndex(MDTable.TypeDef);
  2270. ClassDef parent = (ClassDef)buff.GetElement(MDTable.TypeDef,enclClassIx);
  2271. ClassDef nestClass = ((ClassDef)buff.GetElement(MDTable.TypeDef,nestClassIx)).MakeNestedClass(parent);
  2272. buff.InsertInTable(MDTable.TypeDef,nestClass.Row,nestClass);
  2273. }
  2274. } else { // event or property map
  2275. MapElem prev = new MapElem(buff,tab);
  2276. maps[0] = prev;
  2277. for (int i=1; i < maps.Length; i++) {
  2278. maps[i] = new MapElem(buff,tab);
  2279. prev.endIx = ((MapElem)maps[i]).elemIx;
  2280. prev = (MapElem)maps[i];
  2281. }
  2282. switch (tab) {
  2283. case MDTable.PropertyMap:
  2284. prev.endIx = buff.GetTableSize(MDTable.Property) + 1;
  2285. break;
  2286. case MDTable.EventMap:
  2287. prev.endIx = buff.GetTableSize(MDTable.Event) + 1;
  2288. break;
  2289. default:
  2290. prev.endIx = buff.GetTableSize(tab)+1;
  2291. break;
  2292. }
  2293. }
  2294. }
  2295. internal static void ReadNestedClassInfo(PEReader buff, uint num, uint[] parIxs) {
  2296. for (int i=0; i < parIxs.Length; i++) parIxs[i] = 0;
  2297. for (int i=0; i < num; i++) {
  2298. int ix = (int)buff.GetIndex(MDTable.TypeDef);
  2299. parIxs[ix-1] = buff.GetIndex(MDTable.TypeDef);
  2300. }
  2301. }
  2302. internal override void Resolve(PEReader buff) {
  2303. theClass = (ClassDef)buff.GetElement(MDTable.TypeDef,classIx);
  2304. if (tabIx == MDTable.EventMap) {
  2305. for (uint i=elemIx; i < endIx; i++)
  2306. theClass.AddEvent((Event)buff.GetElement(MDTable.Event,i));
  2307. } else if (tabIx == MDTable.PropertyMap) {
  2308. for (uint i=elemIx; i < endIx; i++)
  2309. theClass.AddProperty((Property)buff.GetElement(MDTable.Property,i));
  2310. } else { // must be nested class -- already done
  2311. //ClassDef parent = (ClassDef)buff.GetElement(MDTable.TypeDef,elemIx);
  2312. //parent.MakeNested(theClass);
  2313. }
  2314. }
  2315. internal static uint Size(MetaData md, MDTable tabIx) {
  2316. return md.TableIndexSize(MDTable.TypeDef) + md.TableIndexSize(tabIx);
  2317. }
  2318. internal override uint SortKey() {
  2319. return theClass.Row;
  2320. }
  2321. internal sealed override void BuildTables(MetaDataOut md) {
  2322. md.AddToTable(tabIx,this);
  2323. }
  2324. internal sealed override void Write(PEWriter output) {
  2325. output.WriteIndex(MDTable.TypeDef,theClass.Row);
  2326. if (parent != null)
  2327. output.WriteIndex(MDTable.TypeDef,parent.Row);
  2328. else
  2329. output.WriteIndex(tabIx,elemIx);
  2330. }
  2331. }
  2332. /**************************************************************************/
  2333. /// <summary>
  2334. /// Base class for field/methods (member of a class)
  2335. /// </summary>
  2336. public abstract class Member : MetaDataElement {
  2337. protected string name;
  2338. protected uint nameIx = 0, sigIx = 0;
  2339. protected byte[] signature;
  2340. protected uint parentIx = 0;
  2341. protected Class parent;
  2342. /*-------------------- Constructors ---------------------------------*/
  2343. internal Member(string memName, Class paren) {
  2344. name = memName;
  2345. parent = paren;
  2346. tabIx = MDTable.MemberRef;
  2347. }
  2348. internal Member(uint parenIx, string name, uint sIx) {
  2349. parentIx = parenIx;
  2350. this.name = name;
  2351. sigIx = sIx;
  2352. tabIx = MDTable.MemberRef;
  2353. }
  2354. internal Member(string name) {
  2355. this.name = name;
  2356. tabIx = MDTable.MemberRef;
  2357. }
  2358. internal static void ReadMember(PEReader buff, TableRow[] members) {
  2359. for (int i=0; i < members.Length; i++) {
  2360. uint parenIx = buff.GetCodedIndex(CIx.MemberRefParent);
  2361. string memName = buff.GetString();
  2362. uint sigIx = buff.GetBlobIx();
  2363. if (buff.FirstBlobByte(sigIx) == Field.FieldTag) // got a field
  2364. members[i] = new FieldRef(parenIx,memName,sigIx);
  2365. else
  2366. members[i] = new MethodRef(parenIx,memName,sigIx);
  2367. }
  2368. }
  2369. internal virtual Member ResolveParent(PEReader buff) { return null; }
  2370. public MetaDataElement GetParent() {
  2371. if (parent == null) return null;
  2372. if (parent.isSpecial())
  2373. return parent.GetParent();
  2374. return parent;
  2375. }
  2376. internal void SetParent(Class paren) {
  2377. parent = paren;
  2378. }
  2379. public string Name() { return name; }
  2380. public string QualifiedName() { return parent.TypeName() + "." + name; }
  2381. internal bool HasName(string name) {
  2382. return (this.name == name);
  2383. }
  2384. protected void WriteFlags(CILWriter output, uint flags) {
  2385. uint vis = (flags & 0x07); // visibility mask
  2386. switch (vis) {
  2387. case 0 : output.Write("compilercontrolled "); break;
  2388. case 1 : output.Write("private "); break;
  2389. case 2 : output.Write("famandassem "); break;
  2390. case 3 : output.Write("assembly "); break;
  2391. case 4 : output.Write("family "); break;
  2392. case 5 : output.Write("famorassem "); break;
  2393. case 6 : output.Write("public "); break;
  2394. }
  2395. if ((flags & (ushort)FieldAttr.Static) != 0) {
  2396. output.Write("static ");
  2397. }
  2398. if ((flags & (ushort)FieldAttr.Initonly) != 0) {
  2399. if (this is MethodDef) {
  2400. output.Write("final ");
  2401. } else {
  2402. output.Write("initonly ");
  2403. }
  2404. }
  2405. if ((flags & (ushort)FieldAttr.Literal) != 0) {
  2406. if (this is MethodDef) {
  2407. output.Write("virtual ");
  2408. } else {
  2409. output.Write("literal ");
  2410. }
  2411. }
  2412. if ((flags & (ushort)FieldAttr.Notserialized) != 0) {
  2413. if (this is MethodDef) {
  2414. output.Write("hidebysig ");
  2415. } else {
  2416. output.Write("notserialized ");
  2417. }
  2418. }
  2419. if (this is MethodDef) {
  2420. // more flags required here
  2421. if ((flags & (ushort)MethAttr.Abstract) != 0) {
  2422. output.Write("abstract ");
  2423. }
  2424. if ((flags & (ushort)MethAttr.SpecialName) != 0) {
  2425. output.Write("specialname ");
  2426. }
  2427. if ((flags & (ushort)MethAttr.RTSpecialName) != 0) {
  2428. output.Write("rtspecialname ");
  2429. }
  2430. } else {
  2431. // more flags required here
  2432. if ((flags & (ushort)FieldAttr.SpecialName) != 0) {
  2433. output.Write("specialname ");
  2434. }
  2435. if ((flags & (ushort)FieldAttr.RTSpecialName) != 0) {
  2436. output.Write("rtsspecialname ");
  2437. }
  2438. }
  2439. }
  2440. internal abstract void WriteType(CILWriter output);
  2441. }
  2442. /**************************************************************************/
  2443. /// <summary>
  2444. /// Descriptor for a field of a class
  2445. /// </summary>
  2446. public abstract class Field : Member {
  2447. internal static readonly byte FieldTag = 0x6;
  2448. protected Type type;
  2449. /*-------------------- Constructors ---------------------------------*/
  2450. internal Field(string pfName, Type pfType, Class paren) : base(pfName, paren) {
  2451. type = pfType;
  2452. }
  2453. internal override void Resolve(PEReader buff) {
  2454. if (type == null) {
  2455. buff.currentClassScope = parent;
  2456. type = buff.GetFieldType(sigIx);
  2457. buff.currentClassScope = null;
  2458. }
  2459. }
  2460. /*------------------------- public set and get methods --------------------------*/
  2461. /// <summary>
  2462. /// Get the type of this field
  2463. /// </summary>
  2464. /// <returns>Type descriptor for this field</returns>
  2465. public Type GetFieldType() { return type; }
  2466. /// <summary>
  2467. /// Set the type of this field
  2468. /// </summary>
  2469. /// <param name="ty">The type of the field</param>
  2470. public void SetFieldType(Type ty) { type = ty; }
  2471. /*----------------------------- internal functions ------------------------------*/
  2472. internal sealed override void BuildSignatures(MetaDataOut md) {
  2473. MemoryStream sig = new MemoryStream();
  2474. sig.WriteByte(FieldTag);
  2475. type.TypeSig(sig);
  2476. sigIx = md.AddToBlobHeap(sig.ToArray());
  2477. done = false;
  2478. }
  2479. internal override string NameString() {
  2480. return parent.NameString() + "." + name;
  2481. }
  2482. internal override void WriteType(CILWriter output) {
  2483. type.WriteType(output);
  2484. output.Write(" ");
  2485. parent.WriteName(output);
  2486. output.Write("::" + name);
  2487. }
  2488. }
  2489. /**************************************************************************/
  2490. /// <summary>
  2491. /// Descriptor for a field defined in a class of an assembly/module
  2492. /// </summary>
  2493. public class FieldDef : Field {
  2494. //private static readonly uint PInvokeImpl = 0x2000;
  2495. private static readonly ushort HasFieldMarshal = 0x1000;
  2496. private static readonly ushort HasFieldRVA = 0x100;
  2497. private static readonly ushort HasDefault = 0x8000;
  2498. private static readonly ushort NoFieldMarshal = 0xEFFF;
  2499. private static readonly ushort NoFieldRVA = 0xFEFF;
  2500. private static readonly ushort NoDefault = 0x7FFF;
  2501. internal FieldRef refOf;
  2502. DataConstant initVal;
  2503. Constant constVal;
  2504. NativeType marshalType;
  2505. ushort flags;
  2506. bool hasOffset = false;
  2507. uint offset;
  2508. /*-------------------- Constructors ---------------------------------*/
  2509. internal FieldDef(string name, Type fType, ClassDef paren) : base(name,fType,paren) {
  2510. tabIx = MDTable.Field;
  2511. }
  2512. internal FieldDef(FieldAttr attrSet, string name, Type fType,ClassDef paren) : base(name, fType,paren) {
  2513. flags = (ushort)attrSet;
  2514. tabIx = MDTable.Field;
  2515. }
  2516. internal FieldDef(FieldAttr attrSet, string name, Type fType, ClassSpec paren) : base(name, fType,paren) {
  2517. flags = (ushort)attrSet;
  2518. tabIx = MDTable.Field;
  2519. }
  2520. internal FieldDef(PEReader buff) : base(null,null,null) {
  2521. flags = buff.ReadUInt16();
  2522. name = buff.GetString();
  2523. sigIx = buff.GetBlobIx();
  2524. tabIx = MDTable.Field;
  2525. }
  2526. internal static void Read(PEReader buff, TableRow[] fields) {
  2527. for (int i=0; i < fields.Length; i++)
  2528. fields[i] = new FieldDef(buff);
  2529. }
  2530. internal static void GetFieldRefs(PEReader buff, uint num, ClassRef parent) {
  2531. for (int i=0; i < num; i++) {
  2532. uint flags = buff.ReadUInt16();
  2533. string name = buff.GetString();
  2534. uint sigIx = buff.GetBlobIx();
  2535. if ((flags & (uint)FieldAttr.Public) == (uint)FieldAttr.Public) {
  2536. if (parent.GetField(name) == null) {
  2537. //Console.WriteLine(parent.NameString());
  2538. buff.currentClassScope = parent;
  2539. FieldRef fRef = new FieldRef(parent,name,buff.GetFieldType(sigIx));
  2540. buff.currentClassScope = null;
  2541. parent.AddToFieldList(fRef);
  2542. }
  2543. }
  2544. }
  2545. }
  2546. internal void Resolve(PEReader buff, uint fIx) {
  2547. /*
  2548. if ((flags & HasFieldMarshal) != 0)
  2549. marshalType = FieldMarshal.FindMarshalType(buff,this,
  2550. buff.MakeCodedIndex(CIx.HasFieldMarshal,MDTable.Field,fIx));
  2551. if ((flags & HasFieldRVA) != 0)
  2552. initVal = FieldRVA.FindValue(buff,this,fIx);
  2553. if ((flags & HasDefault) != 0)
  2554. constVal = ConstantElem.FindConst(buff,this,
  2555. buff.MakeCodedIndex(CIx.HasConstant,MDTable.Field,fIx));
  2556. long offs = FieldLayout.FindLayout(buff,this,fIx);
  2557. if (offs > -1){
  2558. hasOffset = true;
  2559. offset = (uint)offs;
  2560. }
  2561. */
  2562. buff.currentClassScope = parent;
  2563. type = buff.GetFieldType(sigIx);
  2564. buff.currentClassScope = null;
  2565. }
  2566. /*------------------------- public set and get methods --------------------------*/
  2567. /// <summary>
  2568. /// Add an attribute(s) to this field
  2569. /// </summary>
  2570. /// <param name="fa">the attribute(s) to be added</param>
  2571. public void AddFieldAttr(FieldAttr fa) {
  2572. flags |= (ushort)fa;
  2573. }
  2574. public void SetFieldAttr(FieldAttr fa) {
  2575. flags = (ushort)fa;
  2576. }
  2577. public FieldAttr GetFieldAttr() {
  2578. return (FieldAttr)flags;
  2579. }
  2580. /// <summary>
  2581. /// Add a value for this field
  2582. /// </summary>
  2583. /// <param name="val">the value for the field</param>
  2584. public void AddValue(Constant val) {
  2585. flags |= HasDefault;
  2586. constVal = val;
  2587. }
  2588. /// <summary>
  2589. /// Retrieve the initial value for this field
  2590. /// </summary>
  2591. /// <returns>initial value</returns>
  2592. public Constant GetValue() { return constVal; }
  2593. /// <summary>
  2594. /// Remove the initial value from this field
  2595. /// </summary>
  2596. public void RemoveValue() {
  2597. constVal = null;
  2598. flags &= NoDefault;
  2599. }
  2600. /// <summary>
  2601. /// Add an initial value for this field (at dataLabel) (.data)
  2602. /// </summary>
  2603. /// <param name="val">the value for the field</param>
  2604. public void AddDataValue(DataConstant val) {
  2605. flags |= HasFieldRVA;
  2606. initVal = val;
  2607. }
  2608. /// <summary>
  2609. /// Get the value for this data constant
  2610. /// </summary>
  2611. /// <returns></returns>
  2612. public DataConstant GetDataValue() {
  2613. return initVal;
  2614. }
  2615. /// <summary>
  2616. /// Delete the value of this data constant
  2617. /// </summary>
  2618. public void RemoveDataValue() {
  2619. initVal = null;
  2620. flags &= NoFieldRVA;
  2621. }
  2622. /// <summary>
  2623. /// Set the offset of the field. Used for sequential or explicit classes.
  2624. /// (.field [offs])
  2625. /// </summary>
  2626. /// <param name="offs">field offset</param>
  2627. public void SetOffset(uint offs) {
  2628. offset = offs;
  2629. hasOffset = true;
  2630. }
  2631. /// <summary>
  2632. /// Return the offset for this data constant
  2633. /// </summary>
  2634. /// <returns></returns>
  2635. public uint GetOffset() { return offset; }
  2636. /// <summary>
  2637. /// Delete the offset of this data constant
  2638. /// </summary>
  2639. public void RemoveOffset() { hasOffset = false; }
  2640. /// <summary>
  2641. /// Does this data constant have an offset?
  2642. /// </summary>
  2643. public bool HasOffset() { return hasOffset; }
  2644. /// <summary>
  2645. /// Set the marshalling info for a field
  2646. /// </summary>
  2647. /// <param name="mType"></param>
  2648. public void SetMarshalType(NativeType mType) {
  2649. flags |= HasFieldMarshal;
  2650. marshalType = mType;
  2651. }
  2652. public NativeType GetMarshalType() { return marshalType; }
  2653. public void RemoveMarshalType() { marshalType = null; flags &= NoFieldMarshal; }
  2654. /// <summary>
  2655. /// Get the FieldRef equivalent to this FieldDef. Assumes that
  2656. /// one already exists.
  2657. /// </summary>
  2658. /// <returns>FieldRef for this FieldDef</returns>
  2659. public FieldRef RefOf() { return refOf; }
  2660. /// <summary>
  2661. /// Create the FieldRef equivalent to this FieldDef. If one does not
  2662. /// exist then create it.
  2663. /// </summary>
  2664. /// <returns>FieldRef for this FieldDef</returns>
  2665. public FieldRef MakeRefOf() {
  2666. if (refOf != null) return refOf;
  2667. ClassRef parRef = ((ClassDef)parent).MakeRefOf();
  2668. refOf = parRef.GetField(name);
  2669. if (refOf == null) {
  2670. Type refType;
  2671. if (type is ClassDef) {
  2672. refType = ((ClassDef)type).MakeRefOf();
  2673. } else {
  2674. refType = type;
  2675. }
  2676. refOf = new FieldRef(parRef,name,refType);
  2677. refOf.defOf = this;
  2678. }
  2679. return refOf;
  2680. }
  2681. /*------------------------- internal functions --------------------------*/
  2682. internal PEFile GetScope() {
  2683. return ((ClassDef)parent).GetScope();
  2684. }
  2685. internal void ChangeRefsToDefs(ClassDef newPar, ClassDef[] oldTypes) {
  2686. parent = newPar;
  2687. bool changeType = false;
  2688. for (int i=0; i < oldTypes.Length && !changeType; i++) {
  2689. if (type == oldTypes[i])
  2690. type = newPar;
  2691. }
  2692. }
  2693. internal override bool isDef() { return true; }
  2694. internal void SetParent(ClassDef paren) { parent = paren; }
  2695. internal sealed override void BuildTables(MetaDataOut md) {
  2696. md.AddToTable(MDTable.Field,this);
  2697. nameIx = md.AddToStringsHeap(name);
  2698. if (!type.isDef()) type.BuildMDTables(md);
  2699. if (initVal != null) {
  2700. FieldRVA rva = new FieldRVA(this,initVal);
  2701. rva.BuildMDTables(md);
  2702. }
  2703. if (constVal != null) {
  2704. ConstantElem constElem = new ConstantElem(this,constVal);
  2705. constElem.BuildMDTables(md);
  2706. }
  2707. if (hasOffset) {
  2708. FieldLayout layout = new FieldLayout(this,offset);
  2709. layout.BuildMDTables(md);
  2710. }
  2711. if (marshalType != null) {
  2712. FieldMarshal marshalInfo = new FieldMarshal(this,marshalType);
  2713. marshalInfo.BuildMDTables(md);
  2714. }
  2715. }
  2716. internal sealed override void BuildCILInfo(CILWriter output) {
  2717. if (!type.isDef()) type.BuildCILInfo(output);
  2718. }
  2719. internal static uint Size(MetaData md) {
  2720. return 2 + md.StringsIndexSize() + md.BlobIndexSize();
  2721. }
  2722. internal sealed override void Write(PEWriter output) {
  2723. output.Write(flags);
  2724. output.StringsIndex(nameIx);
  2725. output.BlobIndex(sigIx);
  2726. }
  2727. internal override void Write(CILWriter output) {
  2728. output.Write(" .field ");
  2729. if (hasOffset) {
  2730. output.Write("[ {0} ] ", offset);
  2731. }
  2732. WriteFlags(output, flags);
  2733. if (marshalType != null) {
  2734. output.Write("marshal ");
  2735. marshalType.Write(output);
  2736. }
  2737. type.WriteType(output);
  2738. output.Write(" " + name);
  2739. if (initVal != null) {
  2740. initVal.Write(output);
  2741. } else if (constVal != null) {
  2742. constVal.Write(output);
  2743. }
  2744. output.WriteLine();
  2745. }
  2746. internal sealed override uint GetCodedIx(CIx code) {
  2747. switch (code) {
  2748. case (CIx.HasConstant) : return 0;
  2749. case (CIx.HasCustomAttr) : return 1;
  2750. case (CIx.HasFieldMarshal) : return 0;
  2751. case (CIx.MemberForwarded) : return 0;
  2752. }
  2753. return 0;
  2754. }
  2755. }
  2756. /**************************************************************************/
  2757. /// <summary>
  2758. /// Descriptor for a field of a class defined in another assembly/module
  2759. /// </summary>
  2760. public class FieldRef : Field {
  2761. internal FieldDef defOf;
  2762. /*-------------------- Constructors ---------------------------------*/
  2763. internal FieldRef(Class paren, string name, Type fType) : base(name, fType, paren) {
  2764. parent = paren;
  2765. }
  2766. internal FieldRef(uint parenIx, string name, uint sigIx) : base(name,null,null) {
  2767. parentIx = parenIx;
  2768. this.name = name;
  2769. this.sigIx = sigIx;
  2770. }
  2771. internal override Member ResolveParent(PEReader buff) {
  2772. if (parent != null) return this;
  2773. MetaDataElement paren = buff.GetCodedElement(CIx.MemberRefParent,parentIx);
  2774. //Console.WriteLine("parentIx = " + parentIx);
  2775. //Console.WriteLine("paren = " + paren);
  2776. if (paren is ClassDef)
  2777. return((ClassDef)paren).GetField(this.name);
  2778. //if (paren is ClassSpec)
  2779. // paren = ((ClassSpec)paren).GetParent();
  2780. if (paren is ReferenceScope)
  2781. parent = ((ReferenceScope)paren).GetDefaultClass();
  2782. if (paren is TypeSpec)
  2783. parent = new ConstructedTypeSpec((TypeSpec)paren);
  2784. else
  2785. parent = (Class)paren;
  2786. if (parent != null) {
  2787. Field existing = (Field)((Class)parent).GetFieldDesc(name);
  2788. if (existing != null) {
  2789. return existing;
  2790. }
  2791. }
  2792. parent.AddToFieldList(this);
  2793. return this;
  2794. }
  2795. /*------------------------- internal functions --------------------------*/
  2796. internal sealed override void BuildTables(MetaDataOut md) {
  2797. md.AddToTable(tabIx,this);
  2798. nameIx = md.AddToStringsHeap(name);
  2799. if (type is ClassSpec) md.AddToTable(MDTable.TypeSpec, type);
  2800. if (!type.isDef())
  2801. type.BuildMDTables(md);
  2802. if (parent != null) {
  2803. if (parent is ClassSpec) md.AddToTable(MDTable.TypeSpec,parent);
  2804. parent.BuildMDTables(md);
  2805. }
  2806. }
  2807. internal override void BuildCILInfo(CILWriter output) {
  2808. parent.BuildCILInfo(output);
  2809. }
  2810. internal static uint Size(MetaData md) {
  2811. return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
  2812. }
  2813. internal sealed override void Write(PEWriter output) {
  2814. output.WriteCodedIndex(CIx.MemberRefParent,parent);
  2815. output.StringsIndex(nameIx);
  2816. output.BlobIndex(sigIx);
  2817. }
  2818. internal sealed override uint GetCodedIx(CIx code) { return 6; }
  2819. }
  2820. /**************************************************************************/
  2821. /// <summary>
  2822. /// Base class for Method Descriptors
  2823. /// </summary>
  2824. public abstract class Method : Member {
  2825. protected MethSig sig;
  2826. protected ArrayList genericParams;
  2827. /*-------------------- Constructors ---------------------------------*/
  2828. internal Method(string methName, Type rType, Class paren) : base(methName,paren) {
  2829. sig = new MethSig(methName);
  2830. sig.retType = rType;
  2831. }
  2832. internal Method(string name) : base(name) { }
  2833. /// <summary>
  2834. /// Add calling conventions to this method descriptor
  2835. /// </summary>
  2836. /// <param name="cconv"></param>
  2837. public void AddCallConv(CallConv cconv) {
  2838. sig.callConv |= cconv;
  2839. }
  2840. /// <summary>
  2841. /// Get the calling conventions for this method
  2842. /// </summary>
  2843. /// <returns></returns>
  2844. public CallConv GetCallConv() {
  2845. return sig.callConv;
  2846. }
  2847. /// <summary>
  2848. /// Set the return type
  2849. /// </summary>
  2850. /// <param name="retT">type returned</param>
  2851. internal void AddRetType(Type retT) {
  2852. System.Diagnostics.Debug.Assert(retT != null);
  2853. sig.retType = retT;
  2854. }
  2855. /// <summary>
  2856. /// Get the method return type
  2857. /// </summary>
  2858. /// <returns>method return type</returns>
  2859. public Type GetRetType() {
  2860. return sig.retType;
  2861. }
  2862. /// <summary>
  2863. /// Get the types of the method parameters
  2864. /// </summary>
  2865. /// <returns>list of parameter types</returns>
  2866. public Type[] GetParTypes() {
  2867. return sig.parTypes;
  2868. }
  2869. /// <summary>
  2870. /// Get the optional parameter types (for varargs)
  2871. /// </summary>
  2872. /// <returns>list of vararg types</returns>
  2873. public Type[] GetOptParTypes() {
  2874. return sig.optParTypes;
  2875. }
  2876. public int GetGenericParamCount() {
  2877. return genericParams == null? 0 :genericParams.Count;
  2878. }
  2879. /// <summary>
  2880. /// Add a generic type to this method
  2881. /// </summary>
  2882. /// <param name="name">the name of the generic type</param>
  2883. /// <returns>the descriptor for the generic type</returns>
  2884. public GenericParam AddGenericParam(string name) {
  2885. if (genericParams == null) genericParams = new ArrayList();
  2886. GenericParam gp = new GenericParam(name,this,genericParams.Count);
  2887. sig.callConv |= CallConv.Generic;
  2888. genericParams.Add(gp);
  2889. sig.numGenPars = (uint)genericParams.Count;
  2890. return gp;
  2891. }
  2892. /// <summary>
  2893. /// Get the descriptor for a generic type
  2894. /// </summary>
  2895. /// <param name="name">the name of the generic type</param>
  2896. /// <returns>descriptor for generic type "name"</returns>
  2897. public GenericParam GetGenericParam(string name) {
  2898. int pos = FindGenericParam(name);
  2899. if (pos == -1) return null;
  2900. return (GenericParam)genericParams[pos];
  2901. }
  2902. public GenericParam GetGenericParam(int ix) {
  2903. if ((genericParams == null) || (ix >= genericParams.Count)) return null;
  2904. return (GenericParam)genericParams[ix];
  2905. }
  2906. public void RemoveGenericParam(string name) {
  2907. int pos = FindGenericParam(name);
  2908. if (pos == -1) return;
  2909. DeleteGenericParam(pos);
  2910. }
  2911. public void RemoveGenericParam(int ix) {
  2912. if (genericParams == null) return;
  2913. if (ix >= genericParams.Count) return;
  2914. DeleteGenericParam(ix);
  2915. }
  2916. public MethodSpec Instantiate(Type[] genTypes) {
  2917. if (genTypes == null) return null;
  2918. if ((genericParams == null) || (genericParams.Count == 0))
  2919. throw new Exception("Cannot instantiate non-generic method");
  2920. if (genTypes.Length != genericParams.Count)
  2921. throw new Exception("Wrong number of type parameters for instantiation\nNeeded "
  2922. + genericParams.Count + " but got " + genTypes.Length);
  2923. return new MethodSpec(this,genTypes);
  2924. }
  2925. public GenericParam[] GetGenericParams() { // KJG June 2005
  2926. if (genericParams == null) return null;
  2927. return (GenericParam[])genericParams.ToArray(typeof(GenericParam));
  2928. }
  2929. /*------------------------- internal functions --------------------------*/
  2930. internal abstract void TypeSig(MemoryStream sig);
  2931. internal bool HasNameAndSig(string name, Type[] sigTypes) {
  2932. if (this.name != name) return false;
  2933. return sig.HasSig(sigTypes);
  2934. }
  2935. internal bool HasNameAndSig(string name, Type[] sigTypes, Type[] optPars) {
  2936. if (this.name != name) return false;
  2937. return sig.HasSig(sigTypes,optPars);
  2938. }
  2939. internal MethSig GetSig() { return sig; }
  2940. internal void SetSig(MethSig sig) {
  2941. this.sig = sig;
  2942. this.sig.name = name;
  2943. }
  2944. internal override string NameString() {
  2945. return parent.NameString() + sig.NameString();
  2946. }
  2947. private int FindGenericParam(string name) {
  2948. if (genericParams == null) return -1;
  2949. for (int i=0; i < genericParams.Count; i++) {
  2950. GenericParam gp = (GenericParam)genericParams[i];
  2951. if (gp.GetName() == name) return i;
  2952. }
  2953. return -1;
  2954. }
  2955. private void DeleteGenericParam(int pos) {
  2956. genericParams.RemoveAt(pos);
  2957. for (int i=pos; i < genericParams.Count; i++) {
  2958. GenericParam gp = (GenericParam)genericParams[i];
  2959. gp.Index = (uint)i;
  2960. }
  2961. }
  2962. internal void AddGenericParam(GenericParam par) {
  2963. if (genericParams == null) genericParams = new ArrayList();
  2964. genericParams.Add(par);
  2965. //sig.callConv |= CallConv.Generic;
  2966. //sig.numGenPars = (uint)genericParams.Count;
  2967. }
  2968. internal ArrayList GenericParams {
  2969. get { return genericParams; }
  2970. set { genericParams = value; }
  2971. }
  2972. internal void SetGenericParams(GenericParam[] pars) {
  2973. genericParams = new ArrayList(pars);
  2974. sig.callConv |= CallConv.Generic;
  2975. sig.numGenPars = (uint)genericParams.Count;
  2976. }
  2977. internal override void WriteType(CILWriter output) {
  2978. sig.WriteCallConv(output);
  2979. sig.retType.WriteType(output);
  2980. output.Write(" ");
  2981. parent.WriteName(output);
  2982. output.Write("::" + name);
  2983. sig.WriteParTypes(output);
  2984. }
  2985. }
  2986. /**************************************************************************/
  2987. /// <summary>
  2988. /// Descriptor for a method defined in THIS assembly/module
  2989. /// IL .method
  2990. /// </summary>
  2991. public class MethodDef : Method {
  2992. private static readonly ushort PInvokeImpl = 0x2000;
  2993. private static readonly ushort NotPInvoke = 0xDFFF;
  2994. private static readonly ushort HasSecurity = 0x4000;
  2995. private static readonly ushort NoSecurity = 0xBFFF;
  2996. //private static readonly uint UnmanagedExport = 0x0008;
  2997. uint parIx = 0, textOffset = 0;
  2998. internal MethodRef refOf;
  2999. // The default max stack depth to be assigned when the depth can not be calculated.
  3000. private static readonly int DefaultMaxStackDepth = 8;
  3001. CILInstructions code;
  3002. uint rva;
  3003. Param[] parList;
  3004. Local[] locals;
  3005. bool initLocals;
  3006. ushort methFlags = 0, implFlags = 0;
  3007. int maxStack = 0, numLocals = 0;
  3008. uint numPars = 0;
  3009. bool entryPoint = false;
  3010. internal LocalSig localSig;
  3011. MethodRef varArgSig;
  3012. ImplMap pinvokeImpl;
  3013. ArrayList security = null;
  3014. internal uint locToken = 0;
  3015. /*-------------------- Constructors ---------------------------------*/
  3016. internal MethodDef(string name, Type retType, Param[] pars, ClassDef paren)
  3017. : base(name,retType,paren) {
  3018. sig.SetParTypes(pars);
  3019. parList = pars;
  3020. parent = paren;
  3021. tabIx = MDTable.Method;
  3022. }
  3023. internal MethodDef(ClassDef paren, MethSig mSig, Param[] pars) : base(mSig.name) {
  3024. sig = mSig;
  3025. parList = pars;
  3026. parent = paren;
  3027. tabIx = MDTable.Method;
  3028. }
  3029. internal MethodDef(ClassSpec paren, MethSig mSig, Param[] pars) : base(mSig.name) {
  3030. parent = paren;
  3031. parList = pars;
  3032. sig = mSig;
  3033. tabIx = MDTable.Method;
  3034. }
  3035. internal MethodDef(PEReader buff) : base(null) {
  3036. rva = buff.ReadUInt32();
  3037. implFlags = buff.ReadUInt16();
  3038. methFlags = buff.ReadUInt16();
  3039. name = buff.GetString();
  3040. sigIx = buff.GetBlobIx();
  3041. parIx = buff.GetIndex(MDTable.Param);
  3042. tabIx = MDTable.Method;
  3043. }
  3044. internal static void Read(PEReader buff, TableRow[] methDefs) {
  3045. MethodDef prevDef = null;
  3046. prevDef = new MethodDef(buff);
  3047. methDefs[0] = prevDef;
  3048. for (int i=1; i < methDefs.Length; i++) {
  3049. prevDef.Row = (uint)i;
  3050. MethodDef methDef = new MethodDef(buff);
  3051. prevDef.numPars = methDef.parIx - prevDef.parIx;
  3052. prevDef = methDef;
  3053. methDefs[i] = methDef;
  3054. }
  3055. prevDef.Row = (uint)methDefs.Length;
  3056. prevDef.numPars = (buff.GetTableSize(MDTable.Param)+1) - prevDef.parIx;
  3057. }
  3058. internal static void GetMethodRefs(PEReader buff, uint num, ClassRef parent) {
  3059. for (int i=0; i < num; i++) {
  3060. uint rva = buff.ReadUInt32();
  3061. ushort implFlags = buff.ReadUInt16();
  3062. ushort methFlags = buff.ReadUInt16();
  3063. string name = buff.GetString();
  3064. uint sigIx = buff.GetBlobIx();
  3065. uint parIx = buff.GetIndex(MDTable.Param);
  3066. if (IsPublicOrProtected(methFlags)) {
  3067. MethodRef mRef = new MethodRef(parIx,name,sigIx); // changed
  3068. mRef.SetParent(parent);
  3069. //Console.WriteLine(parent.NameString());
  3070. MethSig mSig = buff.ReadMethSig(mRef,name,sigIx);
  3071. //mSig.name = name;
  3072. mRef.SetSig(mSig); // changed
  3073. parent.AddToMethodList(mRef);
  3074. //if (parent.GetMethod(mSig) == null) {
  3075. // MethodRef mRef = new MethodRef(mSig);
  3076. // parent.AddToMethodList(mRef);
  3077. //}
  3078. }
  3079. }
  3080. }
  3081. /*
  3082. internal static void GetMemberNames(PEReader buff, uint start, uint end, ArrayList membs) {
  3083. buff.SetElementPosition(MDTable.Field,start);
  3084. for (int i=0; i < (end - start); i++, insIx++) {
  3085. uint junk = buff.ReadUInt32();
  3086. junk = buff.ReadUInt16();
  3087. uint flags = buff.ReadUInt16();
  3088. if ((flags & MethAttr.Public) == MethAttr.Public)
  3089. membs.Add(new MemberIndex(buff,buff.GetString(),buff.GetBlobIx(),false));
  3090. else {
  3091. junk = buff.GetStringIx();
  3092. junk = buff.GetBlobIx();
  3093. }
  3094. junk = buff.GetIndex(MDTable.Param);
  3095. }
  3096. }
  3097. */
  3098. /* internal static MethSig[] GetMethSigs(PEReader buff, int num) {
  3099. MethSig[] meths = new MethSig[num];
  3100. for (int i=0; i < num; i++) {
  3101. uint junk = buff.ReadUInt32();
  3102. junk = buff.ReadUInt16();
  3103. junk = buff.ReadUInt16();
  3104. string mName = new MethSig(buff.GetString());
  3105. meths[i] = buff.ReadMethSig(buff.GetBlobIx());
  3106. junk = buff.GetIndex(MDTable.Param);
  3107. }
  3108. }
  3109. */
  3110. private void DoPars(PEReader buff, bool resolvePars) {
  3111. if (sig == null) sig = buff.ReadMethSig(this,sigIx);
  3112. sig.name = name;
  3113. parList = new Param[sig.numPars];
  3114. for (uint i=0; i < sig.numPars; i++) {
  3115. parList[i] = (Param)buff.GetElement(MDTable.Param,i+parIx);
  3116. if (resolvePars) parList[i].Resolve(buff,i+parIx,sig.parTypes[i]);
  3117. else parList[i].SetParType(sig.parTypes[i]);
  3118. }
  3119. //parsDone = true;
  3120. }
  3121. private void DoCode(PEReader buff) {
  3122. if (rva != 0) {
  3123. if (Diag.DiagOn) Console.WriteLine("Reading byte codes for method " + name);
  3124. buff.ReadByteCodes(this,rva);
  3125. }
  3126. }
  3127. internal sealed override void Resolve(PEReader buff) {
  3128. buff.currentMethodScope = this;
  3129. buff.currentClassScope = parent;
  3130. DoPars(buff,true);
  3131. if (!buff.skipBody) {
  3132. DoCode(buff);
  3133. }
  3134. buff.currentMethodScope = null;
  3135. buff.currentClassScope = null;
  3136. }
  3137. /*------------------------- public set and get methods --------------------------*/
  3138. /// <summary>
  3139. /// Get the parameters of this method
  3140. /// </summary>
  3141. /// <returns>Array of params of this method</returns>
  3142. public Param[] GetParams() {
  3143. //if (!parsDone) DoPars(buffer);
  3144. return parList;
  3145. }
  3146. /// <summary>
  3147. /// Set the parameters for this method
  3148. /// </summary>
  3149. /// <param name="pars">Descriptors of the parameters for this method</param>
  3150. public void SetParams(Param[] pars) {
  3151. parList = pars;
  3152. sig.SetParTypes(pars);
  3153. }
  3154. /// <summary>
  3155. /// Add some attributes to this method descriptor
  3156. /// </summary>
  3157. /// <param name="ma">the attributes to be added</param>
  3158. public void AddMethAttribute(MethAttr ma) { methFlags |= (ushort)ma; }
  3159. /// <summary>
  3160. /// Property to get and set the attributes for this method
  3161. /// </summary>
  3162. public MethAttr GetMethAttributes() { return (MethAttr)methFlags; }
  3163. public void SetMethAttributes(MethAttr ma) { methFlags = (ushort)ma; }
  3164. /// <summary>
  3165. /// Add some implementation attributes to this method descriptor
  3166. /// </summary>
  3167. /// <param name="ia">the attributes to be added</param>
  3168. public void AddImplAttribute(ImplAttr ia) {
  3169. implFlags |= (ushort)ia;
  3170. }
  3171. /// <summary>
  3172. /// Property to get and set the implementation attributes for this method
  3173. /// </summary>
  3174. public ImplAttr GetImplAttributes() { return (ImplAttr)implFlags; }
  3175. public void SetImplAttributes(ImplAttr ia) { implFlags = (ushort)ia; }
  3176. public void AddPInvokeInfo(ModuleRef scope, string methName,
  3177. PInvokeAttr callAttr) {
  3178. pinvokeImpl = new ImplMap((ushort)callAttr,this,methName,scope);
  3179. methFlags |= PInvokeImpl;
  3180. }
  3181. public void RemovePInvokeInfo() {
  3182. pinvokeImpl = null;
  3183. methFlags &= NotPInvoke;
  3184. }
  3185. public void AddSecurity(SecurityAction act, byte[] permissionSet) {
  3186. methFlags |= HasSecurity;
  3187. if (security == null) security = new ArrayList();
  3188. security.Add(new DeclSecurity(this,act,permissionSet));
  3189. }
  3190. public void AddSecurity(DeclSecurity sec) {
  3191. methFlags |= HasSecurity;
  3192. if (security == null) security = new ArrayList();
  3193. security.Add(sec);
  3194. }
  3195. public DeclSecurity[] GetSecurity() {
  3196. if (security == null) return null;
  3197. return (DeclSecurity[])security.ToArray(typeof(DeclSecurity));
  3198. }
  3199. public void RemoveSecurity() {
  3200. security = null;
  3201. methFlags &= NoSecurity;
  3202. }
  3203. /// <summary>
  3204. /// Set the maximum stack height for this method
  3205. /// </summary>
  3206. /// <param name="maxStack">the maximum height of the stack</param>
  3207. public void SetMaxStack(int maxStack) {
  3208. this.maxStack = maxStack;
  3209. }
  3210. /// <summary>
  3211. /// Retrieve the maximum size of the stack for the code
  3212. /// of this method
  3213. /// </summary>
  3214. /// <returns>max stack height for CIL codes</returns>
  3215. public int GetMaxStack() {
  3216. return maxStack;
  3217. }
  3218. /// <summary>
  3219. /// Add local variables to this method
  3220. /// </summary>
  3221. /// <param name="locals">the locals to be added</param>
  3222. /// <param name="initLocals">are locals initialised to default values</param>
  3223. public void AddLocals(Local[] locals, bool initLocals) {
  3224. if (locals == null) return;
  3225. this.locals = locals;
  3226. this.initLocals = initLocals;
  3227. numLocals = locals.Length;
  3228. for (int i=0; i < numLocals; i++) {
  3229. this.locals[i].SetIndex(i);
  3230. }
  3231. }
  3232. /// <summary>
  3233. /// Retrieve the locals for this method
  3234. /// </summary>
  3235. /// <returns>list of locals declared in this method</returns>
  3236. public Local[] GetLocals() { return locals; }
  3237. /// <summary>
  3238. /// Remove all the locals from this method
  3239. /// </summary>
  3240. public void RemoveLocals() {
  3241. locals = null;
  3242. numLocals = 0;
  3243. initLocals = false;
  3244. }
  3245. /// <summary>
  3246. /// Mark this method as having an entry point
  3247. /// </summary>
  3248. public void DeclareEntryPoint() { entryPoint = true; }
  3249. /// <summary>
  3250. /// Does this method have an entrypoint?
  3251. /// </summary>
  3252. public bool HasEntryPoint() { return entryPoint; }
  3253. /// <summary>
  3254. /// Remove the entry point from this method
  3255. /// </summary>
  3256. public void RemoveEntryPoint() { entryPoint = false; }
  3257. /// <summary>
  3258. /// Create a code buffer for this method to add the IL instructions to
  3259. /// </summary>
  3260. /// <returns>a buffer for this method's IL instructions</returns>
  3261. public CILInstructions CreateCodeBuffer() {
  3262. code = new CILInstructions(this);
  3263. return code;
  3264. }
  3265. /// <summary>
  3266. /// Get the CIL code buffer for this method
  3267. /// </summary>
  3268. /// <returns>Code buffer for this method</returns>
  3269. public CILInstructions GetCodeBuffer() { return code; }
  3270. /// <summary>
  3271. /// Make a method reference descriptor for this method to be used
  3272. /// as a callsite signature for this vararg method
  3273. /// </summary>
  3274. /// <param name="optPars">the optional pars for the vararg method call</param>
  3275. /// <returns></returns>
  3276. public MethodRef MakeVarArgSignature(Type[] optPars) {
  3277. MethSig mSig = new MethSig(name);
  3278. mSig.parTypes = sig.parTypes;
  3279. mSig.retType = sig.retType;
  3280. varArgSig = new MethodRef(sig);
  3281. varArgSig.MakeVarArgMethod(this,optPars);
  3282. return varArgSig;
  3283. }
  3284. public MethodRef GetVarArgSignature() {
  3285. return varArgSig;
  3286. }
  3287. /// <summary>
  3288. /// Get the MethodRef equivalent to this MethodDef. Assumes
  3289. /// that one has been created.
  3290. /// </summary>
  3291. /// <returns>MethodRef for this MethodDef</returns>
  3292. public MethodRef RefOf() { return refOf; }
  3293. /// <summary>
  3294. /// Get the MethodRef equivalent to this MethodDef. If one
  3295. /// does not exist, then create it.
  3296. /// </summary>
  3297. /// <returns>MethodRef for this MethodDef</returns>
  3298. public MethodRef MakeRefOf() {
  3299. if (refOf != null) return refOf;
  3300. ClassRef parRef = ((ClassDef)parent).MakeRefOf();
  3301. refOf = parRef.GetMethod(name, sig.parTypes);
  3302. if (refOf == null) {
  3303. Type rType = sig.MakeRefRetType();
  3304. Type[] pTypes = sig.MakeRefParTypes();
  3305. refOf = new MethodRef(parRef, name, rType, pTypes);
  3306. refOf.defOf = this;
  3307. refOf.AddCallConv(this.GetCallConv());
  3308. }
  3309. return refOf;
  3310. }
  3311. /*------------------------- internal functions --------------------------*/
  3312. private static bool IsPublicOrProtected(ushort methFlags) {
  3313. return (methFlags & (ushort)MethAttr.Public) == (ushort)MethAttr.Public ||
  3314. (methFlags & (ushort)MethAttr.Family) == (ushort)MethAttr.Family;
  3315. }
  3316. internal void InsertGenericParam(GenericParam genPar) {
  3317. if (genericParams == null) genericParams = new ArrayList();
  3318. for (int i=0; i < genericParams.Count - genPar.Index; i++) {
  3319. genericParams.Add(null);
  3320. }
  3321. genericParams.Insert((int)genPar.Index,genPar);
  3322. }
  3323. internal override bool isDef() { return true; }
  3324. internal PEFile GetScope() {
  3325. return ((ClassDef)parent).GetScope();
  3326. }
  3327. internal void ChangeRefsToDefs(ClassDef newPar, ClassDef[] oldTypes) {
  3328. parent = newPar;
  3329. sig.ChangeParTypes(newPar,oldTypes);
  3330. if (code != null)
  3331. code.ChangeRefsToDefs(newPar,oldTypes);
  3332. }
  3333. internal void AddPInvokeInfo(ImplMap impl) {
  3334. pinvokeImpl = impl;
  3335. methFlags |= PInvokeImpl;
  3336. }
  3337. internal void AddVarArgSig(MethodRef meth) {
  3338. varArgSig = meth;
  3339. //meth.MakeVarArgMethod(this,null);
  3340. }
  3341. internal sealed override void TypeSig(MemoryStream sigStream) {
  3342. sig.TypeSig(sigStream);
  3343. }
  3344. // fix for Whidbey bug
  3345. internal void AddGenericsToTable(MetaDataOut md) {
  3346. if (genericParams != null) {
  3347. for (int i=0; i < genericParams.Count; i++) {
  3348. md.AddToTable(MDTable.GenericParam,(GenericParam)genericParams[i]);
  3349. }
  3350. }
  3351. }
  3352. internal sealed override void BuildTables(MetaDataOut md) {
  3353. md.AddToTable(MDTable.Method,this);
  3354. nameIx = md.AddToStringsHeap(name);
  3355. if (genericParams != null) {
  3356. for (int i=0; i < genericParams.Count; i++) {
  3357. ((GenericParam)genericParams[i]).BuildMDTables(md);
  3358. }
  3359. }
  3360. if (security != null) {
  3361. for (int i=0; i < security.Count; i++) {
  3362. ((DeclSecurity)security[i]).BuildMDTables(md);
  3363. }
  3364. }
  3365. if (pinvokeImpl != null) pinvokeImpl.BuildMDTables(md);
  3366. if (entryPoint) md.SetEntryPoint(this);
  3367. if (locals != null) {
  3368. localSig = new LocalSig(locals);
  3369. localSig.BuildMDTables(md);
  3370. }
  3371. try {
  3372. if (code != null) {
  3373. if (code.IsEmpty()) {
  3374. code = null;
  3375. } else {
  3376. code.BuildTables(md);
  3377. }
  3378. }
  3379. } catch (InstructionException ex) {
  3380. throw new Exception(ex.AddMethodName(name));
  3381. }
  3382. parIx = md.TableIndex(MDTable.Param);
  3383. for (int i=0; i < sig.numPars; i++) {
  3384. parList[i].seqNo = (ushort)(i+1);
  3385. parList[i].BuildMDTables(md);
  3386. }
  3387. sig.BuildTables(md);
  3388. }
  3389. internal sealed override void BuildCILInfo(CILWriter output) {
  3390. if (genericParams != null) {
  3391. for (int i = 0; i < genericParams.Count; i++) {
  3392. ((GenericParam)genericParams[i]).BuildCILInfo(output);
  3393. }
  3394. }
  3395. if (security != null) {
  3396. for (int i = 0; i < security.Count; i++) {
  3397. ((DeclSecurity)security[i]).BuildCILInfo(output);
  3398. }
  3399. }
  3400. if (pinvokeImpl != null) pinvokeImpl.BuildCILInfo(output);
  3401. if (locals != null) {
  3402. for (int i = 0; i < locals.Length; i++) {
  3403. locals[i].BuildCILInfo(output);
  3404. }
  3405. }
  3406. try {
  3407. if (code != null) code.BuildCILInfo(output);
  3408. }
  3409. catch (InstructionException ex) {
  3410. throw new Exception(ex.AddMethodName(name));
  3411. }
  3412. sig.BuildCILInfo(output);
  3413. }
  3414. internal sealed override void BuildSignatures(MetaDataOut md) {
  3415. if (locals != null) {
  3416. localSig.BuildSignatures(md);
  3417. locToken = localSig.Token();
  3418. }
  3419. if (code != null) {
  3420. // If the stack depth has not been explicity set, try to work out what is needed.
  3421. if (maxStack == 0) {
  3422. try {
  3423. // Set the flag to show if the return type is void or other.
  3424. code.ReturnsVoid = GetRetType().SameType(PrimitiveType.Void);
  3425. // Calculate the max stack depth
  3426. maxStack = code.GetMaxStackDepthRequired();
  3427. } catch (CouldNotFindMaxStackDepth) {
  3428. // Could not find the depth, assign the default
  3429. maxStack = DefaultMaxStackDepth;
  3430. }
  3431. }
  3432. code.CheckCode(locToken,initLocals,maxStack,md);
  3433. textOffset = md.AddCode(code);
  3434. if (Diag.DiagOn) Console.WriteLine("code offset = " + textOffset);
  3435. }
  3436. sig.BuildSignatures(md);
  3437. MemoryStream outSig = new MemoryStream();
  3438. TypeSig(outSig);
  3439. sigIx = md.AddToBlobHeap(outSig.ToArray());
  3440. done = false;
  3441. }
  3442. internal static uint Size(MetaData md) {
  3443. return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
  3444. }
  3445. internal sealed override void Write(PEWriter output) {
  3446. if (code == null) output.Write(0);
  3447. else output.WriteCodeRVA(textOffset);
  3448. output.Write(implFlags);
  3449. output.Write(methFlags);
  3450. output.StringsIndex(nameIx);
  3451. output.BlobIndex(sigIx);
  3452. output.WriteIndex(MDTable.Param,parIx);
  3453. }
  3454. internal override void Write(CILWriter output) {
  3455. output.Write(" .method ");
  3456. WriteFlags(output, methFlags);
  3457. sig.Write(output);
  3458. output.Write(" " + name + "(");
  3459. if (parList != null) {
  3460. for (int i=0; i < parList.Length; i++) {
  3461. parList[i].Write(output);
  3462. if (i < parList.Length-1) {
  3463. output.Write(", ");
  3464. }
  3465. }
  3466. }
  3467. output.Write(") ");
  3468. uint codeType = implFlags & (uint)0x11;
  3469. if (codeType == 0) {
  3470. output.Write("cil ");
  3471. } else if (codeType == 1) {
  3472. output.Write("native ");
  3473. } else if (codeType == 3) {
  3474. output.Write("runtime ");
  3475. }
  3476. if ((implFlags & (uint)ImplAttr.Unmanaged) == 0) {
  3477. output.Write("managed ");
  3478. } else {
  3479. output.Write("unmanaged ");
  3480. }
  3481. if ((implFlags & (uint)ImplAttr.ForwardRef) != 0) {
  3482. output.Write("forwardref ");
  3483. }
  3484. if ((implFlags & (uint)ImplAttr.InternalCall) != 0) {
  3485. output.Write("internalcall ");
  3486. }
  3487. if ((implFlags & (uint)ImplAttr.Synchronized) != 0) {
  3488. output.Write("synchronized ");
  3489. }
  3490. if ((implFlags & (uint)ImplAttr.NoInLining) != 0) {
  3491. output.Write("noinlining ");
  3492. }
  3493. output.WriteLine(" {");
  3494. if ((locals != null) && (locals.Length > 0)) {
  3495. output.Write(" .locals (");
  3496. for (int i=0; i < locals.Length; i++) {
  3497. if (i > 0) {
  3498. output.Write(" ");
  3499. }
  3500. locals[i].Write(output);
  3501. if (i < locals.Length-1) {
  3502. output.WriteLine(",");
  3503. }
  3504. }
  3505. output.WriteLine(" )");
  3506. }
  3507. if (entryPoint) {
  3508. output.WriteLine(" .entrypoint");
  3509. }
  3510. if (code != null) code.Write(output);
  3511. output.WriteLine(" }");
  3512. }
  3513. internal sealed override uint GetCodedIx(CIx code) {
  3514. switch (code) {
  3515. case (CIx.HasCustomAttr) : return 0;
  3516. case (CIx.HasDeclSecurity) : return 1;
  3517. case (CIx.MemberRefParent) : return 3;
  3518. case (CIx.MethodDefOrRef) : return 0;
  3519. case (CIx.MemberForwarded) : return 1;
  3520. case (CIx.CustomAttributeType) : return 2;
  3521. case (CIx.TypeOrMethodDef) : return 1;
  3522. }
  3523. return 0;
  3524. }
  3525. }
  3526. /**************************************************************************/
  3527. /// <summary>
  3528. /// Descriptor for a method defined in another assembly/module
  3529. /// </summary>
  3530. public class MethodRef : Method {
  3531. internal MethodDef defOf;
  3532. MethodDef varArgParent = null;
  3533. /*-------------------- Constructors ---------------------------------*/
  3534. internal MethodRef(Class paren, string name, Type retType, Type[] pars)
  3535. : base(name,retType,paren) {
  3536. sig.parTypes = pars;
  3537. if (pars != null) sig.numPars = (uint)pars.Length;
  3538. }
  3539. internal MethodRef(uint parIx, string name, uint sigIx) : base(name) {
  3540. this.parentIx = parIx;
  3541. this.sigIx = sigIx;
  3542. }
  3543. internal MethodRef(MethSig sig) : base(sig.name) {
  3544. this.sig = sig;
  3545. }
  3546. internal override void Resolve(PEReader buff) {
  3547. if (sig == null) {
  3548. buff.currentMethodScope = this;
  3549. buff.currentClassScope = parent;
  3550. sig = buff.ReadMethSig(this,name,sigIx);
  3551. buff.currentMethodScope = null;
  3552. buff.currentClassScope = null;
  3553. }
  3554. }
  3555. internal override Member ResolveParent(PEReader buff) {
  3556. if (parent != null) return this;
  3557. buff.currentMethodScope = this;
  3558. MetaDataElement paren = buff.GetCodedElement(CIx.MemberRefParent,parentIx);
  3559. buff.currentMethodScope = null;
  3560. if (paren is MethodDef) {
  3561. parent = null;
  3562. varArgParent = (MethodDef)paren;
  3563. //this.sig = buff.ReadMethSig(this,name,sigIx);
  3564. ((MethodDef)paren).AddVarArgSig(this);
  3565. return this;
  3566. } else if (paren is ClassSpec) {
  3567. ((ClassSpec)paren).AddMethod(this);
  3568. return this;
  3569. } else if (paren is PrimitiveType) {
  3570. paren = MSCorLib.mscorlib.GetDefaultClass();
  3571. } else if (paren is ClassDef) {
  3572. this.sig = buff.ReadMethSig(this,name,sigIx);
  3573. return ((ClassDef)paren).GetMethod(this.sig);
  3574. } else if (paren is TypeSpec) {
  3575. paren = new ConstructedTypeSpec((TypeSpec)paren);
  3576. //Console.WriteLine("Got TypeSpec as parent of Member");
  3577. //return this;
  3578. //throw new Exception("Got TypeSpec as parent of Member");
  3579. //((TypeSpec)paren).AddMethod(buff,this);
  3580. }
  3581. if (paren is ReferenceScope)
  3582. parent = ((ReferenceScope)paren).GetDefaultClass();
  3583. parent = (Class)paren;
  3584. //if ((MethodRef)parent.GetMethodDesc(name) != null) throw new PEFileException("Existing method!!");
  3585. //sig = buff.ReadMethSig(this,name,sigIx);
  3586. //MethodRef existing = (MethodRef)parent.GetMethod(sig);
  3587. //if (existing != null)
  3588. // return existing;
  3589. parent.AddToMethodList(this);
  3590. return this;
  3591. }
  3592. public void MakeVarArgMethod(MethodDef paren, Type[] optPars) {
  3593. if (paren != null) {
  3594. parent = null;
  3595. varArgParent = paren;
  3596. }
  3597. sig.optParTypes = optPars;
  3598. if (sig.optParTypes != null) sig.numOptPars = (uint)sig.optParTypes.Length;
  3599. sig.callConv = CallConv.Vararg;
  3600. }
  3601. internal void MakeGenericPars(uint num) {
  3602. if (genericParams != null) {
  3603. for (int i=genericParams.Count; i < num; i++) {
  3604. genericParams.Add(new GenericParam("GPar"+i,this,i));
  3605. }
  3606. }
  3607. //sig.numGenPars = (uint)genericParams.Count;
  3608. }
  3609. /*------------------------- public set and get methods --------------------------*/
  3610. /// <summary>
  3611. /// Set the parameter types for this method
  3612. /// </summary>
  3613. /// <param name="pars">List of types of method parameters</param>
  3614. public void SetParTypes(Type[] pars) {
  3615. if (pars == null) {
  3616. sig.numPars = 0;
  3617. return;
  3618. }
  3619. sig.parTypes = pars;
  3620. sig.numPars = (uint)pars.Length;
  3621. }
  3622. /// <summary>
  3623. /// Set the list of optional parameter types for this method
  3624. /// </summary>
  3625. /// <param name="pars">list of optional parameter types</param>
  3626. public void SetOptParTypes(Type[] pars) {
  3627. if (pars == null) {
  3628. sig.numOptPars = 0;
  3629. return;
  3630. }
  3631. sig.optParTypes = pars;
  3632. sig.numOptPars = (uint)sig.optParTypes.Length;
  3633. }
  3634. /*------------------------- internal functions --------------------------*/
  3635. internal sealed override void TypeSig(MemoryStream sigStream) {
  3636. sig.TypeSig(sigStream);
  3637. }
  3638. internal sealed override void BuildTables(MetaDataOut md) {
  3639. md.AddToTable(MDTable.MemberRef,this);
  3640. nameIx = md.AddToStringsHeap(name);
  3641. if (parent != null) {
  3642. if (parent is ClassSpec) md.AddToTable(MDTable.TypeSpec,parent);
  3643. parent.BuildMDTables(md);
  3644. }
  3645. sig.BuildTables(md);
  3646. }
  3647. internal sealed override void BuildSignatures(MetaDataOut md) {
  3648. sig.BuildSignatures(md);
  3649. MemoryStream sigStream = new MemoryStream();
  3650. TypeSig(sigStream);
  3651. sigIx = md.AddToBlobHeap(sigStream.ToArray());
  3652. done = false;
  3653. }
  3654. internal override void BuildCILInfo(CILWriter output) {
  3655. parent.BuildCILInfo(output);
  3656. }
  3657. internal static uint Size(MetaData md) {
  3658. return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
  3659. }
  3660. internal sealed override void Write(PEWriter output) {
  3661. if (varArgParent != null)
  3662. output.WriteCodedIndex(CIx.MemberRefParent,varArgParent);
  3663. else
  3664. output.WriteCodedIndex(CIx.MemberRefParent,parent);
  3665. output.StringsIndex(nameIx);
  3666. output.BlobIndex(sigIx);
  3667. }
  3668. internal sealed override uint GetCodedIx(CIx code) {
  3669. switch (code) {
  3670. case (CIx.HasCustomAttr) : return 6;
  3671. case (CIx.MethodDefOrRef) : return 1;
  3672. case (CIx.CustomAttributeType) : return 3;
  3673. }
  3674. return 0;
  3675. }
  3676. }
  3677. /**************************************************************************/
  3678. /// <summary>
  3679. /// Descriptor for an overriding method (.override)
  3680. /// </summary>
  3681. public class MethodImpl : MetaDataElement {
  3682. ClassDef parent;
  3683. Method header, body;
  3684. uint classIx = 0, methBodyIx = 0, methDeclIx = 0;
  3685. bool resolved = true;
  3686. /*-------------------- Constructors ---------------------------------*/
  3687. internal MethodImpl(ClassDef par, Method decl, Method bod) {
  3688. parent = par;
  3689. header = decl;
  3690. body = bod;
  3691. tabIx = MDTable.MethodImpl;
  3692. }
  3693. internal MethodImpl(PEReader buff, ClassDef par, uint bIx, uint dIx) {
  3694. buffer = buff;
  3695. parent = par;
  3696. methBodyIx = bIx;
  3697. methDeclIx = dIx;
  3698. tabIx = MDTable.MethodImpl;
  3699. resolved = false;
  3700. }
  3701. internal MethodImpl(PEReader buff) {
  3702. classIx = buff.GetIndex(MDTable.TypeDef);
  3703. methBodyIx = buff.GetCodedIndex(CIx.MethodDefOrRef);
  3704. methDeclIx = buff.GetCodedIndex(CIx.MethodDefOrRef);
  3705. tabIx = MDTable.MethodImpl;
  3706. }
  3707. /*internal static MethodImpl[] GetMethodImpls(PEReader buff, ClassDef paren, uint classIx) {
  3708. buff.SetElementPosition(MDTable.MethodImpl,0);
  3709. ArrayList impls = new ArrayList();
  3710. for (int i=0; i < buff.GetTableSize(MDTable.MethodImpl); i++) {
  3711. uint cIx = buff.GetIndex(MDTable.TypeDef);
  3712. uint bIx = buff.GetCodedIndex(CIx.MethodDefOrRef);
  3713. uint dIx = buff.GetCodedIndex(CIx.MethodDefOrRef);
  3714. if (cIx == classIx)
  3715. paren.AddMethodOverride(new MethodImpl(buff,paren,bIx,dIx));
  3716. }
  3717. return (MethodImpl[])impls.ToArray(typeof(MethodImpl));
  3718. }
  3719. */
  3720. public Method Body {
  3721. get {
  3722. if ((body == null) && (methBodyIx != 0))
  3723. body = (Method)buffer.GetCodedElement(CIx.MethodDefOrRef,methBodyIx);
  3724. return body;
  3725. }
  3726. set {
  3727. body = value;
  3728. if ((!resolved) && (header != null)) resolved = true;
  3729. }
  3730. }
  3731. public Method Header {
  3732. get {
  3733. if ((header == null) && (methDeclIx != 0))
  3734. header = (Method)buffer.GetCodedElement(CIx.MethodDefOrRef,methDeclIx);
  3735. return header;
  3736. }
  3737. set {
  3738. header = value;
  3739. if ((!resolved) && (body != null)) resolved = true;
  3740. }
  3741. }
  3742. internal void SetOwner(ClassDef cl) {
  3743. parent = cl;
  3744. }
  3745. internal static void Read(PEReader buff, TableRow[] impls) {
  3746. for (int i=0; i < impls.Length; i++)
  3747. impls[i] = new MethodImpl(buff);
  3748. }
  3749. internal override void Resolve(PEReader buff) {
  3750. body = (Method)buff.GetCodedElement(CIx.MethodDefOrRef,methBodyIx);
  3751. header = (Method)buff.GetCodedElement(CIx.MethodDefOrRef,methDeclIx);
  3752. parent = (ClassDef)buff.GetElement(MDTable.TypeDef,classIx);
  3753. parent.AddMethodImpl(this);
  3754. resolved = true;
  3755. }
  3756. internal void ResolveMethDetails() {
  3757. body = (Method)buffer.GetCodedElement(CIx.MethodDefOrRef,methBodyIx);
  3758. header = (Method)buffer.GetCodedElement(CIx.MethodDefOrRef,methDeclIx);
  3759. resolved = true;
  3760. }
  3761. internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) {
  3762. throw new NotYetImplementedException("Merge for MethodImpls");
  3763. }
  3764. internal sealed override void BuildTables(MetaDataOut md) {
  3765. md.AddToTable(MDTable.MethodImpl,this);
  3766. if (!resolved) ResolveMethDetails();
  3767. if (body is MethodRef) body.BuildMDTables(md);
  3768. if (header is MethodRef) header.BuildMDTables(md);
  3769. }
  3770. internal static uint Size(MetaData md) {
  3771. return md.TableIndexSize(MDTable.TypeDef) + 2 * md.CodedIndexSize(CIx.MethodDefOrRef);
  3772. }
  3773. internal sealed override void Write(PEWriter output) {
  3774. output.WriteIndex(MDTable.TypeDef,parent.Row);
  3775. output.WriteCodedIndex(CIx.MethodDefOrRef,body);
  3776. output.WriteCodedIndex(CIx.MethodDefOrRef,header);
  3777. }
  3778. }
  3779. /**************************************************************************/
  3780. /// <summary>
  3781. /// Descriptor for Property and Event methods
  3782. /// </summary>
  3783. public class MethodSemantics : MetaDataElement {
  3784. MethodType type;
  3785. MethodDef meth;
  3786. Feature eventOrProp;
  3787. uint methIx = 0, assocIx = 0;
  3788. /*-------------------- Constructors ---------------------------------*/
  3789. internal MethodSemantics(MethodType mType, MethodDef method, Feature feature) {
  3790. type = mType;
  3791. meth = method;
  3792. eventOrProp = feature;
  3793. sortTable = true;
  3794. tabIx = MDTable.MethodSemantics;
  3795. }
  3796. internal MethodSemantics(PEReader buff) {
  3797. type = (MethodType)buff.ReadUInt16();
  3798. methIx = buff.GetIndex(MDTable.Method);
  3799. assocIx = buff.GetCodedIndex(CIx.HasSemantics);
  3800. sortTable = true;
  3801. tabIx = MDTable.MethodSemantics;
  3802. }
  3803. internal static void Read(PEReader buff, TableRow[] methSems) {
  3804. for (int i=0; i < methSems.Length; i++)
  3805. methSems[i] = new MethodSemantics(buff);
  3806. }
  3807. internal override void Resolve(PEReader buff) {
  3808. meth = (MethodDef)buff.GetElement(MDTable.Method,methIx);
  3809. eventOrProp = (Feature)buff.GetCodedElement(CIx.HasSemantics,assocIx);
  3810. eventOrProp.AddMethod(this);
  3811. }
  3812. internal MethodType GetMethodType() { return type; }
  3813. internal MethodDef GetMethod() { return meth; }
  3814. internal override uint SortKey() {
  3815. return meth.Row;
  3816. }
  3817. internal sealed override void BuildTables(MetaDataOut md) {
  3818. md.AddToTable(MDTable.MethodSemantics,this);
  3819. }
  3820. internal static uint Size(MetaData md) {
  3821. return 2 + md.TableIndexSize(MDTable.Method) + md.CodedIndexSize(CIx.HasSemantics);
  3822. }
  3823. internal sealed override void Write(PEWriter output) {
  3824. output.Write((ushort)type);
  3825. output.WriteIndex(MDTable.Method,meth.Row);
  3826. output.WriteCodedIndex(CIx.HasSemantics,eventOrProp);
  3827. }
  3828. }
  3829. /**************************************************************************/
  3830. /// <summary>
  3831. /// Descriptor for a parameter of a method defined in this assembly/module
  3832. /// </summary>
  3833. public class Param : MetaDataElement {
  3834. private static readonly ushort hasDefault = 0x1000;
  3835. private static readonly ushort noDefault = 0xEFFF;
  3836. private static readonly ushort hasFieldMarshal = 0x2000;
  3837. private static readonly ushort noFieldMarshal = 0xDFFF;
  3838. protected string pName;
  3839. protected uint nameIx = 0;
  3840. Type pType;
  3841. internal ushort seqNo = 0;
  3842. ushort parMode;
  3843. Constant defaultVal;
  3844. NativeType marshalType;
  3845. /*-------------------- Constructors ---------------------------------*/
  3846. /// <summary>
  3847. /// Create a new parameter for a method
  3848. /// </summary>
  3849. /// <param name="mode">param mode (in, out, opt)</param>
  3850. /// <param name="parName">parameter name</param>
  3851. /// <param name="parType">parameter type</param>
  3852. public Param(ParamAttr mode, string parName, Type parType) {
  3853. pName = parName;
  3854. pType = parType;
  3855. parMode = (ushort)mode;
  3856. tabIx = MDTable.Param;
  3857. }
  3858. internal Param(PEReader buff) {
  3859. parMode = buff.ReadUInt16();
  3860. seqNo = buff.ReadUInt16();
  3861. pName = buff.GetString();
  3862. tabIx = MDTable.Param;
  3863. }
  3864. internal static void Read(PEReader buff, TableRow[] pars) {
  3865. for (int i=0; i < pars.Length; i++)
  3866. pars[i] = new Param(buff);
  3867. }
  3868. internal void Resolve(PEReader buff, uint fIx, Type type) {
  3869. this.pType = type;
  3870. /* marshalType = FieldMarshal.FindMarshalType(buff,this,
  3871. buff.MakeCodedIndex(CIx.HasFieldMarshal,MDTable.Param,fIx));
  3872. defaultVal = ConstantElem.FindConst(buff,this,
  3873. buff.MakeCodedIndex(CIx.HasConstant,MDTable.Param,fIx));
  3874. */
  3875. }
  3876. /// <summary>
  3877. /// Add a default value to this parameter
  3878. /// </summary>
  3879. /// <param name="cVal">the default value for the parameter</param>
  3880. public void AddDefaultValue(Constant cVal) {
  3881. defaultVal = cVal;
  3882. parMode |= hasDefault;
  3883. }
  3884. /// <summary>
  3885. /// Get the default constant value for this parameter
  3886. /// </summary>
  3887. /// <returns></returns>
  3888. public Constant GetDefaultValue() { return defaultVal; }
  3889. /// <summary>
  3890. /// Remove the default constant value for this parameter
  3891. /// </summary>
  3892. public void RemoveDefaultValue() { defaultVal = null; parMode &= noDefault; }
  3893. /// <summary>
  3894. /// Add marshalling information about this parameter
  3895. /// </summary>
  3896. public void SetMarshalType (NativeType mType) {
  3897. marshalType = mType;
  3898. parMode |= hasFieldMarshal;
  3899. }
  3900. /// <summary>
  3901. /// Get the parameter marshalling information
  3902. /// </summary>
  3903. /// <returns>The native type to marshall to</returns>
  3904. public NativeType GetMarshalType () { return marshalType; }
  3905. /// <summary>
  3906. /// Remove any marshalling information for this parameter
  3907. /// </summary>
  3908. public void RemoveMashalType() { marshalType = null; parMode &= noFieldMarshal; }
  3909. /// <summary>
  3910. /// Get the type of this parameter
  3911. /// </summary>
  3912. public Type GetParType() { return pType; }
  3913. /// <summary>
  3914. /// Set the type of this parameter
  3915. /// </summary>
  3916. public void SetParType(Type parType) { pType = parType; }
  3917. public void AddAttribute(ParamAttr att) {
  3918. this.parMode |= (ushort)att;
  3919. }
  3920. public ParamAttr GetAttributes() { return (ParamAttr)parMode; }
  3921. public void SetAttributes(ParamAttr att) {
  3922. this.parMode = (ushort)att;
  3923. }
  3924. /// <summary>
  3925. /// Retrieve the name of this parameter
  3926. /// </summary>
  3927. /// <returns>parameter name</returns>
  3928. public string GetName() { return pName; }
  3929. /// <summary>
  3930. /// Set the name of this parameter
  3931. /// </summary>
  3932. /// <param name="nam">parameter name</param>
  3933. public void SetName(string nam) { pName = nam; }
  3934. /*------------------------ internal functions ----------------------------*/
  3935. internal Param Copy(Type paramType) {
  3936. return new Param((ParamAttr)parMode,pName,paramType);
  3937. }
  3938. internal sealed override void BuildTables(MetaDataOut md) {
  3939. md.AddToTable(MDTable.Param,this);
  3940. nameIx = md.AddToStringsHeap(pName);
  3941. if (defaultVal != null) {
  3942. ConstantElem constElem = new ConstantElem(this,defaultVal);
  3943. constElem.BuildMDTables(md);
  3944. }
  3945. if (marshalType != null) {
  3946. FieldMarshal marshalInfo = new FieldMarshal(this,marshalType);
  3947. marshalInfo.BuildMDTables(md);
  3948. }
  3949. }
  3950. internal override void BuildCILInfo(CILWriter output) {
  3951. pType.BuildCILInfo(output);
  3952. }
  3953. internal void TypeSig(MemoryStream str) {
  3954. pType.TypeSig(str);
  3955. }
  3956. internal static uint Size(MetaData md) {
  3957. return 4 + md.StringsIndexSize();
  3958. }
  3959. internal sealed override void Write(PEWriter output) {
  3960. output.Write(parMode);
  3961. output.Write(seqNo);
  3962. output.StringsIndex(nameIx);
  3963. }
  3964. internal override void Write(CILWriter output) {
  3965. pType.WriteType(output);
  3966. output.Write(" " + pName);
  3967. }
  3968. internal sealed override uint GetCodedIx(CIx code) {
  3969. switch (code) {
  3970. case (CIx.HasCustomAttr) : return 4;
  3971. case (CIx.HasConstant) : return 1;
  3972. case (CIx.HasFieldMarshal) : return 1;
  3973. }
  3974. return 0;
  3975. }
  3976. }
  3977. /**************************************************************************/
  3978. /// <summary>
  3979. /// Base class for scopes (extended by Module, ModuleRef, Assembly, AssemblyRef)
  3980. /// </summary>
  3981. public abstract class ResolutionScope : MetaDataElement {
  3982. internal protected uint nameIx = 0;
  3983. internal protected string name;
  3984. internal protected ArrayList classes = new ArrayList();
  3985. internal protected bool readAsDef = false;
  3986. /*-------------------- Constructors ---------------------------------*/
  3987. internal ResolutionScope(string name) {
  3988. this.name = name;
  3989. }
  3990. internal virtual void AddToClassList(Class aClass) {
  3991. classes.Add(aClass);
  3992. }
  3993. internal Class GetExistingClass(string nameSpace, string name) {
  3994. for (int i=0; i < classes.Count; i++) {
  3995. Class aClass = (Class)classes[i];
  3996. if ((aClass.Name() == name) && (aClass.NameSpace() == nameSpace))
  3997. return aClass;
  3998. }
  3999. return null;
  4000. }
  4001. protected Class GetClass(string nameSpace, string name, bool both) {
  4002. for (int i=0; i < classes.Count; i++) {
  4003. Object aClass = classes[i];
  4004. if ((((Class)aClass).Name() == name) &&
  4005. (!both || (both && (((Class)aClass).NameSpace() == nameSpace))))
  4006. return (Class)aClass;
  4007. }
  4008. return null;
  4009. }
  4010. /// <summary>
  4011. /// Delete a class from this module
  4012. /// </summary>
  4013. /// <param name="aClass">The name of the class to be deleted</param>
  4014. public void RemoveClass(Class aClass) {
  4015. classes.Remove(aClass);
  4016. }
  4017. /// <summary>
  4018. /// Delete the class at an index in the class array
  4019. /// </summary>
  4020. /// <param name="ix">The index of the class to be deleted (from 0)</param>
  4021. public void RemoveClass(int ix) {
  4022. classes.RemoveAt(ix);
  4023. }
  4024. public string Name() { return name; }
  4025. internal override string NameString() { return "[" + name + "]"; }
  4026. }
  4027. /**************************************************************************/
  4028. /// <summary>
  4029. /// A scope for definitions
  4030. /// </summary>
  4031. public abstract class DefiningScope : ResolutionScope {
  4032. /*-------------------- Constructors ---------------------------------*/
  4033. internal DefiningScope(string name) : base(name) {
  4034. readAsDef = true;
  4035. }
  4036. internal override void AddToClassList(Class aClass) {
  4037. ((ClassDef)aClass).SetScope((PEFile)this);
  4038. classes.Add(aClass);
  4039. }
  4040. }
  4041. /**************************************************************************/
  4042. /// <summary>
  4043. /// Descriptor for an assembly (.assembly)
  4044. /// </summary>
  4045. public class Assembly : DefiningScope {
  4046. //internal static Hashtable Assemblies = new Hashtable();
  4047. ushort majorVer, minorVer, buildNo, revisionNo;
  4048. uint flags;
  4049. HashAlgorithmType hashAlgId = HashAlgorithmType.None;
  4050. uint keyIx = 0, cultIx = 0;
  4051. byte[] publicKey;
  4052. string culture;
  4053. internal AssemblyRef refOf;
  4054. ArrayList security;
  4055. internal PEFile pefile;
  4056. /*-------------------- Constructors ---------------------------------*/
  4057. internal Assembly(string name, PEFile pefile) : base(name) {
  4058. this.pefile = pefile;
  4059. tabIx = MDTable.Assembly;
  4060. }
  4061. internal Assembly(string name, HashAlgorithmType hashAlgId, ushort majVer,
  4062. ushort minVer, ushort bldNo, ushort revNo, uint flags, byte[] pKey,
  4063. string cult, PEFile pefile ) : base(name) {
  4064. this.hashAlgId = hashAlgId;
  4065. this.majorVer = majVer;
  4066. this.minorVer = minVer;
  4067. this.buildNo = bldNo;
  4068. this.revisionNo = revNo;
  4069. this.flags = flags;
  4070. this.publicKey = pKey;
  4071. this.culture = cult;
  4072. tabIx = MDTable.Assembly;
  4073. }
  4074. internal static AssemblyRef ReadAssemblyRef(PEReader buff) {
  4075. buff.SetElementPosition(MDTable.Assembly,1);
  4076. HashAlgorithmType hAlg = (HashAlgorithmType)buff.ReadUInt32();
  4077. ushort majVer = buff.ReadUInt16();
  4078. ushort minVer = buff.ReadUInt16();
  4079. ushort bldNo = buff.ReadUInt16();
  4080. ushort revNo = buff.ReadUInt16();
  4081. uint flags = buff.ReadUInt32();
  4082. byte[] pKey = buff.GetBlob();
  4083. string name = buff.GetString();
  4084. string cult = buff.GetString();
  4085. AssemblyRef assemRef = null;
  4086. if (name.ToLower() == "mscorlib") {
  4087. assemRef = MSCorLib.mscorlib;
  4088. assemRef.AddVersionInfo(majVer,minVer,bldNo,revNo);
  4089. if (pKey.Length > 8) assemRef.AddKey(pKey);
  4090. else assemRef.AddKeyToken(pKey);
  4091. assemRef.AddCulture(cult);
  4092. assemRef.SetFlags(flags);
  4093. } else {
  4094. assemRef = new AssemblyRef(name,majVer,minVer,bldNo,revNo,flags,pKey,cult,null);
  4095. }
  4096. //AssemblyRef assemRef = new AssemblyRef(name,majVer,minVer,bldNo,revNo,flags,pKey,cult,null);
  4097. assemRef.ReadAsDef();
  4098. return assemRef;
  4099. }
  4100. internal static void Read(PEReader buff, TableRow[] table, PEFile pefile) {
  4101. for (int i=0; i < table.Length; i++) {
  4102. HashAlgorithmType hAlg = (HashAlgorithmType)buff.ReadUInt32();
  4103. ushort majVer = buff.ReadUInt16();
  4104. ushort minVer = buff.ReadUInt16();
  4105. ushort bldNo = buff.ReadUInt16();
  4106. ushort revNo = buff.ReadUInt16();
  4107. uint flags = buff.ReadUInt32();
  4108. byte[] pKey = buff.GetBlob();
  4109. string name = buff.GetString();
  4110. string cult = buff.GetString();
  4111. table[i] = new Assembly(name,hAlg,majVer,minVer,bldNo,revNo,flags,pKey,cult,pefile);
  4112. }
  4113. }
  4114. /*------------------------- public set and get methods --------------------------*/
  4115. /// <summary>
  4116. /// Add details about an assembly
  4117. /// </summary>
  4118. /// <param name="majVer">Major Version</param>
  4119. /// <param name="minVer">Minor Version</param>
  4120. /// <param name="bldNo">Build Number</param>
  4121. /// <param name="revNo">Revision Number</param>
  4122. /// <param name="key">Hash Key</param>
  4123. /// <param name="hash">Hash Algorithm</param>
  4124. /// <param name="cult">Culture</param>
  4125. public void AddAssemblyInfo(int majVer, int minVer, int bldNo, int revNo,
  4126. byte[] key, HashAlgorithmType hash, string cult) {
  4127. majorVer = (ushort)majVer;
  4128. minorVer = (ushort)minVer;
  4129. buildNo = (ushort)bldNo;
  4130. revisionNo = (ushort)revNo;
  4131. hashAlgId = hash;
  4132. publicKey = key;
  4133. culture = cult;
  4134. }
  4135. /// <summary>
  4136. /// Get the major version number for this Assembly
  4137. /// </summary>
  4138. /// <returns>major version number</returns>
  4139. public int MajorVersion () { return majorVer; }
  4140. /// <summary>
  4141. /// Get the minor version number for this Assembly
  4142. /// </summary>
  4143. /// <returns>minor version number</returns>
  4144. public int MinorVersion () { return minorVer; }
  4145. /// <summary>
  4146. /// Get the build number for this Assembly
  4147. /// </summary>
  4148. /// <returns>build number</returns>
  4149. public int BuildNumber () { return buildNo; }
  4150. /// <summary>
  4151. /// Get the revision number for this Assembly
  4152. /// </summary>
  4153. /// <returns>revision number</returns>
  4154. public int RevisionNumber () { return revisionNo; }
  4155. /// <summary>
  4156. /// Get the public key for this Assembly
  4157. /// </summary>
  4158. /// <returns>public key bytes</returns>
  4159. public byte[] Key () { return publicKey; }
  4160. /// <summary>
  4161. /// Get the type of the hash algorithm for this Assembly
  4162. /// </summary>
  4163. /// <returns>hash algorithm type</returns>
  4164. public HashAlgorithmType HashAlgorithm () { return hashAlgId; }
  4165. /// <summary>
  4166. /// Get the culture information for this Assembly
  4167. /// </summary>
  4168. /// <returns>culture string</returns>
  4169. public string Culture () { return culture; }
  4170. /// <summary>
  4171. /// Add some security action(s) to this Assembly
  4172. /// </summary>
  4173. public void AddSecurity(SecurityAction act, byte[] permissionSet) {
  4174. AddSecurity(new DeclSecurity(this,act,permissionSet));
  4175. // securityActions = permissionSet;
  4176. }
  4177. /// <summary>
  4178. /// Get the security information for this assembly
  4179. /// </summary>
  4180. /// <returns>security information</returns>
  4181. public DeclSecurity[] GetSecurity() {
  4182. if (security == null) return null;
  4183. return (DeclSecurity[])security.ToArray(typeof(DeclSecurity));
  4184. }
  4185. /// <summary>
  4186. /// Check if this assembly has security information
  4187. /// </summary>
  4188. public bool HasSecurity() { return security != null; }
  4189. /// <summary>
  4190. /// Set the attributes for this assembly
  4191. /// </summary>
  4192. /// <param name="aa">assembly attribute</param>
  4193. public void SetAssemblyAttr(AssemAttr aa) {
  4194. flags = (uint)aa;
  4195. }
  4196. /// <summary>
  4197. /// Add an attribute for this assembly
  4198. /// </summary>
  4199. /// <param name="aa">assembly attribute</param>
  4200. public void AddAssemblyAttr(AssemAttr aa) {
  4201. flags |= (uint)aa;
  4202. }
  4203. /// <summary>
  4204. /// Get the attributes of this assembly
  4205. /// </summary>
  4206. /// <returns>assembly attributes</returns>
  4207. public AssemAttr AssemblyAttributes() {
  4208. return (AssemAttr)flags;
  4209. }
  4210. /// <summary>
  4211. /// Make an AssemblyRef descriptor for this Assembly
  4212. /// </summary>
  4213. /// <returns>AssemblyRef descriptor for this Assembly</returns>
  4214. public AssemblyRef MakeRefOf() {
  4215. if (refOf == null) {
  4216. refOf = new AssemblyRef(name,majorVer,minorVer,buildNo,revisionNo,
  4217. flags,publicKey,culture,null);
  4218. }
  4219. return refOf;
  4220. }
  4221. /*------------------------ internal functions ----------------------------*/
  4222. internal void AddSecurity(DeclSecurity sec) {
  4223. if (security == null) security = new ArrayList();
  4224. security.Add(sec);
  4225. }
  4226. internal static uint Size(MetaData md) {
  4227. return 16 + md.BlobIndexSize() + 2 * md.StringsIndexSize();
  4228. }
  4229. internal sealed override void BuildTables(MetaDataOut md) {
  4230. md.AddToTable(MDTable.Assembly,this);
  4231. nameIx = md.AddToStringsHeap(name);
  4232. cultIx = md.AddToStringsHeap(culture);
  4233. keyIx = md.AddToBlobHeap(publicKey);
  4234. if (security != null) {
  4235. for (int i=0; i < security.Count; i++) {
  4236. ((DeclSecurity)security[i]).BuildMDTables(md);
  4237. }
  4238. }
  4239. }
  4240. internal sealed override void Write(PEWriter output) {
  4241. //Console.WriteLine("Writing assembly element with nameIx of " + nameIx + " at file offset " + output.Seek(0,SeekOrigin.Current));
  4242. output.Write((uint)hashAlgId);
  4243. output.Write(majorVer);
  4244. output.Write(minorVer);
  4245. output.Write(buildNo);
  4246. output.Write(revisionNo);
  4247. output.Write(flags);
  4248. output.BlobIndex(keyIx);
  4249. output.StringsIndex(nameIx);
  4250. output.StringsIndex(cultIx);
  4251. }
  4252. internal override void Write(CILWriter output) {
  4253. output.WriteLine(".assembly " + name + " { }");
  4254. }
  4255. internal sealed override uint GetCodedIx(CIx code) {
  4256. switch (code) {
  4257. case (CIx.HasCustomAttr) : return 14;
  4258. case (CIx.HasDeclSecurity) : return 2;
  4259. }
  4260. return 0;
  4261. }
  4262. }
  4263. /**************************************************************************/
  4264. /// <summary>
  4265. /// Descriptor for a module
  4266. /// </summary>
  4267. public abstract class Module : DefiningScope {
  4268. Guid mvid;
  4269. uint mvidIx = 0;
  4270. internal ModuleRef refOf;
  4271. /// <summary>
  4272. /// The default class "Module" for globals
  4273. /// </summary>
  4274. protected ClassDef defaultClass;
  4275. /// <summary>
  4276. /// Is this module a .dll or .exe
  4277. /// </summary>
  4278. //protected bool isDLL;
  4279. /// <summary>
  4280. /// Is this module mscorlib.dll
  4281. /// </summary>
  4282. protected bool ismscorlib = false;
  4283. /// <summary>
  4284. /// Managed resources for this module
  4285. /// </summary>
  4286. protected ArrayList resources = new ArrayList();
  4287. /*-------------------- Constructors ---------------------------------*/
  4288. internal Module(string mName) : base(GetBaseName(mName)) {
  4289. mvid = Guid.NewGuid();
  4290. //isDLL = name.EndsWith(".dll") || name.EndsWith(".DLL");
  4291. defaultClass = new ClassDef((PEFile)this,TypeAttr.Private,"","<Module>");
  4292. defaultClass.MakeSpecial();
  4293. tabIx = MDTable.Module;
  4294. ismscorlib = name.ToLower() == "mscorlib.dll";
  4295. if (Diag.DiagOn) Console.WriteLine("Module name = " + name);
  4296. }
  4297. internal void Read(PEReader buff) {
  4298. buff.ReadZeros(2);
  4299. name = buff.GetString();
  4300. mvid = buff.GetGUID();
  4301. uint junk = buff.GetGUIDIx();
  4302. junk = buff.GetGUIDIx();
  4303. if (Diag.DiagOn) Console.WriteLine("Reading module with name " + name + " and Mvid = " + mvid);
  4304. ismscorlib = name.ToLower() == "mscorlib.dll";
  4305. }
  4306. internal static ModuleRef ReadModuleRef(PEReader buff) {
  4307. buff.ReadZeros(2);
  4308. string name = buff.GetString();
  4309. uint junk = buff.GetGUIDIx();
  4310. junk = buff.GetGUIDIx();
  4311. junk = buff.GetGUIDIx();
  4312. ModuleRef mRef = new ModuleRef(new ModuleFile(name,null));
  4313. mRef.ReadAsDef();
  4314. return mRef;
  4315. }
  4316. /*------------------------- public set and get methods --------------------------*/
  4317. /// <summary>
  4318. /// Add a class to this Module
  4319. /// If this class already exists, throw an exception
  4320. /// </summary>
  4321. /// <param name="attrSet">attributes of this class</param>
  4322. /// <param name="nsName">name space name</param>
  4323. /// <param name="name">class name</param>
  4324. /// <returns>a descriptor for this new class</returns>
  4325. public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) {
  4326. ClassDef aClass = GetClass(nsName,name);
  4327. if (aClass != null)
  4328. throw new DescriptorException("Class " + aClass.NameString());
  4329. aClass = new ClassDef((PEFile)this,attrSet,nsName,name);
  4330. classes.Add(aClass);
  4331. return aClass;
  4332. }
  4333. /// <summary>
  4334. /// Add a class which extends System.ValueType to this Module
  4335. /// If this class already exists, throw an exception
  4336. /// </summary>
  4337. /// <param name="attrSet">attributes of this class</param>
  4338. /// <param name="nsName">name space name</param>
  4339. /// <param name="name">class name</param>
  4340. /// <returns>a descriptor for this new class</returns>
  4341. public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name) {
  4342. ClassDef aClass = AddClass(attrSet,nsName,name);
  4343. aClass.SuperType = MSCorLib.mscorlib.ValueType();
  4344. aClass.MakeValueClass();
  4345. return aClass;
  4346. }
  4347. /// <summary>
  4348. /// Add a class to this PE File
  4349. /// </summary>
  4350. /// <param name="attrSet">attributes of this class</param>
  4351. /// <param name="nsName">name space name</param>
  4352. /// <param name="name">class name</param>
  4353. /// <param name="superType">super type of this class (extends)</param>
  4354. /// <returns>a descriptor for this new class</returns>
  4355. public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) {
  4356. ClassDef aClass = AddClass(attrSet,nsName,name);
  4357. aClass.SuperType = superType;
  4358. return aClass;
  4359. }
  4360. /// <summary>
  4361. /// Add a class to this module
  4362. /// If this class already exists, throw an exception
  4363. /// </summary>
  4364. /// <param name="aClass">The class to be added</param>
  4365. public void AddClass(ClassDef aClass) {
  4366. ClassDef eClass = GetClass(aClass.NameSpace(),aClass.Name());
  4367. if (eClass != null)
  4368. throw new DescriptorException("Class " + aClass.NameString());
  4369. classes.Add(aClass);
  4370. // MERGE change Refs to Defs here, fix this
  4371. aClass.SetScope((PEFile)this);
  4372. }
  4373. /// <summary>
  4374. /// Get a class of this module, if no class exists, return null
  4375. /// </summary>
  4376. /// <param name="name">The name of the class to get</param>
  4377. /// <returns>ClassDef for name or null</returns>
  4378. public ClassDef GetClass(string name) {
  4379. return (ClassDef)GetClass(null,name,false);
  4380. }
  4381. /// <summary>
  4382. /// Get a class of this module, if no class exists, return null
  4383. /// </summary>
  4384. /// <param name="nsName">The namespace of the class</param>
  4385. /// <param name="name">The name of the class to get</param>
  4386. /// <returns>ClassDef for nsName.name or null</returns>
  4387. public ClassDef GetClass(string nsName,string name) {
  4388. return (ClassDef)GetClass(nsName,name,true);
  4389. }
  4390. /// <summary>
  4391. /// Get all the classes of this module
  4392. /// </summary>
  4393. /// <returns>An array containing a ClassDef for each class of this module</returns>
  4394. public ClassDef[] GetClasses() {
  4395. return (ClassDef[])classes.ToArray(typeof(ClassDef));
  4396. }
  4397. /// <summary>
  4398. /// Add a "global" method to this module
  4399. /// </summary>
  4400. /// <param name="name">method name</param>
  4401. /// <param name="retType">return type</param>
  4402. /// <param name="pars">method parameters</param>
  4403. /// <returns>a descriptor for this new "global" method</returns>
  4404. public MethodDef AddMethod(string name, Type retType, Param[] pars) {
  4405. MethodDef newMeth = defaultClass.AddMethod(name,retType,pars);
  4406. return newMeth;
  4407. }
  4408. /// <summary>
  4409. /// Add a "global" method to this module
  4410. /// </summary>
  4411. /// <param name="name">method name</param>
  4412. /// <param name="genPars">generic parameters</param>
  4413. /// <param name="retType">return type</param>
  4414. /// <param name="pars">method parameters</param>
  4415. /// <returns>a descriptor for this new "global" method</returns>
  4416. public MethodDef AddMethod(string name, GenericParam[] genPars, Type retType, Param[] pars) {
  4417. MethodDef newMeth = defaultClass.AddMethod(name,genPars,retType,pars);
  4418. return newMeth;
  4419. }
  4420. /// <summary>
  4421. /// Add a "global" method to this module
  4422. /// </summary>
  4423. /// <param name="mAtts">method attributes</param>
  4424. /// <param name="iAtts">method implementation attributes</param>
  4425. /// <param name="name">method name</param>
  4426. /// <param name="retType">return type</param>
  4427. /// <param name="pars">method parameters</param>
  4428. /// <returns>a descriptor for this new "global" method</returns>
  4429. public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) {
  4430. MethodDef newMeth = defaultClass.AddMethod(mAtts,iAtts,name,retType,pars);
  4431. return newMeth;
  4432. }
  4433. /// <summary>
  4434. /// Add a "global" method to this module
  4435. /// </summary>
  4436. /// <param name="mAtts">method attributes</param>
  4437. /// <param name="iAtts">method implementation attributes</param>
  4438. /// <param name="name">method name</param>
  4439. /// <param name="genPars">generic parameters</param>
  4440. /// <param name="retType">return type</param>
  4441. /// <param name="pars">method parameters</param>
  4442. /// <returns>a descriptor for this new "global" method</returns>
  4443. public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, GenericParam[] genPars, Type retType, Param[] pars) {
  4444. MethodDef newMeth = defaultClass.AddMethod(mAtts,iAtts,name,genPars,retType,pars);
  4445. return newMeth;
  4446. }
  4447. /// <summary>
  4448. /// Add a "global" method to this module
  4449. /// </summary>
  4450. /// <param name="meth">The method to be added</param>
  4451. public void AddMethod(MethodDef meth) {
  4452. defaultClass.AddMethod(meth);
  4453. }
  4454. /// <summary>
  4455. /// Get a method of this module, if it exists
  4456. /// </summary>
  4457. /// <param name="name">The name of the method to get</param>
  4458. /// <returns>MethodDef for name, or null if one does not exist</returns>
  4459. public MethodDef GetMethod(string name) {
  4460. return defaultClass.GetMethod(name);
  4461. }
  4462. /// <summary>
  4463. /// Get all the methods of this module with a specified name
  4464. /// </summary>
  4465. /// <param name="name">The name of the method(s)</param>
  4466. /// <returns>An array of all the methods of this module called "name" </returns>
  4467. public MethodDef[] GetMethods(string name) {
  4468. return defaultClass.GetMethods(name);
  4469. }
  4470. /// <summary>
  4471. /// Get a method of this module, if it exists
  4472. /// </summary>
  4473. /// <param name="name">The name of the method to get</param>
  4474. /// <param name="parTypes">The signature of the method</param>
  4475. /// <returns>MethodDef for name(parTypes), or null if one does not exist</returns>
  4476. public MethodDef GetMethod(string name, Type[] parTypes) {
  4477. return defaultClass.GetMethod(name, parTypes);
  4478. }
  4479. /// <summary>
  4480. /// Get all the methods of this module
  4481. /// </summary>
  4482. /// <returns>An array of all the methods of this module</returns>
  4483. public MethodDef[] GetMethods() {
  4484. return defaultClass.GetMethods();
  4485. }
  4486. /// <summary>
  4487. /// Delete a method from this module
  4488. /// </summary>
  4489. /// <param name="meth">The method to be deleted</param>
  4490. public void RemoveMethod(MethodDef meth) {
  4491. defaultClass.RemoveMethod(meth);
  4492. }
  4493. /// <summary>
  4494. /// Delete a method from this module
  4495. /// </summary>
  4496. /// <param name="name">The name of the method to be deleted</param>
  4497. public void RemoveMethod(string name) {
  4498. defaultClass.RemoveMethod(name);
  4499. }
  4500. /// <summary>
  4501. /// Delete a method from this module
  4502. /// </summary>
  4503. /// <param name="name">The name of the method to be deleted</param>
  4504. /// <param name="parTypes">The signature of the method to be deleted</param>
  4505. public void RemoveMethod(string name, Type[] parTypes) {
  4506. defaultClass.RemoveMethod(name,parTypes);
  4507. }
  4508. /// <summary>
  4509. /// Delete a method from this module
  4510. /// </summary>
  4511. /// <param name="ix">The index of the method (in the method array
  4512. /// returned by GetMethods()) to be deleted</param>
  4513. public void RemoveMethod(int ix) {
  4514. defaultClass.RemoveMethod(ix);
  4515. }
  4516. /// <summary>
  4517. /// Add a "global" field to this module
  4518. /// </summary>
  4519. /// <param name="name">field name</param>
  4520. /// <param name="fType">field type</param>
  4521. /// <returns>a descriptor for this new "global" field</returns>
  4522. public FieldDef AddField(string name, Type fType) {
  4523. FieldDef newField = defaultClass.AddField(name,fType);
  4524. return newField;
  4525. }
  4526. /// <summary>
  4527. /// Add a "global" field to this module
  4528. /// </summary>
  4529. /// <param name="attrSet">attributes of this field</param>
  4530. /// <param name="name">field name</param>
  4531. /// <param name="fType">field type</param>
  4532. /// <returns>a descriptor for this new "global" field</returns>
  4533. public FieldDef AddField(FieldAttr attrSet, string name, Type fType) {
  4534. FieldDef newField = defaultClass.AddField(attrSet,name,fType);
  4535. return newField;
  4536. }
  4537. /// <summary>
  4538. /// Add a "global" field to this module
  4539. /// </summary>
  4540. /// <param name="fld">The field to be added</param>
  4541. public void AddField(FieldDef fld) {
  4542. defaultClass.AddField(fld);
  4543. }
  4544. /// <summary>
  4545. /// Get a field of this module, if it exists
  4546. /// </summary>
  4547. /// <param name="name">The name of the field</param>
  4548. /// <returns>FieldDef for "name", or null if one doesn't exist</returns>
  4549. public FieldDef GetField(string name) {
  4550. return defaultClass.GetField(name);
  4551. }
  4552. /// <summary>
  4553. /// Get all the fields of this module
  4554. /// </summary>
  4555. /// <returns>An array of all the fields of this module</returns>
  4556. public FieldDef[] GetFields() {
  4557. return defaultClass.GetFields();
  4558. }
  4559. /// <summary>
  4560. /// Make a ModuleRef for this Module.
  4561. /// </summary>
  4562. /// <returns>ModuleRef for this Module</returns>
  4563. public ModuleRef MakeRefOf(/*bool hasEntryPoint, byte[] hashValue*/) {
  4564. if (refOf == null) {
  4565. refOf = new ModuleRef(name/*,hasEntryPoint,hashValue*/);
  4566. refOf.defOf = this;
  4567. }/* else { // fix this
  4568. if (hasEntryPoint)
  4569. refOf.SetEntryPoint();
  4570. refOf.SetHash(hashValue);
  4571. }*/
  4572. return refOf;
  4573. }
  4574. /// <summary>
  4575. /// Set the name for this module
  4576. /// </summary>
  4577. /// <param name="newName">New module name</param>
  4578. public void SetName(string newName) {
  4579. name = newName;
  4580. //isDLL = name.EndsWith(".dll") || name.EndsWith(".DLL");
  4581. }
  4582. public void SetMVid(Guid guid) {
  4583. mvid = guid;
  4584. }
  4585. public Guid GetMVid() {
  4586. return mvid;
  4587. }
  4588. /*------------------------- internal functions --------------------------*/
  4589. internal bool isMSCorLib() { return ismscorlib; }
  4590. internal bool isDefaultClass(ClassDef aClass) { return aClass == defaultClass; }
  4591. private static string GetBaseName(string name) {
  4592. // more to this??
  4593. if (name.IndexOf("\\") != -1)
  4594. name = name.Substring(name.LastIndexOf("\\")+1);
  4595. return name;
  4596. }
  4597. internal void SetDefaultClass(ClassDef dClass) {
  4598. defaultClass = dClass;
  4599. }
  4600. internal sealed override void BuildTables(MetaDataOut md) {
  4601. md.AddToTable(MDTable.Module,this);
  4602. nameIx = md.AddToStringsHeap(name);
  4603. mvidIx = md.AddToGUIDHeap(mvid);
  4604. defaultClass.BuildTables(md);
  4605. for (int i=0; i < classes.Count; i++) {
  4606. ((Class)classes[i]).BuildMDTables(md);
  4607. }
  4608. for (int i=0; i < resources.Count; i++) {
  4609. ((ManifestResource)resources[i]).BuildMDTables(md);
  4610. }
  4611. }
  4612. internal static uint Size(MetaData md) {
  4613. return 2 + md.StringsIndexSize() + 3 * md.GUIDIndexSize();
  4614. }
  4615. internal sealed override void Write(PEWriter output) {
  4616. output.Write((short)0);
  4617. output.StringsIndex(nameIx);
  4618. output.GUIDIndex(mvidIx);
  4619. output.GUIDIndex(0);
  4620. output.GUIDIndex(0);
  4621. }
  4622. internal sealed override uint GetCodedIx(CIx code) {
  4623. switch (code) {
  4624. case (CIx.HasCustomAttr) : return 7;
  4625. case (CIx.ResolutionScope) : return 0;
  4626. }
  4627. return 0;
  4628. }
  4629. }
  4630. /**************************************************************************/
  4631. /// <summary>
  4632. /// A scope for descriptors which are referenced
  4633. /// </summary>
  4634. public abstract class ReferenceScope : ResolutionScope {
  4635. /// <summary>
  4636. /// A default class decriptor for globals
  4637. /// </summary>
  4638. protected ClassRef defaultClass;
  4639. /*-------------------- Constructors ---------------------------------*/
  4640. internal ReferenceScope(string name) : base(name) {
  4641. defaultClass = new ClassRef(this,"","");
  4642. defaultClass.MakeSpecial();
  4643. }
  4644. internal void ReadAsDef() {
  4645. readAsDef = true;
  4646. }
  4647. internal ClassRef GetDefaultClass() { return defaultClass; }
  4648. internal void SetDefaultClass(ClassRef dClass) {
  4649. defaultClass = dClass;
  4650. }
  4651. internal override void AddToClassList(Class aClass) {
  4652. ((ClassRef)aClass).SetScope(this);
  4653. classes.Add(aClass);
  4654. }
  4655. internal void ReplaceClass(Class aClass) {
  4656. bool found = false;
  4657. for (int i=0; (i < classes.Count) && !found; i++) {
  4658. if (((Class)classes[i]).Name() == aClass.Name()) {
  4659. found = true;
  4660. }
  4661. }
  4662. if (!found)
  4663. classes.Add(aClass);
  4664. }
  4665. internal bool isDefaultClass(ClassRef aClass) { return aClass == defaultClass; }
  4666. /// <summary>
  4667. /// Add a class to this Scope. If this class already exists, throw
  4668. /// an exception
  4669. /// </summary>
  4670. /// <param name="newClass">The class to be added</param>
  4671. public void AddClass(ClassRef newClass) {
  4672. ClassRef aClass = (ClassRef)GetClass(newClass.NameSpace(),newClass.Name(),true);
  4673. if (aClass != null)
  4674. throw new DescriptorException("Class " + newClass.NameString());
  4675. if (Diag.DiagOn) Console.WriteLine("Adding class " + newClass.Name() + " to ResolutionScope " + name);
  4676. classes.Add(newClass);
  4677. // Change Refs to Defs here
  4678. newClass.SetScope(this);
  4679. }
  4680. /// <summary>
  4681. /// Add a class to this Scope. If the class already exists,
  4682. /// throw an exception.
  4683. /// </summary>
  4684. /// <param name="nsName">name space name</param>
  4685. /// <param name="name">class name</param>
  4686. /// <returns>a descriptor for this class in another module</returns>
  4687. public virtual ClassRef AddClass(string nsName, string name) {
  4688. ClassRef aClass = GetClass(nsName,name);
  4689. if (aClass != null) {
  4690. if ((aClass is SystemClass) && (!((SystemClass)aClass).added))
  4691. ((SystemClass)aClass).added = true;
  4692. else
  4693. throw new DescriptorException("Class " + aClass.NameString());
  4694. } else {
  4695. aClass = new ClassRef(this,nsName,name);
  4696. classes.Add(aClass);
  4697. }
  4698. return aClass;
  4699. }
  4700. /// <summary>
  4701. /// Add a value class to this scope. If the class already exists,
  4702. /// throw an exception.
  4703. /// </summary>
  4704. /// <param name="nsName">name space name</param>
  4705. /// <param name="name">class name</param>
  4706. /// <returns></returns>
  4707. public virtual ClassRef AddValueClass(string nsName, string name) {
  4708. ClassRef aClass = AddClass(nsName,name);
  4709. aClass.MakeValueClass();
  4710. return aClass;
  4711. }
  4712. /// <summary>
  4713. /// Get a class of this scope, if it exists.
  4714. /// </summary>
  4715. /// <param name="name">The name of the class.</param>
  4716. /// <returns>ClassRef for "name".</returns>
  4717. public ClassRef GetClass(string name) {
  4718. return (ClassRef)GetClass(null,name,false);
  4719. }
  4720. /// <summary>
  4721. /// Get a class of this scope, if it exists.
  4722. /// </summary>
  4723. /// <param name="nsName">The namespace of the class.</param>
  4724. /// <param name="name">The name of the class.</param>
  4725. /// <returns>ClassRef for "nsName.name".</returns>
  4726. public ClassRef GetClass(string nsName, string name) {
  4727. return (ClassRef)GetClass(nsName,name,true);
  4728. }
  4729. /// <summary>
  4730. /// Get all the classes in this scope.
  4731. /// </summary>
  4732. /// <returns>An array of all the classes in this scope.</returns>
  4733. public ClassRef[] GetClasses() {
  4734. return (ClassRef[])classes.ToArray(typeof(ClassRef));
  4735. }
  4736. /// <summary>
  4737. /// Fetch a MethodRef descriptor for the method "retType name (pars)".
  4738. /// If one exists, it is returned, else one is created.
  4739. /// </summary>
  4740. /// <param name="name">method name</param>
  4741. /// <param name="retType">return type</param>
  4742. /// <param name="pars">method parameter types</param>
  4743. /// <returns>a descriptor for this method in anther module</returns>
  4744. public MethodRef AddMethod(string name, Type retType, Type[] pars) {
  4745. MethodRef meth = defaultClass.AddMethod(name,retType,pars);
  4746. return meth;
  4747. }
  4748. /// <summary>
  4749. /// Fetch a MethodRef descriptor for the method "retType name (pars, optPars)".
  4750. /// If one exists, it is returned, else one is created.
  4751. /// </summary>
  4752. /// <param name="name">method name</param>
  4753. /// <param name="retType">return type</param>
  4754. /// <param name="pars">parameter types</param>
  4755. /// <param name="optPars">optional param types for this vararg method</param>
  4756. /// <returns>a descriptor for this method</returns>
  4757. public MethodRef AddVarArgMethod(string name, Type retType, Type[] pars, Type[] optPars) {
  4758. MethodRef meth = defaultClass.AddVarArgMethod(name,retType,pars,optPars);
  4759. return meth;
  4760. }
  4761. /// <summary>
  4762. /// Add a method to this scope.
  4763. /// </summary>
  4764. /// <param name="meth">The method to be added.</param>
  4765. public void AddMethod(MethodRef meth) {
  4766. defaultClass.AddMethod(meth);
  4767. }
  4768. // internal void CheckAddMethod(MethodRef meth) {
  4769. // defaultClass.CheckAddMethod(meth);
  4770. // }
  4771. /*
  4772. internal void CheckAddMethods(ArrayList meths) {
  4773. for (int i=0; i < meths.Count; i++) {
  4774. Method meth = (Method)meths[i];
  4775. defaultClass.CheckAddMethod(meth);
  4776. meth.SetParent(this);
  4777. }
  4778. }
  4779. internal MethodRef GetMethod(string name, uint sigIx) {
  4780. return defaultClass.GetMethod(name,sigIx);
  4781. }
  4782. */
  4783. /// <summary>
  4784. /// Get a method of this scope, if it exists.
  4785. /// </summary>
  4786. /// <param name="name">The name of the method.</param>
  4787. /// <returns>MethodRef for "name", or null if none exists.</returns>
  4788. public MethodRef GetMethod(string name) {
  4789. return defaultClass.GetMethod(name);
  4790. }
  4791. /// <summary>
  4792. /// Get all the methods with a specified name in this scope.
  4793. /// </summary>
  4794. /// <param name="name">The name of the method(s).</param>
  4795. /// <returns>An array of all the methods called "name".</returns>
  4796. public MethodRef[] GetMethods(string name) {
  4797. return defaultClass.GetMethods(name);
  4798. }
  4799. /// <summary>
  4800. /// Get a method of this scope, if it exists.
  4801. /// </summary>
  4802. /// <param name="name">The name of the method</param>
  4803. /// <param name="parTypes">The signature of the method.</param>
  4804. /// <returns>MethodRef for name(parTypes).</returns>
  4805. public MethodRef GetMethod(string name, Type[] parTypes) {
  4806. return defaultClass.GetMethod(name,parTypes);
  4807. }
  4808. /// <summary>
  4809. /// Get a vararg method of this scope, if it exists.
  4810. /// </summary>
  4811. /// <param name="name">The name of the method.</param>
  4812. /// <param name="parTypes">The signature of the method.</param>
  4813. /// <param name="optPars">The optional parameters of the vararg method.</param>
  4814. /// <returns>MethodRef for name(parTypes,optPars).</returns>
  4815. public MethodRef GetMethod(string name, Type[] parTypes, Type[] optPars) {
  4816. return defaultClass.GetMethod(name,parTypes,optPars);
  4817. }
  4818. /// <summary>
  4819. /// Get all the methods in this module
  4820. /// </summary>
  4821. /// <returns>Array of the methods of this module</returns>
  4822. public MethodRef[] GetMethods() {
  4823. return defaultClass.GetMethods();
  4824. }
  4825. /// <summary>
  4826. /// Delete a method from this scope.
  4827. /// </summary>
  4828. /// <param name="meth">The method to be deleted.</param>
  4829. public void RemoveMethod(MethodRef meth) {
  4830. defaultClass.RemoveMethod(meth);
  4831. }
  4832. /// <summary>
  4833. /// Delete a method from this scope. If there are multiple methods with
  4834. /// the same name, the first on the list will be deleted.
  4835. /// </summary>
  4836. /// <param name="name">The name of the method to delete.</param>
  4837. public void RemoveMethod(string name) {
  4838. defaultClass.RemoveMethod(name);
  4839. }
  4840. /// <summary>
  4841. /// Delete a method from this scope.
  4842. /// </summary>
  4843. /// <param name="name">The name of the method to be deleted.</param>
  4844. /// <param name="parTypes">The signature of the method to be deleted.</param>
  4845. public void RemoveMethod(string name, Type[] parTypes) {
  4846. defaultClass.RemoveMethod(name,parTypes);
  4847. }
  4848. /// <summary>
  4849. /// Delete a (vararg) method from this scope.
  4850. /// </summary>
  4851. /// <param name="name">The name of the method to be deleted.</param>
  4852. /// <param name="parTypes">The signature of the method to be deleted.</param>
  4853. /// <param name="optTypes">The optional parameters of the vararg method.</param>
  4854. public void RemoveMethod(string name, Type[] parTypes, Type[] optTypes) {
  4855. defaultClass.RemoveMethod(name,parTypes,optTypes);
  4856. }
  4857. /// <summary>
  4858. /// Delete a method from this scope.
  4859. /// </summary>
  4860. /// <param name="index">The index of the method to be deleted. Index
  4861. /// into array returned by GetMethods().</param>
  4862. public void RemoveMethod(int index) {
  4863. defaultClass.RemoveMethod(index);
  4864. }
  4865. /// <summary>
  4866. /// Add a field to this scope.
  4867. /// </summary>
  4868. /// <param name="name">field name</param>
  4869. /// <param name="fType">field type</param>
  4870. /// <returns>a descriptor for the field "name" in this scope</returns>
  4871. public FieldRef AddField(string name, Type fType) {
  4872. FieldRef field = defaultClass.AddField(name,fType);
  4873. return field;
  4874. }
  4875. /// <summary>
  4876. /// Add a field to this scope.
  4877. /// </summary>
  4878. /// <param name="fld">The field to be added</param>
  4879. public void AddField(FieldRef fld) {
  4880. defaultClass.AddField(fld);
  4881. }
  4882. /// <summary>
  4883. /// Add a number of fields to this scope.
  4884. /// </summary>
  4885. /// <param name="flds">The fields to be added.</param>
  4886. internal void AddFields(ArrayList flds) {
  4887. for (int i=0; i < flds.Count; i++) {
  4888. FieldRef fld = (FieldRef)flds[i];
  4889. defaultClass.AddField(fld);
  4890. }
  4891. }
  4892. /// <summary>
  4893. /// Fetch the FieldRef descriptor for the field "name" in this module,
  4894. /// if one exists
  4895. /// </summary>
  4896. /// <param name="name">field name</param>
  4897. /// <returns>FieldRef descriptor for "name" or null</returns>
  4898. public FieldRef GetField(string name) {
  4899. return defaultClass.GetField(name);
  4900. }
  4901. /// <summary>
  4902. /// Get all the fields of this module
  4903. /// </summary>
  4904. /// <returns>Array of FieldRefs for this module</returns>
  4905. public FieldRef[] GetFields() {
  4906. return defaultClass.GetFields();
  4907. }
  4908. internal void AddToMethodList(MethodRef meth) {
  4909. defaultClass.AddToMethodList(meth);
  4910. }
  4911. internal void AddToFieldList(FieldRef fld) {
  4912. defaultClass.AddToFieldList(fld);
  4913. }
  4914. internal MethodRef GetMethod(MethSig mSig) {
  4915. return (MethodRef)defaultClass.GetMethod(mSig);
  4916. }
  4917. }
  4918. /**************************************************************************/
  4919. /// <summary>
  4920. /// A reference to an external assembly (.assembly extern)
  4921. /// </summary>
  4922. public class AssemblyRef : ReferenceScope {
  4923. private ushort major, minor, build, revision;
  4924. uint flags, keyIx, hashIx, cultIx;
  4925. bool hasVersion = false, isKeyToken = false;
  4926. byte[] keyBytes, hashBytes;
  4927. string culture;
  4928. /*-------------------- Constructors ---------------------------------*/
  4929. internal AssemblyRef(string name) : base(name) {
  4930. tabIx = MDTable.AssemblyRef;
  4931. }
  4932. internal AssemblyRef(string name, ushort maj, ushort min, ushort bldNo, ushort rev,
  4933. uint flags, byte[] kBytes, string cult, byte[] hBytes) : base(name) {
  4934. tabIx = MDTable.AssemblyRef;
  4935. major = maj;
  4936. minor = min;
  4937. build = bldNo;
  4938. revision = rev;
  4939. this.flags = flags; // check
  4940. keyBytes = kBytes; // need to set is token or full key
  4941. if (keyBytes != null)
  4942. isKeyToken = keyBytes.Length <= 8;
  4943. culture = cult;
  4944. hashBytes = hBytes;
  4945. tabIx = MDTable.AssemblyRef;
  4946. }
  4947. internal static AssemblyRef Read(PEReader buff) {
  4948. ushort majVer = buff.ReadUInt16();
  4949. ushort minVer = buff.ReadUInt16();
  4950. ushort bldNo = buff.ReadUInt16();
  4951. ushort revNo = buff.ReadUInt16();
  4952. uint flags = buff.ReadUInt32();
  4953. byte[] pKey = buff.GetBlob();
  4954. string name = buff.GetString();
  4955. string cult = buff.GetString();
  4956. byte[] hBytes = buff.GetBlob();
  4957. AssemblyRef assemRef;
  4958. if (name.ToLower() == "mscorlib") {
  4959. assemRef = MSCorLib.mscorlib;
  4960. assemRef.AddVersionInfo(majVer,minVer,bldNo,revNo);
  4961. assemRef.AddHash(hBytes);
  4962. if (pKey.Length > 8) assemRef.AddKey(pKey);
  4963. else assemRef.AddKeyToken(pKey);
  4964. assemRef.AddCulture(cult);
  4965. assemRef.SetFlags(flags);
  4966. } else {
  4967. assemRef = new AssemblyRef(name,majVer,minVer,bldNo,revNo,flags,pKey,cult,hBytes);
  4968. }
  4969. return assemRef;
  4970. }
  4971. internal static void Read(PEReader buff, TableRow[] table) {
  4972. for (int i=0; i < table.Length; i++)
  4973. table[i] = Read(buff);
  4974. }
  4975. /*------------------------- public set and get methods --------------------------*/
  4976. /// <summary>
  4977. /// Add version information about this external assembly
  4978. /// </summary>
  4979. /// <param name="majVer">Major Version</param>
  4980. /// <param name="minVer">Minor Version</param>
  4981. /// <param name="bldNo">Build Number</param>
  4982. /// <param name="revNo">Revision Number</param>
  4983. public void AddVersionInfo(int majVer, int minVer, int bldNo, int revNo) {
  4984. major = (ushort)majVer;
  4985. minor = (ushort)minVer;
  4986. build = (ushort)bldNo;
  4987. revision = (ushort)revNo;
  4988. hasVersion = true;
  4989. }
  4990. /// <summary>
  4991. /// Get the major version for this external assembly
  4992. /// </summary>
  4993. /// <returns>major version number</returns>
  4994. public int MajorVersion() { return major; }
  4995. /// <summary>
  4996. /// Get the minor version for this external assembly
  4997. /// </summary>
  4998. /// <returns>minor version number</returns>
  4999. public int MinorVersion() { return minor; }
  5000. /// <summary>
  5001. /// Get the build number for this external assembly
  5002. /// </summary>
  5003. /// <returns>build number</returns>
  5004. public int BuildNumber() { return build; }
  5005. /// <summary>
  5006. /// Get the revision number for this external assembly
  5007. /// </summary>
  5008. /// <returns>revision number</returns>
  5009. public int RevisionNumber() { return revision; }
  5010. /// <summary>
  5011. /// Check if this external assembly has any version information
  5012. /// </summary>
  5013. public bool HasVersionInfo() { return hasVersion; }
  5014. /// <summary>
  5015. /// Add the hash value for this external assembly
  5016. /// </summary>
  5017. /// <param name="hash">bytes of the hash value</param>
  5018. public void AddHash(byte[] hash) { hashBytes = hash; }
  5019. /// <summary>
  5020. /// Get the hash value for this external assembly
  5021. /// </summary>
  5022. /// <returns></returns>
  5023. public byte[] GetHash() { return hashBytes; }
  5024. /// <summary>
  5025. /// Set the culture for this external assembly
  5026. /// </summary>
  5027. /// <param name="cult">the culture string</param>
  5028. public void AddCulture(string cult) { culture = cult; }
  5029. public string GetCulture() { return culture; }
  5030. /// <summary>
  5031. /// Add the full public key for this external assembly
  5032. /// </summary>
  5033. /// <param name="key">bytes of the public key</param>
  5034. public void AddKey(byte[] key) {
  5035. flags |= 0x0001; // full public key
  5036. keyBytes = key;
  5037. }
  5038. /// <summary>
  5039. /// Add the public key token (low 8 bytes of the public key)
  5040. /// </summary>
  5041. /// <param name="key">low 8 bytes of public key</param>
  5042. public void AddKeyToken(byte[] key) {
  5043. keyBytes = key;
  5044. isKeyToken = true;
  5045. }
  5046. /// <summary>
  5047. /// Get the public key token
  5048. /// </summary>
  5049. /// <returns>bytes of public key</returns>
  5050. public byte[] GetKey() { return keyBytes; }
  5051. /// <summary>
  5052. /// Make an AssemblyRef for "name".
  5053. /// </summary>
  5054. /// <param name="name">The name of the assembly</param>
  5055. /// <returns>AssemblyRef for "name".</returns>
  5056. public static AssemblyRef MakeAssemblyRef(string name) {
  5057. AssemblyRef assemRef = new AssemblyRef(name);
  5058. return assemRef;
  5059. }
  5060. public static AssemblyRef MakeAssemblyRef(string name, int majVer, int minVer, int bldNo, int revNo, byte[] key)
  5061. {
  5062. AssemblyRef assemRef = new AssemblyRef(name);
  5063. assemRef.AddVersionInfo(majVer, minVer, bldNo, revNo);
  5064. if (key.Length > 8)
  5065. assemRef.AddKey(key);
  5066. else
  5067. assemRef.AddKeyToken(key);
  5068. return assemRef;
  5069. }
  5070. /*------------------------ internal functions ----------------------------*/
  5071. internal void SetFlags(uint flags) {
  5072. this.flags = flags;
  5073. }
  5074. internal string AssemblyString() {
  5075. string result = name;
  5076. if (hasVersion)
  5077. result = result + ", Version=" + major + "." + minor + "." +
  5078. build + "." + revision;
  5079. if (keyBytes != null) {
  5080. string tokenStr = "=";
  5081. if (isKeyToken) tokenStr = "Token=";
  5082. result = result + ", PublicKey" + tokenStr;
  5083. for (int i=0; i < keyBytes.Length; i++) {
  5084. result = result + Hex.Byte(keyBytes[i]);
  5085. }
  5086. }
  5087. if (culture != null)
  5088. result = result + ", Culture=" + culture;
  5089. return result;
  5090. }
  5091. internal static uint Size(MetaData md) {
  5092. return 12 + 2 * md.StringsIndexSize() + 2 * md.BlobIndexSize();
  5093. }
  5094. internal sealed override void BuildTables(MetaDataOut md) {
  5095. md.AddToTable(MDTable.AssemblyRef,this);
  5096. keyIx = md.AddToBlobHeap(keyBytes);
  5097. nameIx = md.AddToStringsHeap(name);
  5098. cultIx = md.AddToStringsHeap(culture);
  5099. hashIx = md.AddToBlobHeap(hashBytes);
  5100. }
  5101. internal sealed override void Write(PEWriter output) {
  5102. output.Write(major);
  5103. output.Write(minor);
  5104. output.Write(build);
  5105. output.Write(revision);
  5106. output.Write(flags);
  5107. output.BlobIndex(keyIx);
  5108. output.StringsIndex(nameIx);
  5109. output.StringsIndex(cultIx);
  5110. output.BlobIndex(hashIx);
  5111. }
  5112. internal override void Write(CILWriter output) {
  5113. output.WriteLine(".assembly extern " + name + " { }");
  5114. }
  5115. internal sealed override uint GetCodedIx(CIx code) {
  5116. switch (code) {
  5117. case (CIx.ResolutionScope) : return 2;
  5118. case (CIx.HasCustomAttr) : return 15;
  5119. case (CIx.Implementation) : return 1;
  5120. }
  5121. return 0;
  5122. }
  5123. }
  5124. /**************************************************************************/
  5125. /// <summary>
  5126. /// The assembly for mscorlib.
  5127. /// </summary>
  5128. public sealed class MSCorLib : AssemblyRef {
  5129. internal static MSCorLib mscorlib = new MSCorLib();
  5130. internal SystemClass ObjectClass;
  5131. private ClassRef valueType;
  5132. internal MSCorLib() : base("mscorlib") {
  5133. classes.Add(new SystemClass(this,PrimitiveType.Void));
  5134. classes.Add(new SystemClass(this,PrimitiveType.Boolean));
  5135. classes.Add(new SystemClass(this,PrimitiveType.Char));
  5136. classes.Add(new SystemClass(this,PrimitiveType.Int8));
  5137. classes.Add(new SystemClass(this,PrimitiveType.UInt8));
  5138. classes.Add(new SystemClass(this,PrimitiveType.Int16));
  5139. classes.Add(new SystemClass(this,PrimitiveType.UInt16));
  5140. classes.Add(new SystemClass(this,PrimitiveType.Int32));
  5141. classes.Add(new SystemClass(this,PrimitiveType.UInt32));
  5142. classes.Add(new SystemClass(this,PrimitiveType.Int64));
  5143. classes.Add(new SystemClass(this,PrimitiveType.UInt64));
  5144. classes.Add(new SystemClass(this,PrimitiveType.Float32));
  5145. classes.Add(new SystemClass(this,PrimitiveType.Float64));
  5146. classes.Add(new SystemClass(this,PrimitiveType.IntPtr));
  5147. classes.Add(new SystemClass(this,PrimitiveType.UIntPtr));
  5148. classes.Add(new SystemClass(this,PrimitiveType.String));
  5149. classes.Add(new SystemClass(this,PrimitiveType.TypedRef));
  5150. ObjectClass = new SystemClass(this,PrimitiveType.Object);
  5151. classes.Add(ObjectClass);
  5152. valueType = new ClassRef(this,"System","ValueType");
  5153. valueType.MakeValueClass();
  5154. classes.Add(valueType);
  5155. }
  5156. internal ClassRef ValueType() {
  5157. return valueType;
  5158. }
  5159. }
  5160. /**************************************************************************/
  5161. /// <summary>
  5162. /// Descriptor for a module in an assembly
  5163. /// </summary>
  5164. public class ModuleRef : ReferenceScope {
  5165. ArrayList exportedClasses = new ArrayList();
  5166. internal ModuleFile modFile;
  5167. internal Module defOf;
  5168. internal bool ismscorlib = false;
  5169. /*-------------------- Constructors ---------------------------------*/
  5170. internal ModuleRef(string name, bool entryPoint, byte[] hashValue) : base(name) {
  5171. modFile = new ModuleFile(name,hashValue,entryPoint);
  5172. ismscorlib = name.ToLower() == "mscorlib.dll";
  5173. tabIx = MDTable.ModuleRef;
  5174. }
  5175. internal ModuleRef(string name) : base(name) {
  5176. ismscorlib = name.ToLower() == "mscorlib.dll";
  5177. tabIx = MDTable.ModuleRef;
  5178. }
  5179. internal ModuleRef(ModuleFile file) : base(file.Name()) {
  5180. modFile = file;
  5181. tabIx = MDTable.ModuleRef;
  5182. }
  5183. internal static void Read(PEReader buff, TableRow[] mods, bool resolve) {
  5184. for (int i=0; i < mods.Length; i++) {
  5185. string name = buff.GetString();
  5186. ModuleRef mRef = new ModuleRef(name);
  5187. if (resolve) mRef.modFile = buff.GetFileDesc(name);
  5188. mods[i] = mRef;
  5189. }
  5190. }
  5191. internal sealed override void Resolve(PEReader buff) {
  5192. modFile = buff.GetFileDesc(name);
  5193. if (modFile != null)
  5194. modFile.fileModule = this;
  5195. }
  5196. /*------------------------- public set and get methods --------------------------*/
  5197. /// <summary>
  5198. /// Add a class which is declared public in this external module of
  5199. /// THIS assembly. This class will be exported from this assembly.
  5200. /// The ilasm syntax for this is .extern class
  5201. /// </summary>
  5202. /// <param name="attrSet">attributes of the class to be exported</param>
  5203. /// <param name="nsName">name space name</param>
  5204. /// <param name="name">external class name</param>
  5205. /// <param name="declFile">the file where the class is declared</param>
  5206. /// <param name="isValueClass">is this class a value type?</param>
  5207. /// <returns>a descriptor for this external class</returns>
  5208. public ClassRef AddExternClass(TypeAttr attrSet, string nsName,
  5209. string name, bool isValueClass, PEFile pefile) {
  5210. ClassRef cRef = new ClassRef(this,nsName,name);
  5211. if (isValueClass) cRef.MakeValueClass();
  5212. ExternClass eClass = new ExternClass(attrSet,nsName,name,modFile);
  5213. exportedClasses.Add(eClass);
  5214. cRef.SetExternClass(eClass);
  5215. classes.Add(cRef);
  5216. return cRef;
  5217. }
  5218. public static ModuleRef MakeModuleRef(string name, bool entryPoint, byte[] hashValue) {
  5219. ModuleRef mRef = new ModuleRef(name,entryPoint,hashValue);
  5220. return mRef;
  5221. }
  5222. public void SetEntryPoint() {
  5223. modFile.SetEntryPoint();
  5224. }
  5225. public void SetHash(byte[] hashVal) {
  5226. modFile.SetHash(hashVal);
  5227. }
  5228. /*------------------------- internal functions --------------------------*/
  5229. /* internal void AddMember(Member memb) {
  5230. if (memb is Method) {
  5231. Method existing = GetMethod(memb.Name(),((Method)memb).GetParTypes());
  5232. if (existing == null)
  5233. methods.Add(memb);
  5234. } else {
  5235. Field existing = GetField(memb.Name());
  5236. if (existing == null)
  5237. fields.Add(memb);
  5238. }
  5239. }
  5240. */
  5241. internal void AddToExportedClassList(ClassRef exClass) {
  5242. if (exportedClasses.Contains(exClass)) return;
  5243. exportedClasses.Add(exClass);
  5244. }
  5245. internal void AddExternClass(ExternClass eClass) {
  5246. exportedClasses.Add(eClass);
  5247. }
  5248. internal static uint Size(MetaData md) {
  5249. return md.StringsIndexSize();
  5250. }
  5251. internal sealed override void BuildTables(MetaDataOut md) {
  5252. md.AddToTable(MDTable.ModuleRef,this);
  5253. nameIx = md.AddToStringsHeap(name);
  5254. if (modFile != null) modFile.BuildMDTables(md);
  5255. for (int i=0; i < exportedClasses.Count; i++)
  5256. ((ExternClass)exportedClasses[i]).BuildMDTables(md);
  5257. }
  5258. internal sealed override void Write(PEWriter output) {
  5259. output.StringsIndex(nameIx);
  5260. }
  5261. internal sealed override uint GetCodedIx(CIx code) {
  5262. switch (code) {
  5263. case (CIx.HasCustomAttr) : return 12;
  5264. case (CIx.MemberRefParent) : return 2;
  5265. case (CIx.ResolutionScope) : return 1;
  5266. }
  5267. return 0;
  5268. }
  5269. }
  5270. /**************************************************************************/
  5271. /// <summary>
  5272. /// Base descriptor for signature blobs
  5273. /// </summary>
  5274. public class Signature : MetaDataElement {
  5275. protected uint sigIx;
  5276. protected byte[] sigBytes;
  5277. /*-------------------- Constructors ---------------------------------*/
  5278. internal Signature() {
  5279. tabIx = MDTable.StandAloneSig;
  5280. }
  5281. private Signature(uint sIx) {
  5282. sigIx = sIx;
  5283. }
  5284. internal static void Read(PEReader buff, TableRow[] sigs) {
  5285. for (int i=0; i < sigs.Length; i++) {
  5286. uint sigIx = buff.GetBlobIx();
  5287. uint tag = buff.FirstBlobByte(sigIx);
  5288. if (tag == LocalSig.LocalSigByte)
  5289. sigs[i] = new LocalSig(sigIx);
  5290. else if (tag == Field.FieldTag)
  5291. sigs[i] = new Signature(sigIx);
  5292. else
  5293. sigs[i] = new CalliSig(sigIx);
  5294. sigs[i].Row = (uint)i+1;
  5295. }
  5296. }
  5297. internal override void Resolve(PEReader buff) {
  5298. Type sigType = buff.GetFieldType(sigIx);
  5299. buff.ReplaceSig(this,sigType);
  5300. }
  5301. internal static uint Size(MetaData md) {
  5302. return md.BlobIndexSize();
  5303. }
  5304. internal sealed override void Write(PEWriter output) {
  5305. output.BlobIndex(sigIx);
  5306. }
  5307. internal sealed override uint GetCodedIx(CIx code) { return (uint)tabIx; }
  5308. }
  5309. /**************************************************************************/
  5310. /// <summary>
  5311. /// Signature for calli instruction
  5312. /// </summary>
  5313. public class CalliSig : Signature {
  5314. CallConv callConv;
  5315. Type retType;
  5316. Type[] parTypes, optParTypes;
  5317. uint numPars = 0, numOptPars = 0;
  5318. /*-------------------- Constructors ---------------------------------*/
  5319. /// <summary>
  5320. /// Create a signature for a calli instruction
  5321. /// </summary>
  5322. /// <param name="cconv">calling conventions</param>
  5323. /// <param name="retType">return type</param>
  5324. /// <param name="pars">parameter types</param>
  5325. public CalliSig(CallConv cconv, Type retType, Type[] pars) {
  5326. callConv = cconv;
  5327. this.retType = retType;
  5328. parTypes = pars;
  5329. if (pars != null) numPars = (uint)pars.Length;
  5330. }
  5331. internal CalliSig(uint sigIx) {
  5332. this.sigIx = sigIx;
  5333. }
  5334. /// <summary>
  5335. /// The return type of the method being called.
  5336. /// </summary>
  5337. public Type ReturnType { get { return retType; } }
  5338. /// <summary>
  5339. /// The number of parameters on the method being called.
  5340. /// </summary>
  5341. public uint NumPars { get { return numPars; } }
  5342. /// <summary>
  5343. /// The number of optional parameters on the method being called.
  5344. /// </summary>
  5345. public uint NumOptPars { get { return numOptPars; } }
  5346. /// <summary>
  5347. /// Check to see if the method signature has a particular calling convention.
  5348. /// </summary>
  5349. /// <param name="callCon">The convention to check to see if the method has.</param>
  5350. /// <returns>Ture if the calling convention exists on the method.</returns>
  5351. internal bool HasCallConv(CallConv callCon) {
  5352. return ((callConv & callCon) == callCon);
  5353. }
  5354. internal sealed override void Resolve(PEReader buff) {
  5355. MethSig mSig = buff.ReadMethSig(null,sigIx);
  5356. callConv = mSig.callConv;
  5357. retType = mSig.retType;
  5358. parTypes = mSig.parTypes;
  5359. if (parTypes != null) numPars = (uint)parTypes.Length;
  5360. optParTypes = mSig.optParTypes;
  5361. if (optParTypes != null) numOptPars = (uint)optParTypes.Length;
  5362. }
  5363. /// <summary>
  5364. /// Add the optional parameters to a vararg method
  5365. /// This method sets the vararg calling convention
  5366. /// </summary>
  5367. /// <param name="optPars">the optional pars for the vararg call</param>
  5368. public void AddVarArgs(Type[] optPars) {
  5369. optParTypes = optPars;
  5370. if (optPars != null) numOptPars = (uint)optPars.Length;
  5371. callConv |= CallConv.Vararg;
  5372. }
  5373. /// <summary>
  5374. /// Add extra calling conventions to this callsite signature
  5375. /// </summary>
  5376. /// <param name="cconv"></param>
  5377. public void AddCallingConv(CallConv cconv) {
  5378. callConv |= cconv;
  5379. }
  5380. internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) {
  5381. for (int i=0; i < oldTypes.Length; i++) {
  5382. if (retType == oldTypes[i]) retType = newType;
  5383. for (int j=0; j < numPars; j++) {
  5384. if (parTypes[j] == oldTypes[i])
  5385. parTypes[j] = newType;
  5386. }
  5387. for (int j=0; j < numOptPars; j++) {
  5388. if (optParTypes[j] == oldTypes[i])
  5389. optParTypes[j] = newType;
  5390. }
  5391. }
  5392. }
  5393. internal sealed override void BuildTables(MetaDataOut md) {
  5394. md.AddToTable(MDTable.StandAloneSig,this);
  5395. for (int i=0; i < numPars; i++) {
  5396. parTypes[i].BuildMDTables(md);
  5397. }
  5398. if (numOptPars > 0) {
  5399. for (int i=0; i < numOptPars; i++) {
  5400. optParTypes[i].BuildMDTables(md);
  5401. }
  5402. }
  5403. }
  5404. internal sealed override void BuildSignatures(MetaDataOut md) {
  5405. MemoryStream sig = new MemoryStream();
  5406. sig.WriteByte((byte)callConv);
  5407. MetaDataOut.CompressNum(numPars+numOptPars,sig);
  5408. retType.TypeSig(sig);
  5409. for (int i=0; i < numPars; i++) {
  5410. parTypes[i].TypeSig(sig);
  5411. }
  5412. if (numOptPars > 0) {
  5413. sig.WriteByte((byte)ElementType.Sentinel);
  5414. for (int i=0; i < numOptPars; i++) {
  5415. optParTypes[i].TypeSig(sig);
  5416. }
  5417. }
  5418. sigIx = md.AddToBlobHeap(sig.ToArray());
  5419. done = false;
  5420. }
  5421. }
  5422. /**************************************************************************/
  5423. /// <summary>
  5424. /// Descriptor for the locals for a method
  5425. /// </summary>
  5426. public class LocalSig : Signature {
  5427. internal static readonly byte LocalSigByte = 0x7;
  5428. Local[] locals;
  5429. bool resolved = true;
  5430. /*-------------------- Constructors ---------------------------------*/
  5431. public LocalSig(Local[] locals) {
  5432. this.locals = locals;
  5433. }
  5434. internal LocalSig(uint sigIx) {
  5435. resolved = false;
  5436. this.sigIx = sigIx;
  5437. }
  5438. internal override void Resolve(PEReader buff) {
  5439. }
  5440. internal void Resolve(PEReader buff, MethodDef meth) {
  5441. if (resolved) return;
  5442. buff.currentMethodScope = meth;
  5443. buff.currentClassScope = (Class)meth.GetParent();
  5444. locals = buff.ReadLocalSig(sigIx);
  5445. buff.currentMethodScope = null;
  5446. buff.currentClassScope = null;
  5447. }
  5448. internal Local[] GetLocals() {
  5449. return locals;
  5450. }
  5451. internal sealed override void BuildTables(MetaDataOut md) {
  5452. md.AddToTable(tabIx,this);
  5453. for (int i=0; i < locals.Length; i++) {
  5454. locals[i].BuildTables(md);
  5455. }
  5456. }
  5457. internal byte[] SigBytes() {
  5458. MemoryStream sig = new MemoryStream();
  5459. sig.WriteByte(LocalSigByte);
  5460. MetaDataOut.CompressNum((uint)locals.Length,sig);
  5461. for (int i=0; i < locals.Length; i++) {
  5462. ((Local)locals[i]).TypeSig(sig);
  5463. }
  5464. return sig.ToArray();
  5465. }
  5466. internal sealed override void BuildSignatures(MetaDataOut md) {
  5467. sigIx = md.AddToBlobHeap(SigBytes());
  5468. done = false;
  5469. }
  5470. }
  5471. /// <summary>
  5472. /// Stores the signature for the debug info for a local variable.
  5473. /// </summary>
  5474. public class DebugLocalSig : Signature {
  5475. internal static readonly byte LocalSigByte = 0x6;
  5476. bool resolved = true;
  5477. byte[] loc;
  5478. /*-------------------- Constructors ---------------------------------*/
  5479. internal DebugLocalSig(byte[] loc) {
  5480. this.loc = loc;
  5481. }
  5482. internal DebugLocalSig(uint sigIx) {
  5483. resolved = false;
  5484. this.sigIx = sigIx;
  5485. }
  5486. internal override void Resolve(PEReader buff) {
  5487. }
  5488. internal void Resolve(PEReader buff, MethodDef meth) {
  5489. if (resolved) return;
  5490. }
  5491. internal sealed override void BuildTables(MetaDataOut md) {
  5492. md.AddToTable(tabIx, this);
  5493. }
  5494. internal byte[] SigBytes() {
  5495. byte[] b = new byte[loc.Length + 1];
  5496. b[0] = LocalSigByte;
  5497. System.Array.Copy(loc, 0, b, 1, loc.Length);
  5498. return b;
  5499. }
  5500. internal sealed override void BuildSignatures(MetaDataOut md) {
  5501. sigIx = md.AddToBlobHeap(SigBytes());
  5502. done = false;
  5503. }
  5504. }
  5505. /**************************************************************************/
  5506. /// <summary>
  5507. /// Base class for all IL types
  5508. /// </summary>
  5509. public abstract class Type : MetaDataElement {
  5510. protected byte typeIndex;
  5511. /*-------------------- Constructors ---------------------------------*/
  5512. internal Type(byte tyIx) { typeIndex = tyIx; }
  5513. internal byte GetTypeIndex() { return typeIndex; }
  5514. internal virtual bool SameType(Type tstType) {
  5515. return this == tstType;
  5516. }
  5517. internal virtual void TypeSig(MemoryStream str) {
  5518. throw new TypeSignatureException(this.GetType().AssemblyQualifiedName +
  5519. " doesn't have a type signature!!");
  5520. }
  5521. public virtual string TypeName() {
  5522. return "NoTypeName";
  5523. }
  5524. internal virtual void WriteType(CILWriter output) {
  5525. throw new NotYetImplementedException("Writing types for CIL");
  5526. }
  5527. internal virtual void WriteName(CILWriter output) {
  5528. WriteType(output);
  5529. }
  5530. internal virtual Type AddTypeSpec(MetaDataOut md) {
  5531. if (!isDef()) BuildMDTables(md);
  5532. return this;
  5533. }
  5534. }
  5535. /**************************************************************************/
  5536. /*
  5537. internal class IndexedType : Type {
  5538. uint ix;
  5539. CIx codedIx;
  5540. bool isCoded = false;
  5541. internal IndexedType(PEReader buff, MDTable tIx, uint elIx) {
  5542. buffer = buff;
  5543. tabIx = tIx;
  5544. elIx = ix;
  5545. }
  5546. internal IndexedType(PEReader buff, CIx cIx, uint elIx) {
  5547. buffer = buff;
  5548. codedIx = cIx;
  5549. ix = elIx;
  5550. isCoded = true;
  5551. }
  5552. internal Type Resolve() {
  5553. if (isCoded)
  5554. return buffer.ReadCodedElement(cIx,ix);
  5555. return buffer.ReadElement(tabIx,ix);
  5556. }
  5557. }
  5558. */
  5559. /**************************************************************************/
  5560. /// <summary>
  5561. /// The base descriptor for a class
  5562. /// </summary>
  5563. public abstract class Class : Type {
  5564. //protected int row = 0;
  5565. protected string name, nameSpace;
  5566. protected uint nameIx, nameSpaceIx;
  5567. protected ArrayList nestedClasses = new ArrayList();
  5568. protected bool special = false;
  5569. protected ArrayList fields = new ArrayList();
  5570. protected ArrayList methods = new ArrayList();
  5571. internal uint fieldIx = 0, methodIx = 0, fieldEndIx = 0, methodEndIx = 0;
  5572. protected string[] fieldNames, methodNames;
  5573. protected ArrayList genericParams = new ArrayList();
  5574. /*-------------------- Constructors ---------------------------------*/
  5575. internal Class() : base((byte)ElementType.Class) { }
  5576. /*------------------------- public set and get methods --------------------------*/
  5577. public virtual void MakeValueClass() {
  5578. typeIndex = (byte)ElementType.ValueType;
  5579. }
  5580. /// <summary>
  5581. /// Get the name of this class
  5582. /// </summary>
  5583. /// <returns>class name</returns>
  5584. public string Name() { return name; }
  5585. /// <summary>
  5586. /// Get the namespace that includes this class
  5587. /// </summary>
  5588. /// <returns>namespace name</returns>
  5589. public string NameSpace() { return nameSpace; }
  5590. /// <summary>
  5591. /// Get the string representation of the qualified name
  5592. /// of this class
  5593. /// </summary>
  5594. /// <returns>class qualified name</returns>
  5595. public override string TypeName() {
  5596. if ((nameSpace == null) || (nameSpace == "")) return name;
  5597. return nameSpace + "." + name;
  5598. }
  5599. /// <summary>
  5600. /// Get the descriptor for the method "name" of this class
  5601. /// </summary>
  5602. /// <param name="name">The name of the method to be retrieved</param>
  5603. /// <returns>The method descriptor for "name"</returns>
  5604. public Method GetMethodDesc(string name) {
  5605. for (int i=0; i < methods.Count; i++) {
  5606. if (((Method)methods[i]).HasName(name))
  5607. return (Method)methods[i];
  5608. }
  5609. return null;
  5610. }
  5611. /// <summary>
  5612. /// Get the descriptor for the method called "name" with the signature "parTypes"
  5613. /// </summary>
  5614. /// <param name="name">The name of the method</param>
  5615. /// <param name="parTypes">The signature of the method</param>
  5616. /// <returns>The method descriptor for name(parTypes)</returns>
  5617. public Method GetMethodDesc(string name, Type[] parTypes) {
  5618. for (int i=0; i < methods.Count; i++) {
  5619. if (((Method)methods[i]).HasNameAndSig(name,parTypes))
  5620. return (Method)methods[i];
  5621. }
  5622. return null;
  5623. }
  5624. /// <summary>
  5625. /// Get the vararg method "name(parTypes,optTypes)" for this class
  5626. /// </summary>
  5627. /// <param name="name">Method name</param>
  5628. /// <param name="parTypes">Method parameter types</param>
  5629. /// <param name="optParTypes">Optional parameter types</param>
  5630. /// <returns>Descriptor for "name(parTypes,optTypes)"</returns>
  5631. public Method GetMethodDesc(string name, Type[] parTypes, Type[] optParTypes) {
  5632. for (int i=0; i < methods.Count; i++) {
  5633. if (((Method)methods[i]).HasNameAndSig(name,parTypes,optParTypes))
  5634. return (Method)methods[i];
  5635. }
  5636. return null;
  5637. }
  5638. /// <summary>
  5639. /// Get all the methods of this class called "name"
  5640. /// </summary>
  5641. /// <param name="name">The method name</param>
  5642. /// <returns>List of methods called "name"</returns>
  5643. public Method[] GetMethodDescs(string name) {
  5644. ArrayList meths = GetMeths(name);
  5645. return (Method[])meths.ToArray(typeof(Method));
  5646. }
  5647. /// <summary>
  5648. /// Get all the methods for this class
  5649. /// </summary>
  5650. /// <returns>List of methods for this class</returns>
  5651. public Method[] GetMethodDescs() {
  5652. return (Method[])methods.ToArray(typeof(Method));
  5653. }
  5654. /// <summary>
  5655. /// Remove the specified method from this class
  5656. /// </summary>
  5657. /// <param name="name">method name</param>
  5658. public void RemoveMethod(string name) {
  5659. Method meth = GetMethodDesc(name);
  5660. if (meth != null) methods.Remove(meth);
  5661. }
  5662. /// <summary>
  5663. /// Remove the specified method from this class
  5664. /// </summary>
  5665. /// <param name="name">method name</param>
  5666. /// <param name="parTypes">method parameter types</param>
  5667. public void RemoveMethod(string name, Type[] parTypes) {
  5668. Method meth = GetMethodDesc(name,parTypes);
  5669. if (meth != null) methods.Remove(meth);
  5670. }
  5671. /// <summary>
  5672. /// Remove the specified method from this class
  5673. /// </summary>
  5674. /// <param name="name">method name</param>
  5675. /// <param name="parTypes">method parameter types</param>
  5676. /// <param name="optTypes">optional method parameter types</param>
  5677. public void RemoveMethod(string name, Type[] parTypes, Type[] optTypes) {
  5678. Method meth = GetMethodDesc(name,parTypes,optTypes);
  5679. if (meth != null) methods.Remove(meth);
  5680. }
  5681. /// <summary>
  5682. /// Remove the specified method from this class
  5683. /// </summary>
  5684. /// <param name="meth">method descriptor</param>
  5685. public void RemoveMethod(Method meth) {
  5686. methods.Remove(meth);
  5687. }
  5688. /// <summary>
  5689. /// Remove the specified method from this class
  5690. /// </summary>
  5691. /// <param name="ix">index into list of methods for specified method</param>
  5692. public void RemoveMethod(int ix) {
  5693. methods.RemoveAt(ix);
  5694. }
  5695. /// <summary>
  5696. /// Get the descriptor for the field "name" for this class
  5697. /// </summary>
  5698. /// <param name="name">Field name</param>
  5699. /// <returns>Descriptor for field "name"</returns>
  5700. public Field GetFieldDesc(string name) {
  5701. return FindField(name);
  5702. }
  5703. /// <summary>
  5704. /// Get all the fields for this class
  5705. /// </summary>
  5706. /// <returns>List of fields for this class</returns>
  5707. public Field[] GetFieldDescs() {
  5708. return (Field[])fields.ToArray(typeof(Field));
  5709. }
  5710. /// <summary>
  5711. /// Remove the specified field from this class
  5712. /// </summary>
  5713. /// <param name="name">field name</param>
  5714. public void RemoveField(string name) {
  5715. Field f = FindField(name);
  5716. if (f != null) fields.Remove(f);
  5717. }
  5718. /// <summary>
  5719. /// Instantiate this generic type with the supplied types
  5720. /// </summary>
  5721. /// <param name="genTypes">types to instantiate with</param>
  5722. /// <returns>descriptor for instantiated generic type</returns>
  5723. public virtual ClassSpec Instantiate(Type[] genTypes) {
  5724. return new ClassSpec(this,genTypes);
  5725. }
  5726. /// <summary>
  5727. /// Denote this class as "special" such as a default module class
  5728. /// </summary>
  5729. public virtual void MakeSpecial() {
  5730. special = true;
  5731. }
  5732. /// <summary>
  5733. /// Get the owing scope of this class
  5734. /// </summary>
  5735. /// <returns>owner of this class</returns>
  5736. public abstract MetaDataElement GetParent();
  5737. /// <summary>
  5738. /// Get any nested classes of this class
  5739. /// </summary>
  5740. /// <returns>list of nested classes</returns>
  5741. public Class[] GetNestedClasses() {
  5742. return (Class[])nestedClasses.ToArray(typeof(Class));
  5743. }
  5744. /// <summary>
  5745. /// How many nested classes does this class have?
  5746. /// </summary>
  5747. /// <returns>number of nested classes</returns>
  5748. public int GetNestedClassCount() {
  5749. return nestedClasses.Count;
  5750. }
  5751. /*------------------------- internal functions --------------------------*/
  5752. internal virtual Type GetGenPar(uint ix) { return null; }
  5753. protected ArrayList GetMeths(string name) {
  5754. ArrayList meths = new ArrayList();
  5755. for (int i=0; i < methods.Count; i++) {
  5756. if (((Method)methods[i]).HasName(name))
  5757. meths.Add(methods[i]);
  5758. }
  5759. return meths;
  5760. }
  5761. internal ArrayList GetFieldList() { return fields; }
  5762. internal ArrayList GetMethodList() { return methods; }
  5763. internal bool isValueType() {
  5764. return typeIndex == (byte)ElementType.ValueType;
  5765. }
  5766. internal bool isSpecial() { return special; }
  5767. internal void AddToFieldList(Field f) {
  5768. f.SetParent(this);
  5769. fields.Add(f);
  5770. }
  5771. internal void AddToList(ArrayList list, MDTable tabIx) {
  5772. switch (tabIx) {
  5773. case (MDTable.Field) : fields.AddRange(list); break;
  5774. case (MDTable.Method) : methods.AddRange(list); break;
  5775. case (MDTable.TypeDef) : nestedClasses.AddRange(list); break;
  5776. default : throw new Exception("Unknown list type");
  5777. }
  5778. }
  5779. internal void AddToMethodList(Method m) {
  5780. m.SetParent(this);
  5781. methods.Add(m);
  5782. }
  5783. internal void AddToClassList(Class nClass) {
  5784. nestedClasses.Add(nClass);
  5785. }
  5786. internal Class GetNested(string name) {
  5787. for (int i=0; i < nestedClasses.Count; i++) {
  5788. if (((Class)nestedClasses[i]).Name() == name)
  5789. return (Class)nestedClasses[i];
  5790. }
  5791. return null;
  5792. }
  5793. internal Method GetMethod(MethSig mSig) {
  5794. return GetMethodDesc(mSig.name,mSig.parTypes,mSig.optParTypes);
  5795. }
  5796. protected Field FindField(string name) {
  5797. for (int i=0; i < fields.Count; i++) {
  5798. if (((Field)fields[i]).Name() == name)
  5799. return (Field)fields[i];
  5800. }
  5801. return null;
  5802. }
  5803. internal void SetBuffer(PEReader buff) { buffer = buff; }
  5804. internal override void TypeSig(MemoryStream sig) {
  5805. sig.WriteByte(typeIndex);
  5806. MetaDataOut.CompressNum(TypeDefOrRefToken(),sig);
  5807. }
  5808. internal abstract string ClassName();
  5809. internal virtual uint TypeDefOrRefToken() { return 0; }
  5810. }
  5811. /**************************************************************************/
  5812. /// <summary>
  5813. ///
  5814. /// </summary>
  5815. public class ClassSpec : Class {
  5816. Class genClass;
  5817. uint sigIx;
  5818. private static byte GENERICINST = 0x15;
  5819. /*-------------------- Constructors ---------------------------------*/
  5820. internal ClassSpec(Class clType, Type[] gPars) {
  5821. this.typeIndex = GENERICINST;
  5822. genClass = clType;
  5823. genericParams = new ArrayList(gPars);
  5824. tabIx = MDTable.TypeSpec;
  5825. typeIndex = GENERICINST;
  5826. ArrayList classMethods = clType.GetMethodList();
  5827. ArrayList classFields = clType.GetFieldList();
  5828. for (int i=0; i < classMethods.Count; i++) {
  5829. MethSig mSig = ((Method)classMethods[i]).GetSig(); //.InstantiateGenTypes(this,gPars);
  5830. if (mSig != null) {
  5831. MethodRef newMeth = new MethodRef(mSig);
  5832. newMeth.SetParent(this);
  5833. newMeth.GenericParams = ((Method)classMethods[i]).GenericParams;
  5834. methods.Add(newMeth);
  5835. }
  5836. }
  5837. for (int i=0; i < classFields.Count; i++) {
  5838. Type fType = ((Field)classFields[i]).GetFieldType();
  5839. //if ((fType is GenericParam) && (((GenericParam)fType).GetParent() == genClass)) {
  5840. // fType = gPars[((GenericParam)fType).Index];
  5841. //}
  5842. fields.Add(new FieldRef(this,((Field)classFields[i]).Name(),fType));
  5843. }
  5844. }
  5845. /*------------------------- public set and get methods --------------------------*/
  5846. /// <summary>
  5847. /// Get the generic class that this is an instantiation of
  5848. /// </summary>
  5849. /// <returns>generic class</returns>
  5850. public override MetaDataElement GetParent() {
  5851. return null;
  5852. }
  5853. /// <summary>
  5854. /// Get the specified generic parameter number
  5855. /// </summary>
  5856. /// <param name="ix">generic parameter number</param>
  5857. /// <returns>generic parameter number ix</returns>
  5858. public Type GetGenericParamType(int ix) {
  5859. if (ix >= genericParams.Count) return null;
  5860. return (Type)genericParams[ix];
  5861. }
  5862. /// <summary>
  5863. /// Get the generic parameters of this class
  5864. /// </summary>
  5865. /// <returns>list of generic parameters</returns>
  5866. public Type[] GetGenericParamTypes() {
  5867. return (Type[])genericParams.ToArray(typeof(Type));
  5868. }
  5869. /// <summary>
  5870. /// Get the generic class that this class instantiates
  5871. /// </summary>
  5872. /// <returns>generic class</returns>
  5873. public Class GetGenericClass() {
  5874. return genClass;
  5875. }
  5876. /// <summary>
  5877. /// Count how many generic parameters this class has
  5878. /// </summary>
  5879. /// <returns>number of generic parameters</returns>
  5880. public int GetGenericParCount() {
  5881. return genericParams.Count;
  5882. }
  5883. /*----------------------------- internal functions ------------------------------*/
  5884. internal void AddMethod(Method meth) {
  5885. methods.Add(meth);
  5886. meth.SetParent(this);
  5887. }
  5888. internal override string ClassName() {
  5889. // need to return something here??
  5890. return null;
  5891. }
  5892. internal override sealed uint TypeDefOrRefToken() {
  5893. uint cIx = Row;
  5894. cIx = (cIx << 2) | 0x2;
  5895. return cIx;
  5896. }
  5897. internal override Type GetGenPar(uint ix) {
  5898. if (genClass == null) return new GenericParam(null,this,(int)ix);
  5899. return genClass.GetGenPar(ix);
  5900. //if (ix >= genericParams.Count) return null;
  5901. //return (Type)genericParams[(int)ix];
  5902. }
  5903. internal override sealed Type AddTypeSpec(MetaDataOut md) {
  5904. md.AddToTable(MDTable.TypeSpec,this);
  5905. BuildMDTables(md);
  5906. return this;
  5907. }
  5908. internal override void BuildTables(MetaDataOut md) {
  5909. //md.AddToTable(MDTable.TypeSpec,this);
  5910. if (!genClass.isDef())
  5911. genClass.BuildMDTables(md);
  5912. for (int i=0; i < genericParams.Count; i++) {
  5913. if (!((Type)genericParams[i]).isDef() &&
  5914. (!(genericParams[i] is GenericParam)))
  5915. ((Type)genericParams[i]).BuildMDTables(md);
  5916. }
  5917. }
  5918. internal override void BuildSignatures(MetaDataOut md) {
  5919. MemoryStream outSig = new MemoryStream();
  5920. TypeSig(outSig);
  5921. sigIx = md.AddToBlobHeap(outSig.ToArray());
  5922. }
  5923. internal sealed override void TypeSig(MemoryStream sig) {
  5924. sig.WriteByte(typeIndex);
  5925. genClass.TypeSig(sig);
  5926. MetaDataOut.CompressNum((uint)genericParams.Count,sig);
  5927. for (int i=0; i < genericParams.Count; i++) {
  5928. ((Type)genericParams[i]).TypeSig(sig);
  5929. }
  5930. }
  5931. internal sealed override void Write(PEWriter output) {
  5932. //Console.WriteLine("Writing the blob index for a TypeSpec");
  5933. output.BlobIndex(sigIx);
  5934. }
  5935. internal sealed override uint GetCodedIx(CIx code) {
  5936. switch (code) {
  5937. case (CIx.TypeDefOrRef) : return 2;
  5938. case (CIx.HasCustomAttr) : return 13;
  5939. case (CIx.MemberRefParent) : return 4;
  5940. }
  5941. return 0;
  5942. }
  5943. }
  5944. /**************************************************************************/
  5945. /// <summary>
  5946. /// wrapper for TypeSpec parent of MethodRef or FieldRef
  5947. /// </summary>
  5948. public class ConstructedTypeSpec : Class {
  5949. TypeSpec constrType;
  5950. public ConstructedTypeSpec(TypeSpec tySpec) : base() {
  5951. constrType = tySpec;
  5952. this.typeIndex = constrType.GetTypeIndex();
  5953. }
  5954. public override MetaDataElement GetParent() {
  5955. return null;
  5956. }
  5957. internal override string ClassName() {
  5958. return constrType.NameString();
  5959. }
  5960. }
  5961. /**************************************************************************/
  5962. public abstract class ClassDesc : Class {
  5963. /*-------------------- Constructors ---------------------------------*/
  5964. internal ClassDesc(string nameSpaceName, string className) {
  5965. nameSpace = nameSpaceName;
  5966. name = className;
  5967. }
  5968. internal ClassDesc() {
  5969. }
  5970. /*------------------------- public set and get methods --------------------------*/
  5971. public GenericParam GetGenericParam(int ix) {
  5972. if (ix >= genericParams.Count) return null;
  5973. return (GenericParam)genericParams[ix];
  5974. }
  5975. public GenericParam[] GetGenericParams() {
  5976. return (GenericParam[])genericParams.ToArray(typeof(GenericParam));
  5977. }
  5978. public virtual void SetGenericParams(GenericParam[] genPars) {
  5979. for (int i=0; i < genPars.Length; i++) {
  5980. genPars[i].SetClassParam(this,i);
  5981. }
  5982. genericParams = new ArrayList(genPars);
  5983. }
  5984. /*----------------------------- internal functions ------------------------------*/
  5985. protected void DeleteGenericParam(int pos) {
  5986. genericParams.RemoveAt(pos);
  5987. for (int i=pos; i < genericParams.Count; i++) {
  5988. GenericParam gp = (GenericParam)genericParams[i];
  5989. gp.Index = (uint)i;
  5990. }
  5991. }
  5992. internal void AddGenericParam(GenericParam par) {
  5993. genericParams.Add(par);
  5994. //par.SetClassParam(this,genericParams.Count-1);
  5995. }
  5996. internal override Type GetGenPar(uint ix) {
  5997. // create generic param descriptor if one does not exist
  5998. // - used when reading exported interface
  5999. // The next two lines are *required* for v2.0 beta release! (kjg)
  6000. for (int i = genericParams.Count; i <= ix; i++)
  6001. genericParams.Add(new GenericParam("gp" + i, this, i));
  6002. return (GenericParam)genericParams[(int)ix];
  6003. }
  6004. }
  6005. /**************************************************************************/
  6006. // This Class produces entries in the TypeDef table of the MetaData
  6007. // in the PE meta data.
  6008. // NOTE: Entry 0 in TypeDef table is always the pseudo class <module>
  6009. // which is the parent for functions and variables declared a module level
  6010. /// <summary>
  6011. /// The descriptor for a class defined in the IL (.class) in the current assembly/module
  6012. /// </summary>
  6013. ///
  6014. public class ClassDef : ClassDesc {
  6015. private static readonly uint HasSecurity = 0x00040000;
  6016. private static readonly uint NoSecurity = 0xFFFBFFFF;
  6017. private static readonly uint VisibilityMask = 0x07;
  6018. private static readonly uint LayoutMask = 0x18;
  6019. private static readonly uint StringFormatMask = 0x030000;
  6020. //private static readonly uint fieldListIx = 0, methListIx = 1, eventListIx = 2, propListIx = 3;
  6021. //private static readonly uint numListIx = 4;
  6022. protected PEFile scope;
  6023. uint flags;
  6024. Class superType;
  6025. ArrayList security;
  6026. ClassLayout layout;
  6027. uint extendsIx;
  6028. internal ClassRef refOf;
  6029. internal uint eventIx = 0, propIx = 0;
  6030. ArrayList events = new ArrayList();
  6031. ArrayList properties = new ArrayList();
  6032. ArrayList interfaces = new ArrayList();
  6033. ArrayList methodImpls = new ArrayList();
  6034. //uint[] interfaceIndexes;
  6035. //private string[] eventNames, propertyNames, nestedNames;
  6036. //internal string[][] names = new string[numListIx][];
  6037. /*-------------------- Constructors ---------------------------------*/
  6038. internal ClassDef(PEFile scope, TypeAttr attrSet, string nsName, string name)
  6039. : base(nsName,name) {
  6040. this.scope = scope;
  6041. superType = MSCorLib.mscorlib.ObjectClass;
  6042. flags = (uint)attrSet;
  6043. tabIx = MDTable.TypeDef;
  6044. }
  6045. internal ClassDef(PEReader buff, uint row, bool isMSCorLib) {
  6046. flags = buff.ReadUInt32();
  6047. name = buff.GetString();
  6048. nameSpace = buff.GetString();
  6049. extendsIx = buff.GetCodedIndex(CIx.TypeDefOrRef);
  6050. fieldIx = buff.GetIndex(MDTable.Field);
  6051. methodIx = buff.GetIndex(MDTable.Method);
  6052. this.Row = row;
  6053. tabIx = MDTable.TypeDef;
  6054. if (isMSCorLib && (name == "ValueType"))
  6055. typeIndex = (byte)ElementType.ValueType;
  6056. }
  6057. internal static void Read(PEReader buff, TableRow[] typeDefs, bool isMSCorLib) {
  6058. ClassDef prevDef = null;
  6059. prevDef = new ClassDef(buff,1,isMSCorLib);
  6060. typeDefs[0] = prevDef;
  6061. for (int i=1; i < typeDefs.Length; i++) {
  6062. ClassDef typeDef = new ClassDef(buff,(uint)i+1,isMSCorLib);
  6063. prevDef.fieldEndIx = typeDef.fieldIx;
  6064. prevDef.methodEndIx = typeDef.methodIx;
  6065. prevDef = typeDef;
  6066. typeDefs[i] = typeDef;
  6067. }
  6068. prevDef.fieldEndIx = buff.GetTableSize(MDTable.Field)+1;
  6069. prevDef.methodEndIx = buff.GetTableSize(MDTable.Method)+1;
  6070. }
  6071. private static uint GetParentClassIx(uint[] enclClasses, uint[] nestClasses, uint classIx) {
  6072. if (enclClasses == null) return 0;
  6073. for (uint i=0; i < enclClasses.Length; i++) {
  6074. if (nestClasses[i] == classIx)
  6075. return enclClasses[i];
  6076. }
  6077. return 0;
  6078. }
  6079. internal static void GetClassRefs(PEReader buff, TableRow[] typeRefs, ReferenceScope paren, uint[] parIxs) {
  6080. int num = typeRefs.Length;
  6081. uint[] fieldStart = new uint[num+1], methStart = new uint[num+1], extends = new uint[num+1];
  6082. for (int i=0; i < num; i++) {
  6083. uint flags = buff.ReadUInt32();
  6084. string name = buff.GetString();
  6085. string nameSpace = buff.GetString();
  6086. extends[i] = buff.GetCodedIndex(CIx.TypeDefOrRef);
  6087. fieldStart[i] = buff.GetIndex(MDTable.Field);
  6088. methStart[i] = buff.GetIndex(MDTable.Method);
  6089. //Console.WriteLine("flags = " + Hex.Int(flags));
  6090. if (i == 0) // ASSERT first entry is always <Module>
  6091. typeRefs[i] = paren.GetDefaultClass();
  6092. else if (isPublic(flags)) {
  6093. if (parIxs[i] != 0) {
  6094. typeRefs[i] = new NestedClassRef(paren,nameSpace,name);
  6095. } else {
  6096. typeRefs[i] = paren.GetExistingClass(nameSpace,name);
  6097. if (typeRefs[i] == null) {
  6098. typeRefs[i] = new ClassRef(paren,nameSpace,name);
  6099. paren.AddToClassList((ClassRef)typeRefs[i]);
  6100. }
  6101. }
  6102. }
  6103. }
  6104. fieldStart[num] = buff.GetTableSize(MDTable.Field)+1;
  6105. methStart[num] = buff.GetTableSize(MDTable.Method)+1;
  6106. // Find Nested Classes
  6107. for (int i=0; i < typeRefs.Length; i++) {
  6108. if ((typeRefs[i] != null) && (typeRefs[i] is NestedClassRef)) {
  6109. NestedClassRef nRef = (NestedClassRef)typeRefs[i];
  6110. ClassRef nPar = (ClassRef)typeRefs[parIxs[i]-1];
  6111. if (nPar == null) { // parent is private, so ignore
  6112. typeRefs[i] = null;
  6113. } else {
  6114. nRef.SetParent(nPar);
  6115. nPar.AddToClassList(nRef);
  6116. }
  6117. }
  6118. if (typeRefs[i] != null) {
  6119. if (buff.GetCodedElement(CIx.TypeDefOrRef,extends[i]) == MSCorLib.mscorlib.ValueType())
  6120. ((ClassRef)typeRefs[i]).MakeValueClass();
  6121. buff.SetElementPosition(MDTable.Field,fieldStart[i]);
  6122. FieldDef.GetFieldRefs(buff,fieldStart[i+1]-fieldStart[i],(ClassRef)typeRefs[i]);
  6123. buff.SetElementPosition(MDTable.Method,methStart[i]);
  6124. MethodDef.GetMethodRefs(buff,methStart[i+1]-methStart[i],(ClassRef)typeRefs[i]);
  6125. }
  6126. }
  6127. }
  6128. internal override void Resolve(PEReader buff) {
  6129. buff.currentClassScope = this;
  6130. superType = (Class)buff.GetCodedElement(CIx.TypeDefOrRef,extendsIx);
  6131. if ((superType != null) && superType.isValueType())
  6132. typeIndex = (byte)ElementType.ValueType;
  6133. for (int i=0; fieldIx < fieldEndIx; i++, fieldIx++) {
  6134. FieldDef field = (FieldDef)buff.GetElement(MDTable.Field,fieldIx);
  6135. field.SetParent(this);
  6136. fields.Add(field);
  6137. }
  6138. for (int i=0; methodIx < methodEndIx; i++, methodIx++) {
  6139. MethodDef meth = (MethodDef)buff.GetElement(MDTable.Method,methodIx);
  6140. if (Diag.DiagOn) Console.WriteLine("Adding method " + meth.Name() + " to class " + name);
  6141. meth.SetParent(this);
  6142. methods.Add(meth);
  6143. }
  6144. buff.currentClassScope = null;
  6145. }
  6146. internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) {
  6147. for (int i=0; i < oldTypes.Length; i++) {
  6148. for (int j=0; j < oldTypes[i].fields.Count; j++)
  6149. ((FieldDef)oldTypes[i].fields[j]).ChangeRefsToDefs(this,oldTypes);
  6150. for (int j=0; j < oldTypes[i].methods.Count; j++)
  6151. ((MethodDef)oldTypes[i].methods[j]).ChangeRefsToDefs(this,oldTypes);
  6152. for (int j=0; j < oldTypes[i].events.Count; j++)
  6153. ((Event)oldTypes[i].events[j]).ChangeRefsToDefs(this,oldTypes);
  6154. for (int j=0; j < oldTypes[i].properties.Count; j++)
  6155. ((Property)oldTypes[i].properties[j]).ChangeRefsToDefs(this,oldTypes);
  6156. for (int j=0; j < oldTypes[i].interfaces.Count; j++)
  6157. ((ClassDef)oldTypes[i].interfaces[j]).ChangeRefsToDefs(this,oldTypes);
  6158. for (int j=0; j < oldTypes[i].methodImpls.Count; j++)
  6159. ((MethodImpl)oldTypes[i].methodImpls[j]).ChangeRefsToDefs(this,oldTypes);
  6160. for (int j=0; j < oldTypes[i].nestedClasses.Count; j++)
  6161. ((ClassDef)oldTypes[i].nestedClasses[j]).ChangeRefsToDefs(this,oldTypes);
  6162. }
  6163. }
  6164. public void MergeClasses(ClassDef[] classes) {
  6165. ChangeRefsToDefs(this,classes);
  6166. for (int i=0; i < classes.Length; i++) {
  6167. fields.AddRange(classes[i].fields);
  6168. methods.AddRange(classes[i].methods);
  6169. events.AddRange(classes[i].events);
  6170. properties.AddRange(classes[i].properties);
  6171. interfaces.AddRange(classes[i].interfaces);
  6172. methodImpls.AddRange(classes[i].methodImpls);
  6173. nestedClasses.AddRange(classes[i].nestedClasses);
  6174. }
  6175. }
  6176. /*------------------------- public set and get methods --------------------------*/
  6177. /// <summary>
  6178. /// Fetch the PEFile which contains this class
  6179. /// </summary>
  6180. /// <returns>PEFile containing this class</returns>
  6181. public virtual PEFile GetScope() { return scope; }
  6182. public override MetaDataElement GetParent() { return scope; }
  6183. /// <summary>
  6184. /// Fetch or Get the superType for this class
  6185. /// </summary>
  6186. public Class SuperType {
  6187. get { return superType; }
  6188. set {
  6189. superType = value;
  6190. if (value == MSCorLib.mscorlib.ValueType())
  6191. typeIndex = (byte)ElementType.ValueType;
  6192. else
  6193. typeIndex = (byte)ElementType.Class;
  6194. }
  6195. }
  6196. /* /// <summary>
  6197. /// Make this class inherit from ValueType
  6198. /// </summary>
  6199. public override void MakeValueClass() {
  6200. superType = MSCorLib.mscorlib.ValueType();
  6201. typeIndex = (byte)ElementType.ValueType;
  6202. }
  6203. */
  6204. /// <summary>
  6205. /// Add an attribute to the attributes of this class
  6206. /// </summary>
  6207. /// <param name="ta">the attribute to be added</param>
  6208. public void AddAttribute(TypeAttr ta) {
  6209. flags |= (uint)ta;
  6210. }
  6211. /// <summary>
  6212. /// Set the attributes of this class
  6213. /// </summary>
  6214. /// <param name="ta">class attributes</param>
  6215. public void SetAttribute(TypeAttr ta) {
  6216. flags = (uint)ta;
  6217. }
  6218. /// <summary>
  6219. /// Get the attributes for this class
  6220. /// </summary>
  6221. /// <returns></returns>
  6222. public TypeAttr GetAttributes() { return (TypeAttr)flags; }
  6223. public GenericParam AddGenericParam(string name) {
  6224. GenericParam gp = new GenericParam(name,this,genericParams.Count);
  6225. genericParams.Add(gp);
  6226. return gp;
  6227. }
  6228. public int GetGenericParamCount() {
  6229. return genericParams.Count;
  6230. }
  6231. public GenericParam GetGenericParam(string name) {
  6232. int pos = FindGenericParam(name);
  6233. if (pos == -1) return null;
  6234. return (GenericParam)genericParams[pos];
  6235. }
  6236. public void RemoveGenericParam(string name) {
  6237. int pos = FindGenericParam(name);
  6238. if (pos == -1) return;
  6239. DeleteGenericParam(pos);
  6240. }
  6241. public void RemoveGenericParam(int ix) {
  6242. if (ix >= genericParams.Count) return;
  6243. DeleteGenericParam(ix);
  6244. }
  6245. public override ClassSpec Instantiate(Type[] genTypes) {
  6246. if (genTypes == null) return null;
  6247. if (genericParams.Count == 0)
  6248. throw new Exception("Cannot instantiate non-generic class");
  6249. if (genTypes.Length != genericParams.Count)
  6250. throw new Exception("Wrong number of type parameters for instantiation\nNeeded "
  6251. + genericParams.Count + " but got " + genTypes.Length);
  6252. return new ClassSpec(this,genTypes);
  6253. }
  6254. /// <summary>
  6255. /// Add an interface that is implemented by this class
  6256. /// </summary>
  6257. /// <param name="iFace">the interface that is implemented</param>
  6258. public void AddImplementedInterface(Class iFace) {
  6259. interfaces.Add(new InterfaceImpl(this,iFace));
  6260. //metaData.AddToTable(MDTable.InterfaceImpl,new InterfaceImpl(this,iFace));
  6261. }
  6262. /// <summary>
  6263. /// Get the interfaces implemented by this class
  6264. /// </summary>
  6265. /// <returns>List of implemented interfaces</returns>
  6266. public Class[] GetInterfaces() {
  6267. Class[] iFaces = new Class[interfaces.Count];
  6268. for (int i=0; i < iFaces.Length; i++) {
  6269. iFaces[i] = ((InterfaceImpl)interfaces[i]).TheInterface();
  6270. }
  6271. return iFaces;
  6272. }
  6273. /// <summary>
  6274. /// Add a field to this class
  6275. /// </summary>
  6276. /// <param name="name">field name</param>
  6277. /// <param name="fType">field type</param>
  6278. /// <returns>a descriptor for this new field</returns>
  6279. public FieldDef AddField(string name, Type fType) {
  6280. FieldDef field = (FieldDef)FindField(name);
  6281. if (field != null)
  6282. throw new DescriptorException("Field " + field.NameString());
  6283. field = new FieldDef(name,fType,this);
  6284. fields.Add(field);
  6285. return field;
  6286. }
  6287. /// <summary>
  6288. /// Add a field to this class
  6289. /// </summary>
  6290. /// <param name="fAtts">attributes for this field</param>
  6291. /// <param name="name">field name</param>
  6292. /// <param name="fType">field type</param>
  6293. /// <returns>a descriptor for this new field</returns>
  6294. public FieldDef AddField(FieldAttr fAtts, string name, Type fType) {
  6295. FieldDef field = AddField(name,fType);
  6296. field.SetFieldAttr(fAtts);
  6297. return field;
  6298. }
  6299. /// <summary>
  6300. /// Add a field to this class
  6301. /// </summary>
  6302. /// <param name="f">Descriptor for the field to be added</param>
  6303. public void AddField(FieldDef f) {
  6304. FieldDef field = (FieldDef)FindField(f.Name());
  6305. if (field != null)
  6306. throw new DescriptorException("Field " + field.NameString());
  6307. f.SetParent(this);
  6308. fields.Add(f);
  6309. }
  6310. /// <summary>
  6311. /// Get the descriptor for the field of this class named "name"
  6312. /// </summary>
  6313. /// <param name="name">The field name</param>
  6314. /// <returns>The descriptor for field "name"</returns>
  6315. public FieldDef GetField(string name) {
  6316. return (FieldDef)FindField(name);
  6317. }
  6318. /// <summary>
  6319. /// Get the fields for this class
  6320. /// </summary>
  6321. /// <returns>List of fields of this class</returns>
  6322. public FieldDef[] GetFields() {
  6323. return (FieldDef[])fields.ToArray(typeof(FieldDef));
  6324. }
  6325. /// <summary>
  6326. /// Add a method to this class
  6327. /// </summary>
  6328. /// <param name="name">method name</param>
  6329. /// <param name="retType">return type</param>
  6330. /// <param name="pars">parameters</param>
  6331. /// <returns>a descriptor for this new method</returns>
  6332. public MethodDef AddMethod(string name, Type retType, Param[] pars) {
  6333. System.Diagnostics.Debug.Assert(retType != null);
  6334. MethSig mSig = new MethSig(name);
  6335. mSig.SetParTypes(pars);
  6336. MethodDef meth = (MethodDef)GetMethod(mSig);
  6337. if (meth != null)
  6338. throw new DescriptorException("Method " + meth.NameString());
  6339. mSig.retType = retType;
  6340. meth = new MethodDef(this,mSig,pars);
  6341. methods.Add(meth);
  6342. return meth;
  6343. }
  6344. /// <summary>
  6345. /// Add a method to this class
  6346. /// </summary>
  6347. /// <param name="name">method name</param>
  6348. /// <param name="genPars">generic parameters</param>
  6349. /// <param name="retType">return type</param>
  6350. /// <param name="pars">parameters</param>
  6351. /// <returns>a descriptor for this new method</returns>
  6352. public MethodDef AddMethod(string name, GenericParam[] genPars, Type retType, Param[] pars) {
  6353. MethodDef meth = AddMethod(name,retType,pars);
  6354. if ((genPars != null) && (genPars.Length > 0)) {
  6355. for (int i=0; i < genPars.Length; i++) {
  6356. genPars[i].SetMethParam(meth,i);
  6357. }
  6358. meth.SetGenericParams(genPars);
  6359. }
  6360. return meth;
  6361. }
  6362. /// <summary>
  6363. /// Add a method to this class
  6364. /// </summary>
  6365. /// <param name="mAtts">attributes for this method</param>
  6366. /// <param name="iAtts">implementation attributes for this method</param>
  6367. /// <param name="name">method name</param>
  6368. /// <param name="retType">return type</param>
  6369. /// <param name="pars">parameters</param>
  6370. /// <returns>a descriptor for this new method</returns>
  6371. public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
  6372. Type retType, Param[] pars) {
  6373. MethodDef meth = AddMethod(name,retType,pars);
  6374. meth.AddMethAttribute(mAtts);
  6375. meth.AddImplAttribute(iAtts);
  6376. return meth;
  6377. }
  6378. /// <summary>
  6379. /// Add a method to this class
  6380. /// </summary>
  6381. /// <param name="mAtts">attributes for this method</param>
  6382. /// <param name="iAtts">implementation attributes for this method</param>
  6383. /// <param name="name">method name</param>
  6384. /// <param name="genPars">generic parameters</param>
  6385. /// <param name="retType">return type</param>
  6386. /// <param name="pars">parameters</param>
  6387. /// <returns>a descriptor for this new method</returns>
  6388. public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name,
  6389. GenericParam[] genPars, Type retType, Param[] pars) {
  6390. MethodDef meth = AddMethod(name,genPars,retType,pars);
  6391. meth.AddMethAttribute(mAtts);
  6392. meth.AddImplAttribute(iAtts);
  6393. return meth;
  6394. }
  6395. /// <summary>
  6396. /// Add a method to this class
  6397. /// </summary>
  6398. /// <param name="meth">Descriptor for the method to be added</param>
  6399. public void AddMethod(MethodDef meth) {
  6400. MethodDef m = (MethodDef)GetMethodDesc(meth.Name(),meth.GetParTypes());
  6401. if (m != null)
  6402. throw new DescriptorException("Method " + m.NameString());
  6403. methods.Add(meth);
  6404. meth.SetParent(this);
  6405. }
  6406. /// <summary>
  6407. /// Get the descriptor for the method "name" of this class
  6408. /// </summary>
  6409. /// <param name="name">The name of the method to be retrieved</param>
  6410. /// <returns>The method descriptor for "name"</returns>
  6411. public MethodDef GetMethod(string name) {
  6412. return (MethodDef)GetMethodDesc(name);
  6413. }
  6414. /// <summary>
  6415. /// Get the descriptor for the method called "name" with the signature "parTypes"
  6416. /// </summary>
  6417. /// <param name="name">The name of the method</param>
  6418. /// <param name="parTypes">The signature of the method</param>
  6419. /// <returns>The method descriptor for name(parTypes)</returns>
  6420. public MethodDef GetMethod(string name, Type[] parTypes) {
  6421. return (MethodDef)GetMethodDesc(name,parTypes);
  6422. }
  6423. /// <summary>
  6424. /// Get all the methods of this class called "name"
  6425. /// </summary>
  6426. /// <param name="name">The method name</param>
  6427. /// <returns>List of methods called "name"</returns>
  6428. public MethodDef[] GetMethods(string name) {
  6429. ArrayList meths = GetMeths(name);
  6430. return (MethodDef[])meths.ToArray(typeof(MethodDef));
  6431. }
  6432. /// <summary>
  6433. /// Get all the methods for this class
  6434. /// </summary>
  6435. /// <returns>List of methods for this class</returns>
  6436. public MethodDef[] GetMethods() {
  6437. return (MethodDef[])methods.ToArray(typeof(MethodDef));
  6438. }
  6439. /// <summary>
  6440. /// Add an event to this class
  6441. /// </summary>
  6442. /// <param name="name">event name</param>
  6443. /// <param name="eType">event type</param>
  6444. /// <returns>a descriptor for this new event</returns>
  6445. public Event AddEvent(string name, Type eType) {
  6446. Event e = (Event)FindFeature(name,events);
  6447. if (e != null)
  6448. throw new DescriptorException("Event " + e.NameString());
  6449. e = new Event(name,eType,this);
  6450. events.Add(e);
  6451. return e;
  6452. }
  6453. /// <summary>
  6454. /// Get the event "name" of this class
  6455. /// </summary>
  6456. /// <param name="name">The event name</param>
  6457. /// <returns>The event desctiptor for "name"</returns>
  6458. public Event GetEvent(string name) {
  6459. return (Event)FindFeature(name,events);
  6460. }
  6461. /// <summary>
  6462. /// Get all the events of this class
  6463. /// </summary>
  6464. /// <returns>List of events for this class</returns>
  6465. public Event[] GetEvents() {
  6466. return (Event[])events.ToArray(typeof(Event));
  6467. }
  6468. /// <summary>
  6469. /// Remove the event "name" from this class
  6470. /// </summary>
  6471. /// <param name="name">The name of the event to be removed</param>
  6472. public void RemoveEvent(string name) {
  6473. Feature ev = FindFeature(name,events);
  6474. if (ev != null) events.Remove(ev);
  6475. }
  6476. /// <summary>
  6477. /// Add a property to this class
  6478. /// </summary>
  6479. /// <param name="name">property name</param>
  6480. /// <param name="pars">parameters</param>
  6481. /// <param name="retType">return type</param>
  6482. /// <returns>a descriptor for this new property</returns>
  6483. public Property AddProperty(string name, Type retType, Type[] pars) {
  6484. Property p = (Property)FindFeature(name,properties);
  6485. if (p != null)
  6486. throw new DescriptorException("Property " + p.NameString());
  6487. p = new Property(name, retType, pars, this);
  6488. properties.Add(p);
  6489. return p;
  6490. }
  6491. /// <summary>
  6492. /// Get the property "name" for this class
  6493. /// </summary>
  6494. /// <param name="name">Descriptor for the property "name"</param>
  6495. /// <returns></returns>
  6496. public Property GetProperty(string name) {
  6497. return (Property)FindFeature(name,properties);
  6498. }
  6499. /// <summary>
  6500. /// Get all the properties for this class
  6501. /// </summary>
  6502. /// <returns>List of properties for this class</returns>
  6503. public Property[] GetProperties() {
  6504. return (Property[])properties.ToArray(typeof(Property));
  6505. }
  6506. /// <summary>
  6507. /// Remove the property "name" from this class
  6508. /// </summary>
  6509. /// <param name="name">Name of the property to be removed</param>
  6510. public void RemoveProperty(string name) {
  6511. Feature prop = FindFeature(name,properties);
  6512. if (prop != null) properties.Remove(prop);
  6513. }
  6514. /// <summary>
  6515. /// Add a nested class to this class
  6516. /// </summary>
  6517. /// <param name="attrSet">attributes for this nested class</param>
  6518. /// <param name="name">nested class name</param>
  6519. /// <returns>a descriptor for this new nested class</returns>
  6520. public NestedClassDef AddNestedClass(TypeAttr attrSet, string name) {
  6521. NestedClassDef nClass = GetNestedClass(name);
  6522. if (nClass != null)
  6523. throw new DescriptorException("Nested Class " + nClass.NameString());
  6524. nClass = new NestedClassDef(this,attrSet,name);
  6525. nestedClasses.Add(nClass);
  6526. return (nClass);
  6527. }
  6528. /// <summary>
  6529. /// Add a nested class to this class
  6530. /// </summary>
  6531. /// <param name="attrSet">attributes for this nested class</param>
  6532. /// <param name="name">nested class name</param>
  6533. /// <param name="sType">super type of this nested class</param>
  6534. /// <returns>a descriptor for this new nested class</returns>
  6535. public NestedClassDef AddNestedClass(TypeAttr attrSet, string name, Class sType) {
  6536. NestedClassDef nClass = AddNestedClass(attrSet,name);
  6537. nClass.superType = sType;
  6538. return (nClass);
  6539. }
  6540. /// <summary>
  6541. /// Get the nested class called "name"
  6542. /// </summary>
  6543. /// <param name="name">The name of the nested class</param>
  6544. /// <returns>Descriptor for the nested class</returns>
  6545. public NestedClassDef GetNestedClass(string name) {
  6546. //CheckNestedClassNames(MDTable.TypeDef);
  6547. return (NestedClassDef)GetNested(name);
  6548. }
  6549. /// <summary>
  6550. /// Add layout information for this class. This class must have the
  6551. /// sequential or explicit attribute.
  6552. /// </summary>
  6553. /// <param name="packSize">packing size (.pack)</param>
  6554. /// <param name="classSize">class size (.size)</param>
  6555. public void AddLayoutInfo (int packSize, int classSize) {
  6556. layout = new ClassLayout(packSize,classSize,this);
  6557. }
  6558. /// <summary>
  6559. /// Get the pack size for this class (only valid for ExplicitLayout or SequentialLayout
  6560. /// </summary>
  6561. /// <returns>Class pack size</returns>
  6562. public int GetPackSize() {
  6563. if ((layout == null) && (((flags & (uint)TypeAttr.ExplicitLayout) != 0) ||
  6564. ((flags & (uint)TypeAttr.SequentialLayout) != 0)) && (buffer != null)) {
  6565. buffer.SetElementPosition(MDTable.ClassLayout,0);
  6566. //layout = buffer.FindParent(MDTable.ClassLayout,this);
  6567. }
  6568. if (layout != null) return layout.GetPack();
  6569. return 0;
  6570. }
  6571. /// <summary>
  6572. /// Get the size of this class (only valid for ExplicitLayout or SequentialLayout
  6573. /// </summary>
  6574. /// <returns>The size of this class</returns>
  6575. public int GetClassSize() {
  6576. if (layout == null) return 0;
  6577. return layout.GetSize();
  6578. }
  6579. /// <summary>
  6580. /// Get the ClassRef for this ClassDef, if there is one
  6581. /// </summary>
  6582. public ClassRef RefOf {
  6583. get {
  6584. if (refOf == null) {
  6585. ModuleRef modRef = scope.refOf;
  6586. if (modRef != null)
  6587. refOf = modRef.GetClass(name);
  6588. }
  6589. return refOf;
  6590. }
  6591. }
  6592. /// <summary>
  6593. /// Make a ClassRef for this ClassDef
  6594. /// </summary>
  6595. /// <returns>ClassRef equivalent to this ClassDef</returns>
  6596. public virtual ClassRef MakeRefOf() {
  6597. if (refOf == null) {
  6598. Assembly assem = scope.GetThisAssembly();
  6599. ReferenceScope scopeRef;
  6600. if (assem != null)
  6601. scopeRef = assem.MakeRefOf();
  6602. else
  6603. scopeRef = scope.MakeRefOf();
  6604. refOf = scopeRef.GetClass(name);
  6605. if (refOf == null) {
  6606. refOf = new ClassRef(scopeRef,nameSpace,name);
  6607. scopeRef.AddToClassList(refOf);
  6608. }
  6609. refOf.defOf = this;
  6610. }
  6611. return refOf;
  6612. }
  6613. /// <summary>
  6614. /// Use a method as the implementation for another method (.override)
  6615. /// </summary>
  6616. /// <param name="decl">the method to be overridden</param>
  6617. /// <param name="body">the implementation to be used</param>
  6618. public void AddMethodOverride(Method decl, Method body) {
  6619. methodImpls.Add(new MethodImpl(this,decl,body));
  6620. }
  6621. public void AddMethodOverride(MethodImpl mImpl) {
  6622. methodImpls.Add(mImpl);
  6623. mImpl.SetOwner(this);
  6624. }
  6625. public MethodImpl[] GetMethodOverrides() {
  6626. return (MethodImpl[])methodImpls.ToArray(typeof(MethodImpl));
  6627. }
  6628. public void RemoveMethodOverride(MethodImpl mImpl) {
  6629. if (methodImpls != null)
  6630. methodImpls.Remove(mImpl);
  6631. }
  6632. /// <summary>
  6633. /// Add security to this class
  6634. /// </summary>
  6635. /// <param name="act">The security action</param>
  6636. /// <param name="permissionSet">Permission set</param>
  6637. public void AddSecurity(SecurityAction act, byte[] permissionSet) {
  6638. AddSecurity(new DeclSecurity(this,act,permissionSet));
  6639. // securityActions = permissionSet;
  6640. }
  6641. /// <summary>
  6642. /// Add security to this class
  6643. /// </summary>
  6644. /// <param name="sec">The descriptor for the security to add to this class</param>
  6645. internal void AddSecurity(DeclSecurity sec) {
  6646. flags |= HasSecurity;
  6647. if (security == null) security = new ArrayList();
  6648. security.Add(sec);
  6649. }
  6650. /// <summary>
  6651. /// Get the security descriptor associated with this class
  6652. /// </summary>
  6653. /// <returns></returns>
  6654. public DeclSecurity[] GetSecurity() {
  6655. if (security == null) return null;
  6656. return (DeclSecurity[])security.ToArray(typeof(DeclSecurity));
  6657. }
  6658. /// <summary>
  6659. /// Remove the security associated with this class
  6660. /// </summary>
  6661. public void DeleteSecurity() {
  6662. flags &= NoSecurity;
  6663. security = null;
  6664. }
  6665. //public void AddLineInfo(int row, int col) { }
  6666. /*----------------------------- internal functions ------------------------------*/
  6667. internal bool isPublic() {
  6668. uint vis = flags & VisibilityMask;
  6669. return (vis > 0) && (vis != 3) && (vis != 5);
  6670. }
  6671. internal static bool isPublic(uint flags) {
  6672. uint vis = flags & VisibilityMask;
  6673. return (vis > 0) && (vis != 3) && (vis != 5);
  6674. }
  6675. internal static bool isNested(uint flags) {
  6676. uint vis = flags & VisibilityMask;
  6677. return vis > 1;
  6678. }
  6679. internal override bool isDef() { return true; }
  6680. private Feature FindFeature(string name, ArrayList featureList) {
  6681. if (featureList == null) return null;
  6682. for (int i=0; i < featureList.Count; i++ ) {
  6683. if (((Feature)featureList[i]).Name() == name) {
  6684. return (Feature)featureList[i];
  6685. }
  6686. }
  6687. return null;
  6688. }
  6689. private int FindGenericParam(string name) {
  6690. for (int i=0; i < genericParams.Count; i++) {
  6691. GenericParam gp = (GenericParam)genericParams[i];
  6692. if (gp.GetName() == name) return i;
  6693. }
  6694. return -1;
  6695. }
  6696. internal ClassLayout Layout {
  6697. set { layout = value; }
  6698. get { return layout; }
  6699. }
  6700. internal void SetScope(PEFile mod) { scope = mod; }
  6701. internal void AddImplementedInterface(InterfaceImpl iImpl) {
  6702. interfaces.Add(iImpl);
  6703. }
  6704. internal NestedClassDef MakeNestedClass(ClassDef parent) {
  6705. NestedClassDef nClass = new NestedClassDef(parent,(TypeAttr)flags,name);
  6706. ClassDef tmp = nClass;
  6707. tmp.fieldIx = fieldIx;
  6708. tmp.fieldEndIx = fieldEndIx;
  6709. tmp.methodIx = methodIx;
  6710. tmp.methodEndIx = methodEndIx;
  6711. tmp.extendsIx = extendsIx;
  6712. tmp.Row = Row;
  6713. parent.nestedClasses.Add(nClass);
  6714. return nClass;
  6715. }
  6716. private void ReadSecurity() {
  6717. //if ((security == null) && ((flags & HasSecurity) != 0) && (buffer != null))
  6718. //security = buffer.FindParent(MDTable.DeclSecurity,this);
  6719. }
  6720. public override void MakeSpecial() {
  6721. special = true;
  6722. superType = null;
  6723. flags = (uint)TypeAttr.Private;
  6724. }
  6725. internal void AddMethodImpl(MethodImpl impl) {
  6726. methodImpls.Add(impl);
  6727. }
  6728. internal void AddEvent(Event ev) {
  6729. if (ev == null) return;
  6730. ev.SetParent(this);
  6731. events.Add(ev);
  6732. }
  6733. internal void AddProperty(Property prop) {
  6734. if (prop == null) return;
  6735. prop.SetParent(this);
  6736. properties.Add(prop);
  6737. }
  6738. internal void AddToFeatureList(ArrayList list, MDTable tabIx) {
  6739. if (tabIx == MDTable.Event) {
  6740. events.AddRange(list);
  6741. } else {
  6742. properties.AddRange(list);
  6743. }
  6744. }
  6745. // fix for Whidbey bug
  6746. internal void AddGenericsToTable(MetaDataOut md) {
  6747. //for (int i=0; i < methods.Count; i++) {
  6748. // ((MethodDef)methods[i]).AddGenericsToTable(md);
  6749. //}
  6750. for (int i=0; i < genericParams.Count; i++) {
  6751. md.AddToTable(MDTable.GenericParam,(GenericParam)genericParams[i]);
  6752. }
  6753. }
  6754. internal sealed override void BuildTables(MetaDataOut md) {
  6755. md.AddToTable(MDTable.TypeDef,this);
  6756. //if ((flags & (uint)TypeAttr.Interface) != 0) { superType = null; }
  6757. if (superType != null) {
  6758. superType.BuildMDTables(md);
  6759. if (superType is ClassSpec) md.AddToTable(MDTable.TypeSpec,superType);
  6760. }
  6761. for (int i=0; i < genericParams.Count; i++) {
  6762. ((GenericParam)genericParams[i]).BuildMDTables(md);
  6763. }
  6764. nameIx = md.AddToStringsHeap(name);
  6765. nameSpaceIx = md.AddToStringsHeap(nameSpace);
  6766. if (security != null) {
  6767. for (int i=0; i < security.Count; i++) {
  6768. ((DeclSecurity)security[i]).BuildMDTables(md);
  6769. }
  6770. }
  6771. // Console.WriteLine("Building tables for " + name);
  6772. if (layout != null) layout.BuildMDTables(md);
  6773. // Console.WriteLine("adding methods " + methods.Count);
  6774. methodIx = md.TableIndex(MDTable.Method);
  6775. for (int i=0; i < methods.Count; i++) {
  6776. ((MethodDef)methods[i]).BuildMDTables(md);
  6777. }
  6778. // Console.WriteLine("adding fields");
  6779. fieldIx = md.TableIndex(MDTable.Field);
  6780. for (int i=0; i < fields.Count; i++) {
  6781. ((FieldDef)fields[i]).BuildMDTables(md);
  6782. }
  6783. // Console.WriteLine("adding interfaceimpls and methodimpls");
  6784. if (interfaces.Count > 0) {
  6785. for (int i=0; i < interfaces.Count; i++) {
  6786. ((InterfaceImpl)interfaces[i]).BuildMDTables(md);
  6787. }
  6788. }
  6789. if (methodImpls.Count > 0) {
  6790. for (int i=0; i < methodImpls.Count; i++) {
  6791. ((MethodImpl)methodImpls[i]).BuildMDTables(md);
  6792. }
  6793. }
  6794. // Console.WriteLine("adding events and properties");
  6795. if (events.Count > 0) {
  6796. new MapElem(this,md.TableIndex(MDTable.Event),MDTable.EventMap).BuildMDTables(md);
  6797. for (int i=0; i < events.Count; i++) {
  6798. ((Event)events[i]).BuildMDTables(md);
  6799. }
  6800. }
  6801. if (properties.Count > 0) {
  6802. new MapElem(this,md.TableIndex(MDTable.Property),MDTable.PropertyMap).BuildMDTables(md);
  6803. for (int i=0; i < properties.Count; i++) {
  6804. ((Property)properties[i]).BuildMDTables(md);
  6805. }
  6806. }
  6807. // Console.WriteLine("Adding nested classes");
  6808. if (nestedClasses.Count > 0) {
  6809. for (int i=0; i < nestedClasses.Count; i++) {
  6810. ClassDef nClass = (ClassDef)nestedClasses[i];
  6811. nClass.BuildMDTables(md);
  6812. new MapElem(nClass,this,MDTable.NestedClass).BuildTables(md);
  6813. }
  6814. }
  6815. // Console.WriteLine("End of building tables");
  6816. }
  6817. internal override void BuildCILInfo(CILWriter output) {
  6818. if ((superType != null) && !(superType is ClassDef)) {
  6819. superType.BuildCILInfo(output);
  6820. }
  6821. for (int i = 0; i < genericParams.Count; i++) {
  6822. ((GenericParam)genericParams[i]).BuildCILInfo(output);
  6823. }
  6824. if (security != null) {
  6825. for (int i = 0; i < security.Count; i++) {
  6826. ((DeclSecurity)security[i]).BuildCILInfo(output);
  6827. }
  6828. }
  6829. // Console.WriteLine("Building CIL info for " + name);
  6830. // Console.WriteLine("adding methods " + methods.Count);
  6831. for (int i = 0; i < methods.Count; i++) {
  6832. ((MethodDef)methods[i]).BuildCILInfo(output);
  6833. }
  6834. // Console.WriteLine("adding fields");
  6835. for (int i = 0; i < fields.Count; i++) {
  6836. ((FieldDef)fields[i]).BuildCILInfo(output);
  6837. }
  6838. // Console.WriteLine("adding interfaceimpls and methodimpls");
  6839. if (interfaces.Count > 0) {
  6840. for (int i = 0; i < interfaces.Count; i++) {
  6841. ((InterfaceImpl)interfaces[i]).BuildCILInfo(output);
  6842. }
  6843. }
  6844. if (methodImpls.Count > 0) {
  6845. for (int i = 0; i < methodImpls.Count; i++) {
  6846. ((MethodImpl)methodImpls[i]).BuildCILInfo(output);
  6847. }
  6848. }
  6849. for (int i = 0; i < events.Count; i++) {
  6850. ((Event)events[i]).BuildCILInfo(output);
  6851. }
  6852. for (int i = 0; i < properties.Count; i++) {
  6853. ((Property)properties[i]).BuildCILInfo(output);
  6854. }
  6855. // Console.WriteLine("Adding nested classes");
  6856. for (int i = 0; i < nestedClasses.Count; i++) {
  6857. ((ClassDef)nestedClasses[i]).BuildCILInfo(output);
  6858. }
  6859. // Console.WriteLine("End of building tables");
  6860. }
  6861. internal static uint Size(MetaData md) {
  6862. return 4 + 2 * md.StringsIndexSize() +
  6863. md.CodedIndexSize(CIx.TypeDefOrRef) +
  6864. md.TableIndexSize(MDTable.Field) +
  6865. md.TableIndexSize(MDTable.Method);
  6866. }
  6867. internal sealed override void Write(PEWriter output) {
  6868. output.Write(flags);
  6869. output.StringsIndex(nameIx);
  6870. output.StringsIndex(nameSpaceIx);
  6871. //if (superType != null)
  6872. // Console.WriteLine("getting coded index for superType of " + name + " = " + superType.GetCodedIx(CIx.TypeDefOrRef));
  6873. output.WriteCodedIndex(CIx.TypeDefOrRef,superType);
  6874. output.WriteIndex(MDTable.Field,fieldIx);
  6875. output.WriteIndex(MDTable.Method,methodIx);
  6876. }
  6877. internal override void WriteType(CILWriter output) {
  6878. output.Write("class ");
  6879. WriteName(output);
  6880. }
  6881. internal override void WriteName(CILWriter output) {
  6882. if ((nameSpace == null) || (nameSpace == "")) {
  6883. output.Write(name);
  6884. } else {
  6885. output.Write(nameSpace + "." + name);
  6886. }
  6887. }
  6888. private void WriteFlags(CILWriter output) {
  6889. uint vis = flags & VisibilityMask;
  6890. switch (vis) {
  6891. case 0 : output.Write("private "); break;
  6892. case 1 : output.Write("public "); break;
  6893. case 2 : output.Write("nested public "); break;
  6894. case 3 : output.Write("nested private "); break;
  6895. case 4 : output.Write("nested family "); break;
  6896. case 5 : output.Write("nested assembly "); break;
  6897. case 6 : output.Write("nested famandassem "); break;
  6898. case 7 : output.Write("nested famorassem "); break;
  6899. }
  6900. uint layout = flags & LayoutMask;
  6901. if (layout == 0) {
  6902. output.Write("auto ");
  6903. } else if (layout == (uint)TypeAttr.ExplicitLayout) {
  6904. output.Write("explicit ");
  6905. } else {
  6906. output.Write("sequential ");
  6907. }
  6908. if ((flags & (uint)TypeAttr.Interface) != 0) {
  6909. output.Write("interface ");
  6910. }
  6911. if ((flags & (uint)TypeAttr.Abstract) != 0) {
  6912. output.Write("abstract ");
  6913. } else if ((flags & (uint)TypeAttr.Sealed) != 0) {
  6914. output.Write("sealed ");
  6915. }
  6916. uint strForm = flags & StringFormatMask;
  6917. if (strForm == 0) {
  6918. output.Write("ansi ");
  6919. } else if (strForm == (uint)TypeAttr.UnicodeClass) {
  6920. output.Write("unicode ");
  6921. } else {
  6922. output.Write("autochar ");
  6923. }
  6924. if ((flags & (uint)TypeAttr.BeforeFieldInit) != 0) {
  6925. output.Write("beforefieldinit ");
  6926. }
  6927. if ((flags & (uint)TypeAttr.Serializable) != 0) {
  6928. output.Write("serializable ");
  6929. }
  6930. if ((flags & (uint)TypeAttr.SpecialName) != 0) {
  6931. output.Write("specialname ");
  6932. }
  6933. if ((flags & (uint)TypeAttr.RTSpecialName) != 0) {
  6934. output.Write("rtsspecialname ");
  6935. }
  6936. }
  6937. internal override void Write(CILWriter output) {
  6938. output.Write(".class ");
  6939. WriteFlags(output);
  6940. if ((nameSpace != null) && (nameSpace != "")) {
  6941. output.Write(nameSpace + ".");
  6942. }
  6943. output.WriteLine(name);
  6944. if (superType != null) {
  6945. output.Write(" extends ");
  6946. superType.WriteName(output);
  6947. }
  6948. if (interfaces.Count > 0) {
  6949. output.Write(" implements ");
  6950. for (int i=0; i < interfaces.Count; i++) {
  6951. InterfaceImpl impl = (InterfaceImpl)interfaces[i];
  6952. if (i > 0) output.Write(", ");
  6953. impl.TheInterface().WriteName(output);
  6954. }
  6955. }
  6956. output.WriteLine();
  6957. output.WriteLine("{");
  6958. for (int i=0; i < fields.Count; i++) {
  6959. ((Field)fields[i]).Write(output);
  6960. output.WriteLine();
  6961. }
  6962. for (int i=0; i < methods.Count; i++) {
  6963. ((MethodDef)methods[i]).Write(output);
  6964. output.WriteLine();
  6965. }
  6966. for (int i=0; i < methodImpls.Count; i++) {
  6967. ((MethodImpl)methodImpls[i]).Write(output);
  6968. output.WriteLine();
  6969. }
  6970. for (int i=0; i < events.Count; i++) {
  6971. ((Event)events[i]).Write(output);
  6972. output.WriteLine();
  6973. }
  6974. for (int i=0; i < properties.Count; i++) {
  6975. ((Property)properties[i]).Write(output);
  6976. output.WriteLine();
  6977. }
  6978. output.WriteLine("}");
  6979. output.WriteLine();
  6980. }
  6981. internal sealed override uint TypeDefOrRefToken() {
  6982. uint cIx = Row;
  6983. cIx = cIx << 2;
  6984. return cIx;
  6985. }
  6986. internal sealed override uint GetCodedIx(CIx code) {
  6987. switch (code) {
  6988. case (CIx.TypeDefOrRef) : return 0;
  6989. case (CIx.HasCustomAttr) : return 3;
  6990. case (CIx.HasDeclSecurity) : return 0;
  6991. case (CIx.TypeOrMethodDef) : return 0;
  6992. }
  6993. return 0;
  6994. }
  6995. internal override string ClassName() {
  6996. return (nameSpace + "." + name);
  6997. }
  6998. internal override string NameString() {
  6999. string nameString = "";
  7000. if (scope != null) nameString = "[" + scope.NameString() + "]";
  7001. if ((nameSpace != null) && (nameSpace.Length > 0)) nameString += nameSpace + ".";
  7002. nameString += name;
  7003. return nameString;
  7004. }
  7005. }
  7006. /**************************************************************************/
  7007. /// <summary>
  7008. /// Descriptor for a Nested Class defined in an assembly
  7009. /// </summary>
  7010. public class NestedClassDef : ClassDef {
  7011. ClassDef parent;
  7012. /*-------------------- Constructors ---------------------------------*/
  7013. internal NestedClassDef(ClassDef parent, TypeAttr attrSet, string name)
  7014. : base(parent.GetScope(),attrSet,"",name) {
  7015. this.parent = parent;
  7016. }
  7017. /// <summary>
  7018. /// Fetch the PEFile which contains this class
  7019. /// </summary>
  7020. /// <returns>PEFile containing this class</returns>
  7021. public override PEFile GetScope() {
  7022. if (scope == null)
  7023. scope = parent.GetScope();
  7024. return scope;
  7025. }
  7026. /// <summary>
  7027. /// Get the enclosing class for this nested class
  7028. /// </summary>
  7029. /// <returns>ClassDef of the enclosing class</returns>
  7030. public ClassDef GetParentClass() { return parent; }
  7031. internal void SetParent(ClassDef par) { parent = par; }
  7032. internal override string ClassName() {
  7033. string nameString = name;
  7034. if (parent != null) nameString = parent.TypeName() + "+" + name;
  7035. return nameString;
  7036. }
  7037. /// <returns>ClassRef equivalent to this ClassDef</returns>
  7038. public override ClassRef MakeRefOf() {
  7039. if (refOf == null) {
  7040. ClassRef parentRef = parent.MakeRefOf();
  7041. refOf = parentRef.GetNestedClass(name);
  7042. if (refOf == null) {
  7043. refOf = parentRef.AddNestedClass(name);
  7044. }
  7045. refOf.defOf = this;
  7046. }
  7047. return refOf;
  7048. }
  7049. }
  7050. /**************************************************************************/
  7051. /// <summary>
  7052. /// Descriptor for a class/interface declared in another module of THIS
  7053. /// assembly, or in another assembly.
  7054. /// </summary>
  7055. public class ClassRef : ClassDesc {
  7056. protected ReferenceScope scope;
  7057. protected uint resScopeIx = 0;
  7058. internal ExternClass externClass;
  7059. internal ClassDef defOf;
  7060. internal bool readAsDef = false;
  7061. /*-------------------- Constructors ---------------------------------*/
  7062. internal ClassRef(ReferenceScope scope, string nsName, string name)
  7063. : base(nsName, name) {
  7064. this.scope = scope;
  7065. tabIx = MDTable.TypeRef;
  7066. }
  7067. internal ClassRef(uint scopeIx, string nsName, string name) : base(nsName,name) {
  7068. resScopeIx = scopeIx;
  7069. tabIx = MDTable.TypeRef;
  7070. }
  7071. internal static ClassRef ReadDef(PEReader buff, ReferenceScope resScope, uint index) {
  7072. uint junk = buff.ReadUInt32();
  7073. string cName = buff.GetString();
  7074. string nsName = buff.GetString();
  7075. ClassRef newClass = (ClassRef)resScope.GetExistingClass(nsName,cName);
  7076. if (newClass == null) {
  7077. newClass = new ClassRef(resScope,nsName,cName);
  7078. resScope.AddToClassList(newClass);
  7079. }
  7080. newClass.readAsDef = true;
  7081. newClass.Row = index;
  7082. junk = buff.GetCodedIndex(CIx.TypeDefOrRef);
  7083. newClass.fieldIx = buff.GetIndex(MDTable.Field);
  7084. newClass.methodIx = buff.GetIndex(MDTable.Method);
  7085. return newClass;
  7086. }
  7087. internal static void Read(PEReader buff, TableRow[] typeRefs, bool resolve) {
  7088. for (uint i=0; i < typeRefs.Length; i++) {
  7089. uint resScopeIx = buff.GetCodedIndex(CIx.ResolutionScope);
  7090. string name = buff.GetString();
  7091. string nameSpace = buff.GetString();
  7092. if (buff.CodedTable(CIx.ResolutionScope,resScopeIx) == MDTable.TypeRef)
  7093. typeRefs[i] = new NestedClassRef(resScopeIx,nameSpace,name);
  7094. else
  7095. typeRefs[i] = new ClassRef(resScopeIx,nameSpace,name);
  7096. typeRefs[i].Row = i+1;
  7097. }
  7098. if (resolve) {
  7099. for (int i=0; i < typeRefs.Length; i++) {
  7100. ((ClassRef)typeRefs[i]).ResolveParent(buff,false);
  7101. }
  7102. }
  7103. }
  7104. internal static ClassRef ReadClass(PEReader buff, ReferenceScope resScope) {
  7105. uint resScopeIx = buff.GetCodedIndex(CIx.ResolutionScope);
  7106. string name = buff.GetString();
  7107. string nameSpace = buff.GetString();
  7108. ClassRef newClass = (ClassRef)resScope.GetExistingClass(nameSpace,name);
  7109. if (newClass == null)
  7110. newClass = new ClassRef(resScope,nameSpace,name);
  7111. return newClass;
  7112. }
  7113. internal virtual void ResolveParent(PEReader buff, bool isExtern) {
  7114. CIx cIx = CIx.ResolutionScope;
  7115. if (isExtern) cIx = CIx.Implementation;
  7116. if (scope != null) return;
  7117. MetaDataElement parentScope = buff.GetCodedElement(cIx,resScopeIx);
  7118. if (parentScope is Module) { // special code for glitch in Everett ilasm
  7119. ClassDef newDef = new ClassDef((PEFile)parentScope,0,nameSpace,name);
  7120. ((Module)parentScope).AddToClassList(newDef);
  7121. buff.InsertInTable(MDTable.TypeRef,Row,newDef);
  7122. } else {
  7123. scope = (ReferenceScope)buff.GetCodedElement(cIx,resScopeIx);
  7124. ClassRef existing = (ClassRef)scope.GetExistingClass(nameSpace,name);
  7125. if (existing == null) {
  7126. scope.AddToClassList(this);
  7127. } else {
  7128. if (isExtern)
  7129. buff.InsertInTable(MDTable.ExportedType,Row,existing);
  7130. else
  7131. buff.InsertInTable(MDTable.TypeRef,Row,existing);
  7132. }
  7133. }
  7134. }
  7135. /*------------------------- public set and get methods --------------------------*/
  7136. /// <summary>
  7137. /// Add a method to this class
  7138. /// </summary>
  7139. /// <param name="name">method name</param>
  7140. /// <param name="retType">return type</param>
  7141. /// <param name="pars">parameter types</param>
  7142. /// <returns>a descriptor for this method</returns>
  7143. public MethodRef AddMethod(string name, Type retType, Type[] pars) {
  7144. System.Diagnostics.Debug.Assert(retType != null);
  7145. MethodRef meth = (MethodRef)GetMethodDesc(name,pars);
  7146. if (meth != null) DescriptorError(meth);
  7147. meth = new MethodRef(this,name,retType,pars);
  7148. methods.Add(meth);
  7149. return meth;
  7150. }
  7151. /// <summary>
  7152. /// Add a method to this class
  7153. /// </summary>
  7154. /// <param name="name">method name</param>
  7155. /// <param name="genPars">generic parameters</param>
  7156. /// <param name="retType">return type</param>
  7157. /// <param name="pars">parameter types</param>
  7158. /// <returns>a descriptor for this method</returns>
  7159. public MethodRef AddMethod(string name, GenericParam[] genPars, Type retType, Type[] pars) {
  7160. MethodRef meth = AddMethod(name,retType,pars);
  7161. if ((genPars != null) && (genPars.Length > 0)) {
  7162. for (int i=0; i < genPars.Length; i++) {
  7163. genPars[i].SetMethParam(meth,i);
  7164. }
  7165. meth.SetGenericParams(genPars);
  7166. }
  7167. return meth;
  7168. }
  7169. /// <summary>
  7170. /// Add a method to this class
  7171. /// </summary>
  7172. /// <param name="name">method name</param>
  7173. /// <param name="retType">return type</param>
  7174. /// <param name="pars">parameter types</param>
  7175. /// <param name="optPars">optional parameter types</param>
  7176. /// <returns>a descriptor for this method</returns>
  7177. public MethodRef AddVarArgMethod(string name, Type retType, Type[] pars, Type[] optPars) {
  7178. MethodRef meth = AddMethod(name,retType,pars);
  7179. meth.MakeVarArgMethod(null,optPars);
  7180. return meth;
  7181. }
  7182. /// <summary>
  7183. /// Add a method to this class
  7184. /// </summary>
  7185. /// <param name="name">method name</param>
  7186. /// <param name="genPars">generic parameters</param>
  7187. /// <param name="retType">return type</param>
  7188. /// <param name="pars">parameter types</param>
  7189. /// <param name="optPars">optional parameter types</param>
  7190. /// <returns>a descriptor for this method</returns>
  7191. public MethodRef AddVarArgMethod(string name, GenericParam[] genPars, Type retType, Type[] pars, Type[] optPars) {
  7192. MethodRef meth = AddMethod(name,genPars,retType,pars);
  7193. meth.MakeVarArgMethod(null,optPars);
  7194. return meth;
  7195. }
  7196. /// <summary>
  7197. /// Get the method "name" for this class
  7198. /// </summary>
  7199. /// <param name="name">The method name</param>
  7200. /// <returns>Descriptor for the method "name" for this class</returns>
  7201. public MethodRef GetMethod(string name) {
  7202. return (MethodRef)GetMethodDesc(name);
  7203. }
  7204. /// <summary>
  7205. /// Get the method "name(parTypes)" for this class
  7206. /// </summary>
  7207. /// <param name="name">Method name</param>
  7208. /// <param name="parTypes">Method signature</param>
  7209. /// <returns>Descriptor for "name(parTypes)"</returns>
  7210. public MethodRef GetMethod(string name, Type[] parTypes) {
  7211. return (MethodRef)GetMethodDesc(name,parTypes);
  7212. }
  7213. /// <summary>
  7214. /// Get the vararg method "name(parTypes,optTypes)" for this class
  7215. /// </summary>
  7216. /// <param name="name">Method name</param>
  7217. /// <param name="parTypes">Method parameter types</param>
  7218. /// <param name="optTypes">Optional parameter types</param>
  7219. /// <returns>Descriptor for "name(parTypes,optTypes)"</returns>
  7220. public MethodRef GetMethod(string name, Type[] parTypes, Type[] optTypes) {
  7221. return (MethodRef)GetMethodDesc(name,parTypes,optTypes);
  7222. }
  7223. /// <summary>
  7224. /// Get the descriptors for the all methods name "name" for this class
  7225. /// </summary>
  7226. /// <param name="name">Method name</param>
  7227. /// <returns>List of methods called "name"</returns>
  7228. public MethodRef[] GetMethods(string name) {
  7229. ArrayList meths = GetMeths(name);
  7230. return (MethodRef[])meths.ToArray(typeof(MethodRef));
  7231. }
  7232. /// <summary>
  7233. /// Get all the methods for this class
  7234. /// </summary>
  7235. /// <returns>List of methods for this class</returns>
  7236. public MethodRef[] GetMethods() {
  7237. return (MethodRef[])methods.ToArray(typeof(MethodRef));
  7238. }
  7239. /// <summary>
  7240. /// Add a field to this class
  7241. /// </summary>
  7242. /// <param name="name">field name</param>
  7243. /// <param name="fType">field type</param>
  7244. /// <returns>a descriptor for this field</returns>
  7245. public FieldRef AddField(string name, Type fType) {
  7246. FieldRef fld = (FieldRef)FindField(name);
  7247. if (fld != null) DescriptorError(fld);
  7248. fld = new FieldRef(this,name,fType);
  7249. fields.Add(fld);
  7250. return fld;
  7251. }
  7252. /// <summary>
  7253. /// Get the descriptor for the field "name" for this class
  7254. /// </summary>
  7255. /// <param name="name">Field name</param>
  7256. /// <returns>Descriptor for field "name"</returns>
  7257. public FieldRef GetField(string name) {
  7258. return (FieldRef)FindField(name);
  7259. }
  7260. /// <summary>
  7261. /// Get all the fields for this class
  7262. /// </summary>
  7263. /// <returns>List of fields for this class</returns>
  7264. public FieldRef[] GetFields() {
  7265. return (FieldRef[])fields.ToArray(typeof(FieldRef));
  7266. }
  7267. /// <summary>
  7268. /// Add a nested class to this class
  7269. /// </summary>
  7270. /// <param name="name">Nested class name</param>
  7271. /// <returns>Descriptor for the nested class "name"</returns>
  7272. public NestedClassRef AddNestedClass(string name) {
  7273. NestedClassRef nestedClass = (NestedClassRef)GetNested(name);
  7274. if (nestedClass != null) DescriptorError(nestedClass);
  7275. nestedClass = new NestedClassRef(this,name);
  7276. AddToClassList(nestedClass);
  7277. return nestedClass;
  7278. }
  7279. /// <summary>
  7280. /// Get the nested class "name"
  7281. /// </summary>
  7282. /// <param name="name">Nestec class name</param>
  7283. /// <returns>Descriptor for the nested class "name"</returns>
  7284. public NestedClassRef GetNestedClass(string name) {
  7285. // check nested names
  7286. return (NestedClassRef)GetNested(name);
  7287. }
  7288. /// <summary>
  7289. /// Make this Class exported from an Assembly (ie. add to ExportedType table)
  7290. /// </summary>
  7291. public void MakeExported() {
  7292. if ((scope == null) || (!(scope is ModuleRef)))
  7293. throw new Exception("Module not set for class to be exported");
  7294. ((ModuleRef)scope).AddToExportedClassList(this);
  7295. }
  7296. /// <summary>
  7297. /// Get the scope or "parent" of this ClassRef (either ModuleRef or AssemblyRef)
  7298. /// </summary>
  7299. /// <returns>Descriptor for the scope containing this class</returns>
  7300. public virtual ReferenceScope GetScope() {
  7301. return scope;
  7302. }
  7303. public override MetaDataElement GetParent() { return scope; }
  7304. /*----------------------------- internal functions ------------------------------*/
  7305. internal void SetExternClass(ExternClass eClass) { externClass = eClass; }
  7306. internal void SetScope(ReferenceScope scope) {
  7307. this.scope = scope;
  7308. }
  7309. internal void AddField(FieldRef fld) {
  7310. fields.Add(fld);
  7311. fld.SetParent(this);
  7312. }
  7313. internal void AddMethod(MethodRef meth) {
  7314. MethodRef m = (MethodRef)GetMethodDesc(meth.Name(),meth.GetParTypes());
  7315. if (m == null) {
  7316. methods.Add(meth);
  7317. meth.SetParent(this);
  7318. }
  7319. }
  7320. /*
  7321. internal FieldRef GetExistingField(string fName, uint tyIx, PEReader buff) {
  7322. FieldRef existing = (FieldRef)FindField(fName);
  7323. if (existing != null) {
  7324. Type fType = buff.GetBlobType(tyIx);
  7325. if (!fType.SameType(existing.GetFieldType()))
  7326. throw new DescriptorException("Cannot have two fields (" + fName +
  7327. ") for class " + name);
  7328. }
  7329. return existing;
  7330. }
  7331. */
  7332. /*
  7333. internal MethodRef CheckForMethod(string mName, uint sigIx, PEReader buff) {
  7334. int exIx = FindMeth(mName,0);
  7335. if (exIx > -1) {
  7336. MethSig mType = buff.ReadMethSig(sigIx);
  7337. mType.name = mName;
  7338. exIx = FindMeth(mType,0);
  7339. if (exIx > -1)
  7340. return (MethodRef)methods[exIx];
  7341. }
  7342. return null;
  7343. }
  7344. */
  7345. internal override string ClassName() {
  7346. string nameString = nameSpace + "." + name;
  7347. if ((scope != null) && (scope is AssemblyRef))
  7348. nameString += (", " + ((AssemblyRef)scope).AssemblyString());
  7349. return nameString;
  7350. }
  7351. internal bool HasParent(uint tok) {
  7352. return resScopeIx == tok;
  7353. }
  7354. internal override void BuildTables(MetaDataOut md) {
  7355. if (!special) {
  7356. md.AddToTable(MDTable.TypeRef,this);
  7357. nameIx = md.AddToStringsHeap(name);
  7358. nameSpaceIx = md.AddToStringsHeap(nameSpace);
  7359. }
  7360. scope.BuildMDTables(md);
  7361. }
  7362. internal override void BuildCILInfo(CILWriter output) {
  7363. if (!special && scope != null) {
  7364. output.AddRef(scope);
  7365. }
  7366. }
  7367. internal static uint Size(MetaData md) {
  7368. return md.CodedIndexSize(CIx.ResolutionScope) + 2 * md.StringsIndexSize();
  7369. }
  7370. internal override void Write(PEWriter output) {
  7371. output.WriteCodedIndex(CIx.ResolutionScope,scope);
  7372. output.StringsIndex(nameIx);
  7373. output.StringsIndex(nameSpaceIx);
  7374. }
  7375. internal override void WriteType(CILWriter output) {
  7376. if ((nameSpace == null) || (nameSpace == "")) {
  7377. output.Write("[" + scope.Name() +"]" + name);
  7378. } else {
  7379. output.Write("[" + scope.Name() +"]" + nameSpace + "." + name);
  7380. }
  7381. }
  7382. internal override sealed uint TypeDefOrRefToken() {
  7383. uint cIx = Row;
  7384. cIx = (cIx << 2) | 0x1;
  7385. return cIx;
  7386. }
  7387. internal sealed override uint GetCodedIx(CIx code) {
  7388. switch (code) {
  7389. case (CIx.TypeDefOrRef) : return 1;
  7390. case (CIx.HasCustomAttr) : return 2;
  7391. case (CIx.MemberRefParent) : return 1;
  7392. case (CIx.ResolutionScope) : return 3;
  7393. }
  7394. return 0;
  7395. }
  7396. internal override string NameString() {
  7397. string nameString = "";
  7398. if (scope != null) nameString = "[" + scope.NameString() + "]";
  7399. if ((nameSpace != null) && (nameSpace.Length > 0)) nameString += nameSpace + ".";
  7400. nameString += name;
  7401. return nameString;
  7402. }
  7403. }
  7404. /**************************************************************************/
  7405. /// <summary>
  7406. /// Descriptor for a reference to a Nested Class
  7407. /// </summary>
  7408. public class NestedClassRef : ClassRef {
  7409. ClassRef parent;
  7410. internal uint parentIx = 0;
  7411. /*-------------------- Constructors ---------------------------------*/
  7412. internal NestedClassRef(ClassRef parent, string name)
  7413. : base(parent.GetScope(),"",name) {
  7414. this.parent = parent;
  7415. }
  7416. internal NestedClassRef(uint scopeIx, string nsName, string name)
  7417. : base(scopeIx,nsName,name) {
  7418. }
  7419. internal NestedClassRef(ReferenceScope scope, string nsName, string name)
  7420. : base(scope,nsName,name) {
  7421. }
  7422. internal override void ResolveParent(PEReader buff, bool isExtern) {
  7423. if (parent != null) return;
  7424. CIx cIx = CIx.ResolutionScope;
  7425. if (isExtern) cIx = CIx.Implementation;
  7426. parent = (ClassRef)buff.GetCodedElement(cIx,resScopeIx);
  7427. parent.ResolveParent(buff,isExtern);
  7428. parent = (ClassRef)buff.GetCodedElement(cIx,resScopeIx);
  7429. if (parent == null) return;
  7430. NestedClassRef existing = parent.GetNestedClass(name);
  7431. if (existing == null) {
  7432. scope = parent.GetScope();
  7433. parent.AddToClassList(this);
  7434. } else if (isExtern)
  7435. buff.InsertInTable(MDTable.ExportedType,Row,existing);
  7436. else
  7437. buff.InsertInTable(MDTable.TypeRef,Row,existing);
  7438. }
  7439. /// <summary>
  7440. /// Get the scope of this ClassRef (either ModuleRef or AssemblyRef)
  7441. /// </summary>
  7442. /// <returns>Descriptor for the scope containing this class</returns>
  7443. public override ReferenceScope GetScope() {
  7444. if (scope == null)
  7445. scope = parent.GetScope();
  7446. return scope;
  7447. }
  7448. /// <summary>
  7449. /// Get the parent (enclosing ClassRef) for this nested class
  7450. /// </summary>
  7451. /// <returns>Enclosing class descriptor</returns>
  7452. public ClassRef GetParentClass() { return parent; }
  7453. internal void SetParent(ClassRef paren) { parent = paren; }
  7454. internal override string ClassName() {
  7455. string nameString = name;
  7456. if (parent != null) nameString = parent.TypeName() + "+" + name;
  7457. if ((scope != null) && (scope is AssemblyRef))
  7458. nameString += (", " + ((AssemblyRef)scope).AssemblyString());
  7459. return nameString;
  7460. }
  7461. internal override string NameString() {
  7462. if (parent == null) return name;
  7463. return parent.NameString() + "+" + name;
  7464. }
  7465. internal sealed override void BuildTables(MetaDataOut md) {
  7466. if (!special) {
  7467. md.AddToTable(MDTable.TypeRef,this);
  7468. nameIx = md.AddToStringsHeap(name);
  7469. nameSpaceIx = md.AddToStringsHeap(nameSpace);
  7470. }
  7471. parent.BuildMDTables(md);
  7472. }
  7473. internal sealed override void Write(PEWriter output) {
  7474. output.WriteCodedIndex(CIx.ResolutionScope,parent);
  7475. output.StringsIndex(nameIx);
  7476. output.StringsIndex(nameSpaceIx);
  7477. }
  7478. }
  7479. /**************************************************************************/
  7480. /// <summary>
  7481. /// Descriptor for a class defined in System (mscorlib)
  7482. /// </summary>
  7483. internal class SystemClass : ClassRef {
  7484. PrimitiveType elemType;
  7485. internal bool added = false;
  7486. internal SystemClass(AssemblyRef paren,PrimitiveType eType)
  7487. : base(paren,"System",eType.GetName()) {
  7488. elemType = eType;
  7489. }
  7490. // internal override sealed void AddTypeSpec(MetaDataOut md) {
  7491. // elemType.AddTypeSpec(md);
  7492. // if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
  7493. // return typeSpec;
  7494. // }
  7495. internal sealed override void TypeSig(MemoryStream str) {
  7496. str.WriteByte(elemType.GetTypeIndex());
  7497. }
  7498. internal override bool SameType(Type tstType) {
  7499. if (tstType is SystemClass)
  7500. return elemType == ((SystemClass)tstType).elemType;
  7501. return elemType == tstType;
  7502. }
  7503. }
  7504. /**************************************************************************/
  7505. /// <summary>
  7506. /// Descriptor for a custom modifier of a type (modopt or modreq)
  7507. /// </summary>
  7508. public class CustomModifiedType : Type {
  7509. Type type;
  7510. Class cmodType;
  7511. /*-------------------- Constructors ---------------------------------*/
  7512. /// <summary>
  7513. /// Create a new custom modifier for a type
  7514. /// </summary>
  7515. /// <param name="type">the type to be modified</param>
  7516. /// <param name="cmod">the modifier</param>
  7517. /// <param name="cmodType">the type reference to be associated with the type</param>
  7518. public CustomModifiedType(Type type, CustomModifier cmod, Class cmodType)
  7519. : base((byte)cmod) {
  7520. this.type = type;
  7521. this.cmodType = cmodType;
  7522. }
  7523. /*------------------------- public set and get methods --------------------------*/
  7524. public void SetModifiedType(Type modType) { type = modType; }
  7525. public Type GetModifiedType() { return type; }
  7526. public void SetModifingType(Class mod) { cmodType = mod; }
  7527. public Class GetModifingType() { return cmodType; }
  7528. public void SetModifier(CustomModifier cmod) { typeIndex = (byte) cmod; }
  7529. public CustomModifier GetModifier() { return (CustomModifier)typeIndex; }
  7530. /*----------------------------- internal functions ------------------------------*/
  7531. internal override bool SameType(Type tstType) {
  7532. if (this == tstType) return true;
  7533. if (tstType is CustomModifiedType) {
  7534. CustomModifiedType cmTstType = (CustomModifiedType)tstType;
  7535. return type.SameType(cmTstType.type) &&
  7536. cmodType.SameType(cmTstType.cmodType);
  7537. }
  7538. return false;
  7539. }
  7540. internal sealed override void TypeSig(MemoryStream str) {
  7541. str.WriteByte(typeIndex);
  7542. MetaDataOut.CompressNum(cmodType.TypeDefOrRefToken(),str);
  7543. type.TypeSig(str);
  7544. }
  7545. internal sealed override void BuildTables(MetaDataOut md) {
  7546. if (!(cmodType is ClassDef))
  7547. cmodType.BuildMDTables(md);
  7548. if (!(type is ClassDef))
  7549. type.BuildMDTables(md);
  7550. }
  7551. }
  7552. /**************************************************************************/
  7553. internal class Pinned : Type {
  7554. internal Pinned() : base((byte)ElementType.Pinned) { }
  7555. }
  7556. /**************************************************************************/
  7557. /// <summary>
  7558. /// Descriptor for the Primitive types defined in IL
  7559. /// </summary>
  7560. public class PrimitiveType : TypeSpec {
  7561. private string name;
  7562. private int systemTypeIndex;
  7563. internal static int NumSystemTypes = 18;
  7564. public static readonly PrimitiveType Void = new PrimitiveType(0x01,"Void",0);
  7565. public static readonly PrimitiveType Boolean = new PrimitiveType(0x02,"Boolean",1);
  7566. public static readonly PrimitiveType Char = new PrimitiveType(0x03,"Char",2);
  7567. public static readonly PrimitiveType Int8 = new PrimitiveType(0x04,"SByte",3);
  7568. public static readonly PrimitiveType UInt8 = new PrimitiveType(0x05,"Byte",4);
  7569. public static readonly PrimitiveType Int16 = new PrimitiveType(0x06,"Int16",5);
  7570. public static readonly PrimitiveType UInt16 = new PrimitiveType(0x07,"UInt16",6);
  7571. public static readonly PrimitiveType Int32 = new PrimitiveType(0x08,"Int32",7);
  7572. public static readonly PrimitiveType UInt32 = new PrimitiveType(0x09,"UInt32",8);
  7573. public static readonly PrimitiveType Int64 = new PrimitiveType(0x0A,"Int64",9);
  7574. public static readonly PrimitiveType UInt64 = new PrimitiveType(0x0B,"UInt64",10);
  7575. public static readonly PrimitiveType Float32 = new PrimitiveType(0x0C,"Single",11);
  7576. public static readonly PrimitiveType Float64 = new PrimitiveType(0x0D,"Double",12);
  7577. public static readonly PrimitiveType String = new PrimitiveType(0x0E,"String",13);
  7578. internal static readonly PrimitiveType Class = new PrimitiveType(0x12);
  7579. public static readonly PrimitiveType TypedRef = new PrimitiveType(0x16,"TypedReference",14);
  7580. public static readonly PrimitiveType IntPtr = new PrimitiveType(0x18,"IntPtr",15);
  7581. public static readonly PrimitiveType UIntPtr = new PrimitiveType(0x19,"UIntPtr",16);
  7582. public static readonly PrimitiveType Object = new PrimitiveType(0x1C,"Object",17);
  7583. internal static readonly PrimitiveType ClassType = new PrimitiveType(0x50);
  7584. internal static readonly PrimitiveType SZArray = new PrimitiveType(0x1D);
  7585. public static readonly PrimitiveType NativeInt = IntPtr;
  7586. public static readonly PrimitiveType NativeUInt = UIntPtr;
  7587. internal static PrimitiveType[] primitives = {null,Void,Boolean,Char,Int8,UInt8,
  7588. Int16,UInt16,Int32,UInt32,Int64,
  7589. UInt64,Float32,Float64,String};
  7590. /*-------------------- Constructors ---------------------------------*/
  7591. internal PrimitiveType(byte typeIx) : base(typeIx) { }
  7592. internal PrimitiveType(byte typeIx, string name, int STIx) : base(typeIx) {
  7593. this.name = name;
  7594. this.systemTypeIndex = STIx;
  7595. }
  7596. internal string GetName() { return name; }
  7597. public override string TypeName() {
  7598. if (typeIndex == 0x0E) return "System.String";
  7599. return name;
  7600. }
  7601. internal int GetSystemTypeIx() { return systemTypeIndex; }
  7602. internal sealed override void TypeSig(MemoryStream str) {
  7603. str.WriteByte(typeIndex);
  7604. }
  7605. internal override void WriteType(CILWriter output) {
  7606. //if (typeIndex == 0x0E) {
  7607. // output.Write("[mscorlib]System.String");
  7608. //} else
  7609. switch (typeIndex) {
  7610. case (0x1C) : output.Write("[mscorlib]System.Object"); break;
  7611. case (0x02) : output.Write("bool"); break;
  7612. case (0x0C) : output.Write("float32"); break;
  7613. case (0x0D) : output.Write("float64"); break;
  7614. default : output.Write(name.ToLower()); break;
  7615. }
  7616. }
  7617. internal sealed override bool SameType(Type tstType) {
  7618. if (tstType is SystemClass)
  7619. return tstType.SameType(this);
  7620. return this == tstType;
  7621. }
  7622. /* now done in MetaDataOut.WriteTildeStream
  7623. internal static void ClearAddedFlags() { // KJG 18-April-2005
  7624. for (int i = 0; i < primitives.Length; i++) {
  7625. if (primitives[i] != null) primitives[i].typeSpecAdded = false;
  7626. }
  7627. }
  7628. */
  7629. }
  7630. /**************************************************************************/
  7631. internal class Sentinel : Type {
  7632. internal Sentinel() : base((byte)ElementType.Sentinel) { }
  7633. }
  7634. /**************************************************************************/
  7635. public abstract class TypeSpec : Type {
  7636. uint sigIx = 0;
  7637. internal bool typeSpecAdded = false; // so that MetaDataOut can reset it
  7638. /*-------------------- Constructors ---------------------------------*/
  7639. internal TypeSpec(byte typeIx) : base(typeIx) {
  7640. tabIx = MDTable.TypeSpec;
  7641. }
  7642. internal static void Read(PEReader buff, TableRow[] specs) {
  7643. for (int i=0; i < specs.Length; i++) {
  7644. specs[i] = new UnresolvedTypeSpec(buff,i);
  7645. //specs[i] = buff.GetBlobType(null,null,buff.GetBlobIx());
  7646. //if (specs[i] is GenericParam) {
  7647. // Console.WriteLine("GenericParam in TypeSpec table at pos " + i);
  7648. //}
  7649. }
  7650. }
  7651. internal override sealed Type AddTypeSpec(MetaDataOut md) {
  7652. if (typeSpecAdded) return this;
  7653. md.AddToTable(MDTable.TypeSpec,this);
  7654. BuildMDTables(md);
  7655. typeSpecAdded = true;
  7656. return this;
  7657. }
  7658. internal override void BuildSignatures(MetaDataOut md) {
  7659. MemoryStream str = new MemoryStream();
  7660. TypeSig(str);
  7661. sigIx = md.AddToBlobHeap(str.ToArray());
  7662. done = false;
  7663. }
  7664. internal static uint Size(MetaData md) {
  7665. return md.BlobIndexSize();
  7666. }
  7667. internal sealed override void Write(PEWriter output) {
  7668. //Console.WriteLine("Writing the blob index for a TypeSpec");
  7669. output.BlobIndex(sigIx);
  7670. }
  7671. internal sealed override uint GetCodedIx(CIx code) {
  7672. switch (code) {
  7673. case (CIx.TypeDefOrRef) : return 2;
  7674. case (CIx.HasCustomAttr) : return 13;
  7675. case (CIx.MemberRefParent) : return 4;
  7676. }
  7677. return 0;
  7678. }
  7679. }
  7680. /**************************************************************************/
  7681. internal class UnresolvedTypeSpec : TypeSpec {
  7682. uint blobIx;
  7683. internal UnresolvedTypeSpec(PEReader buff,int i) : base(0) {
  7684. blobIx = buff.GetBlobIx();
  7685. Row = (uint)i+1;
  7686. this.unresolved = true;
  7687. }
  7688. internal override void Resolve(PEReader buff) {
  7689. buff.InsertInTable(MDTable.TypeSpec,Row,buff.GetBlobType(blobIx));
  7690. this.unresolved = false;
  7691. }
  7692. }
  7693. /**************************************************************************/
  7694. /// <summary>
  7695. ///
  7696. /// </summary>
  7697. public class GenericParTypeSpec : TypeSpec {
  7698. GenericParam gPar;
  7699. bool isClassPar;
  7700. uint index;
  7701. internal GenericParTypeSpec(GenericParam gPar) : base(gPar.GetTypeIndex()) {
  7702. this.gPar = gPar;
  7703. }
  7704. internal GenericParTypeSpec(int gpTypeIx, uint ix) : base((byte)gpTypeIx) {
  7705. isClassPar = gpTypeIx == (int)ElementType.Var;
  7706. index = ix;
  7707. }
  7708. internal GenericParam GetGenericParam(MethodDef meth) {
  7709. if (gPar == null) {
  7710. if (isClassPar) {
  7711. ClassDef methClass = (ClassDef)meth.GetParent();
  7712. gPar = methClass.GetGenericParam((int)index);
  7713. } else {
  7714. gPar = meth.GetGenericParam((int)index);
  7715. }
  7716. }
  7717. return gPar;
  7718. }
  7719. internal override void TypeSig(MemoryStream str) {
  7720. gPar.TypeSig(str);
  7721. }
  7722. }
  7723. /**************************************************************************/
  7724. /// <summary>
  7725. /// The IL Array type
  7726. /// </summary>
  7727. public abstract class Array : TypeSpec {
  7728. /// <summary>
  7729. /// The element type of the array
  7730. /// </summary>
  7731. protected Type elemType;
  7732. /*-------------------- Constructors ---------------------------------*/
  7733. internal Array(Type eType, byte TypeId) : base(TypeId) {
  7734. elemType = eType;
  7735. tabIx = MDTable.TypeSpec;
  7736. }
  7737. public Type ElemType() { return elemType; }
  7738. internal sealed override void BuildTables(MetaDataOut md) {
  7739. if (!(elemType is ClassDef))
  7740. elemType.BuildMDTables(md);
  7741. }
  7742. internal sealed override void BuildCILInfo(CILWriter output) {
  7743. if (!(elemType is ClassDef))
  7744. elemType.BuildCILInfo(output);
  7745. }
  7746. }
  7747. /**************************************************************************/
  7748. /// <summary>
  7749. /// Multi dimensional array with explicit bounds
  7750. /// </summary>
  7751. public class BoundArray : Array {
  7752. int[] lowerBounds;
  7753. int[] sizes;
  7754. uint numDims;
  7755. /*-------------------- Constructors ---------------------------------*/
  7756. /// <summary>
  7757. /// Create a new multi dimensional array type
  7758. /// eg. elemType[1..5,3..10,5,,] would be
  7759. /// new BoundArray(elemType,5,[1,3,0],[5,10,4])
  7760. /// </summary>
  7761. /// <param name="elementType">the type of the elements</param>
  7762. /// <param name="dimensions">the number of dimensions</param>
  7763. /// <param name="loBounds">lower bounds of dimensions</param>
  7764. /// <param name="upBounds">upper bounds of dimensions</param>
  7765. public BoundArray(Type elementType, int dimensions, int[] loBounds,
  7766. int[] upBounds) : base (elementType,0x14) {
  7767. numDims = (uint)dimensions;
  7768. lowerBounds = loBounds;
  7769. if (upBounds != null) {
  7770. sizes = new int[upBounds.Length];
  7771. for (int i=0; i < upBounds.Length; i++) {
  7772. sizes[i] = upBounds[i] - loBounds[i] + 1;
  7773. }
  7774. }
  7775. }
  7776. /// <summary>
  7777. /// Create a new multi dimensional array type
  7778. /// eg. elemType[5,10,20] would be new BoundArray(elemType,3,[5,10,20])
  7779. /// </summary>
  7780. /// <param name="elementType">the type of the elements</param>
  7781. /// <param name="dimensions">the number of dimensions</param>
  7782. /// <param name="size">the sizes of the dimensions</param>
  7783. public BoundArray(Type elementType, int dimensions, int[] size)
  7784. : base (elementType,0x14) {
  7785. numDims = (uint)dimensions;
  7786. sizes = size;
  7787. }
  7788. /// <summary>
  7789. /// Create a new multi dimensional array type
  7790. /// eg. elemType[,,] would be new BoundArray(elemType,3)
  7791. /// </summary>
  7792. /// <param name="elementType">the type of the elements</param>
  7793. /// <param name="dimensions">the number of dimensions</param>
  7794. public BoundArray(Type elementType, int dimensions)
  7795. : base (elementType,0x14) {
  7796. numDims = (uint)dimensions;
  7797. }
  7798. internal override bool SameType(Type tstType) {
  7799. if (this == tstType) return true;
  7800. if (!(tstType is BoundArray)) return false;
  7801. BoundArray bArray = (BoundArray)tstType;
  7802. if (elemType.SameType(bArray.ElemType()))
  7803. return SameBounds(numDims,lowerBounds,sizes);
  7804. return false;
  7805. }
  7806. internal bool SameBounds(uint dims, int[] lbounds, int[] sizs) {
  7807. if (dims != numDims) return false;
  7808. if (lowerBounds != null) {
  7809. if ((lbounds == null) || (lowerBounds.Length != lbounds.Length)) return false;
  7810. for (int i=0; i < lowerBounds.Length; i++)
  7811. if (lowerBounds[i] != lbounds[i]) return false;
  7812. } else
  7813. if (lbounds != null) return false;
  7814. if (sizes != null) {
  7815. if ((sizs == null) || (sizes.Length != sizs.Length)) return false;
  7816. for (int i=0; i < sizes.Length; i++)
  7817. if (sizes[i] != sizs[i]) return false;
  7818. } else
  7819. if (sizs != null) return false;
  7820. return true;
  7821. }
  7822. internal sealed override void TypeSig(MemoryStream str) {
  7823. str.WriteByte(typeIndex);
  7824. elemType.TypeSig(str);
  7825. MetaDataOut.CompressNum(numDims,str);
  7826. if ((sizes != null) && (sizes.Length > 0)) {
  7827. MetaDataOut.CompressNum((uint)sizes.Length,str);
  7828. for (int i=0; i < sizes.Length; i++) {
  7829. MetaDataOut.CompressNum((uint)sizes[i],str);
  7830. }
  7831. } else str.WriteByte(0);
  7832. if ((lowerBounds != null) && (lowerBounds.Length > 0)) {
  7833. MetaDataOut.CompressNum((uint)lowerBounds.Length,str);
  7834. for (int i=0; i < lowerBounds.Length; i++) {
  7835. uint tmp = ((uint)Math.Abs(lowerBounds[i]) << 1) | ((uint)lowerBounds[i] >> 31);
  7836. MetaDataOut.CompressNum(tmp,str);
  7837. }
  7838. } else str.WriteByte(0);
  7839. }
  7840. }
  7841. /**************************************************************************/
  7842. /// <summary>
  7843. /// Single dimensional array with zero lower bound
  7844. /// </summary>
  7845. public class ZeroBasedArray : Array {
  7846. /*-------------------- Constructors ---------------------------------*/
  7847. /// <summary>
  7848. /// Create a new array - elementType[]
  7849. /// </summary>
  7850. /// <param name="elementType">the type of the array elements</param>
  7851. public ZeroBasedArray(Type elementType) : base (elementType,(byte)ElementType.SZArray) { }
  7852. internal sealed override void TypeSig(MemoryStream str) {
  7853. str.WriteByte(typeIndex);
  7854. elemType.TypeSig(str);
  7855. }
  7856. internal override bool SameType(Type tstType) {
  7857. if (this == tstType) return true;
  7858. if (!(tstType is ZeroBasedArray)) return false;
  7859. //return elemType == ((ZeroBasedArray)tstType).ElemType();
  7860. return elemType.SameType(((ZeroBasedArray)tstType).ElemType());
  7861. }
  7862. internal override void WriteType(CILWriter output) {
  7863. elemType.WriteType(output);
  7864. output.Write("[]");
  7865. }
  7866. }
  7867. /**************************************************************************/
  7868. /// <summary>
  7869. /// Descriptor for a FunctionPointer type
  7870. /// </summary>
  7871. ///
  7872. public class MethPtrType : TypeSpec {
  7873. // MethPtrType == FNPTR
  7874. Method meth;
  7875. MethSig mSig;
  7876. /*-------------------- Constructors ---------------------------------*/
  7877. /// <summary>
  7878. /// Create a new function pointer type
  7879. /// </summary>
  7880. /// <param name="meth">the function to be referenced</param>
  7881. public MethPtrType(Method meth) : base((byte)ElementType.FnPtr) {
  7882. this.meth = meth;
  7883. }
  7884. internal MethPtrType(MethSig msig) : base((byte)ElementType.FnPtr) {
  7885. mSig = msig;
  7886. }
  7887. internal sealed override void TypeSig(MemoryStream str) {
  7888. str.WriteByte(typeIndex);
  7889. if (meth == null)
  7890. mSig.TypeSig(str);
  7891. else
  7892. meth.TypeSig(str);
  7893. }
  7894. internal override bool SameType(Type tstType) {
  7895. if (this == tstType) return true;
  7896. if (tstType is MethPtrType) {
  7897. MethPtrType mpType = (MethPtrType)tstType;
  7898. }
  7899. return false;
  7900. }
  7901. internal sealed override void BuildTables(MetaDataOut md) {
  7902. Type[] types = meth.GetParTypes();
  7903. if (types != null)
  7904. for (int i=0; i < types.Length; i++)
  7905. types[i].BuildMDTables(md);
  7906. types = meth.GetOptParTypes();
  7907. if (types != null)
  7908. for (int i=0; i < types.Length; i++)
  7909. types[i].BuildMDTables(md);
  7910. }
  7911. internal sealed override void BuildCILInfo(CILWriter output) {
  7912. Type[] types = meth.GetParTypes();
  7913. if (types != null)
  7914. for (int i = 0; i < types.Length; i++)
  7915. types[i].BuildCILInfo(output);
  7916. types = meth.GetOptParTypes();
  7917. if (types != null)
  7918. for (int i = 0; i < types.Length; i++)
  7919. types[i].BuildCILInfo(output);
  7920. }
  7921. /* internal sealed override void BuildSignatures(MetaDataOut md) {
  7922. if (sigIx == 0) {
  7923. MemoryStream sig = new MemoryStream();
  7924. TypeSig(sig);
  7925. sigIx = md.AddToBlobHeap(sig.ToArray());
  7926. }
  7927. done = false;
  7928. }
  7929. */
  7930. }
  7931. /**************************************************************************/
  7932. /// <summary>
  7933. /// Descriptor for an pointer (type * or type &)
  7934. /// </summary>
  7935. public abstract class PtrType : TypeSpec {
  7936. protected Type baseType;
  7937. /*-------------------- Constructors ---------------------------------*/
  7938. internal PtrType(Type bType, byte typeIx) : base(typeIx) {
  7939. baseType = bType;
  7940. }
  7941. public Type GetBaseType() { return baseType; }
  7942. internal sealed override void TypeSig(MemoryStream str) {
  7943. str.WriteByte(typeIndex);
  7944. baseType.TypeSig(str);
  7945. }
  7946. internal sealed override void BuildTables(MetaDataOut md) {
  7947. if (!(baseType is ClassDef))
  7948. baseType.BuildMDTables(md);
  7949. }
  7950. internal sealed override void BuildCILInfo(CILWriter output) {
  7951. if (!(baseType is ClassDef))
  7952. baseType.BuildCILInfo(output);
  7953. }
  7954. }
  7955. /**************************************************************************/
  7956. /// <summary>
  7957. /// Descriptor for a managed pointer (type & or byref)
  7958. /// </summary>
  7959. public class ManagedPointer : PtrType { // <type> & (BYREF)
  7960. /*-------------------- Constructors ---------------------------------*/
  7961. /// <summary>
  7962. /// Create new managed pointer to baseType
  7963. /// </summary>
  7964. /// <param name="bType">the base type of the pointer</param>
  7965. public ManagedPointer(Type baseType) : base(baseType,0x10) { }
  7966. }
  7967. /**************************************************************************/
  7968. /// <summary>
  7969. /// Descriptor for an unmanaged pointer (type *)
  7970. /// </summary>
  7971. public class UnmanagedPointer : PtrType { // PTR
  7972. /*-------------------- Constructors ---------------------------------*/
  7973. /// <summary>
  7974. /// Create a new unmanaged pointer to baseType
  7975. /// </summary>
  7976. /// <param name="baseType">the base type of the pointer</param>
  7977. public UnmanagedPointer(Type baseType) : base(baseType, 0x0F) { }
  7978. }
  7979. /**************************************************************************/
  7980. // Classes to represent CIL Byte Codes
  7981. /**************************************************************************/
  7982. /// <summary>
  7983. /// The IL instructions for a method
  7984. /// </summary>
  7985. public class CILInstructions {
  7986. private static readonly uint MaxClauses = 10;
  7987. private static readonly uint ExHeaderSize = 4;
  7988. private static readonly uint FatExClauseSize = 24;
  7989. private static readonly uint SmlExClauseSize = 12;
  7990. private static readonly sbyte maxByteVal = 127;
  7991. private static readonly sbyte minByteVal = -128;
  7992. private static readonly byte maxUByteVal = 255;
  7993. private static readonly int smallSize = 64;
  7994. internal static readonly ushort TinyFormat = 0x2;
  7995. internal static readonly ushort FatFormat = 0x03;
  7996. internal static readonly ushort FatFormatHeader = 0x3003;
  7997. internal static readonly ushort MoreSects = 0x8;
  7998. internal static readonly ushort InitLocals = 0x10;
  7999. private static readonly uint FatSize = 12;
  8000. private static readonly uint FatWords = FatSize/4;
  8001. internal static readonly byte FatExceptTable = 0x41;
  8002. internal static readonly byte SmlExceptTable = 0x01;
  8003. internal static readonly uint EHTable = 0x1;
  8004. internal static readonly uint SectFatFormat = 0x40;
  8005. internal static readonly uint SectMoreSects = 0x80;
  8006. private ArrayList exceptions, sourceLines, defaultLines;
  8007. private SourceFile defaultSourceFile;
  8008. // Made public for FCodeEmit
  8009. public Stack blockStack;
  8010. //private bool codeChecked = false;
  8011. private static readonly int INITSIZE = 5;
  8012. private CILInstruction[] buffer = new CILInstruction[INITSIZE];
  8013. // REPLACE with ArrayList<CILInstruction> for next version of .NET
  8014. private CILInstruction[] saveBuffer;
  8015. private int tide = 0, saveTide = 0;
  8016. private uint offset = 0;
  8017. private ushort headerFlags = 0;
  8018. private short maxStack;
  8019. private uint paddingNeeded = 0;
  8020. private byte exceptHeader = 0;
  8021. private int currI = -1;
  8022. uint localSigIx = 0;
  8023. int numReplace = 0;
  8024. uint codeSize = 0, exceptSize = 0;
  8025. bool tinyFormat, fatExceptionFormat = false, inserting=false;
  8026. MethodDef thisMeth;
  8027. internal Scope currentScope;
  8028. /// <summary>
  8029. /// Shows if return statements in this code block require a value on the stack or not.
  8030. /// </summary>
  8031. internal bool ReturnsVoid;
  8032. /*-------------------- Constructors ---------------------------------*/
  8033. internal CILInstructions(MethodDef meth) {
  8034. thisMeth = meth;
  8035. }
  8036. /*--------------------- public general editing methods ---------------------------*/
  8037. /// <summary>
  8038. /// The source file containing these IL instructions
  8039. /// </summary>
  8040. public SourceFile DefaultSourceFile {
  8041. get { return defaultSourceFile; }
  8042. set { defaultSourceFile = value; }
  8043. }
  8044. /// <summary>
  8045. /// The number of instructions currently in the buffer.
  8046. /// </summary>
  8047. public int NumInstructions() {
  8048. if (inserting) return tide + saveTide;
  8049. return tide;
  8050. }
  8051. /// <summary>
  8052. /// Get the next instruction in the instruction buffer in sequence.
  8053. /// An internal index is kept to keep track of which instruction was the last
  8054. /// retrieved by this method. On the first call, the first instruction in
  8055. /// the buffer is retrieved. The instruction index may be zeroed
  8056. /// using ResetInstCounter(). This method cannot be called when in "insert" mode.
  8057. /// </summary>
  8058. /// <returns></returns>
  8059. public CILInstruction GetNextInstruction() {
  8060. if (inserting) throw new Exception("Cannot access next instruction during insert");
  8061. if (currI+1 < tide)
  8062. return buffer[++currI];
  8063. return null;
  8064. }
  8065. /// <summary>
  8066. /// Get the previous instruction in the instruction buffer in sequence.
  8067. /// An internal index is kept to keep track of which instruction was the last
  8068. /// retrieved by this method. This method cannot be called when in "insert" mode.
  8069. /// </summary>
  8070. /// <returns></returns>
  8071. public CILInstruction GetPrevInstruction() {
  8072. if (inserting) throw new Exception("Cannot access previous instruction during insert");
  8073. if (currI > 0)
  8074. return buffer[--currI];
  8075. return null;
  8076. }
  8077. /// <summary>
  8078. /// Reset the counter for GetNextInstuction to the first instruction.
  8079. /// This method cannot be called when in "insert" mode.
  8080. /// </summary>
  8081. public void ResetInstCounter() {
  8082. if (inserting) throw new Exception("Cannot reset instruction counter during insert");
  8083. currI = -1;
  8084. }
  8085. /// <summary>
  8086. /// Reset the counter for GetNextInstuction to the first instruction.
  8087. /// This method cannot be called when in "insert" mode.
  8088. /// </summary>
  8089. public void EndInstCounter() {
  8090. if (inserting) throw new Exception("Cannot reset instruction counter during insert");
  8091. currI = tide;
  8092. }
  8093. /// <summary>
  8094. /// Get all the IL instructions.
  8095. /// This method cannot be called when in "insert" mode.
  8096. /// </summary>
  8097. /// <returns></returns>
  8098. public CILInstruction[] GetInstructions() {
  8099. if (inserting) throw new Exception("Cannot get instructions during insert");
  8100. return buffer;
  8101. }
  8102. /// <summary>
  8103. /// Set the instruction to be the new array of instructions, this will replace
  8104. /// any existing instructions. This method cannot be called when in "insert" mode.
  8105. /// </summary>
  8106. /// <param name="insts">The new instructions</param>
  8107. public void SetInstructions(CILInstruction[] insts) {
  8108. if (inserting) throw new Exception("Cannot replace instructions during insert.");
  8109. buffer = insts;
  8110. tide = buffer.Length;
  8111. for (int i=0; i < tide; i++) {
  8112. if (insts[i] == null)
  8113. tide = i;
  8114. insts[i].index = (uint)i;
  8115. }
  8116. }
  8117. /// <summary>
  8118. /// This method should only be used to insert instructions into a buffer which
  8119. /// already contains some instructions.
  8120. /// Start inserting instructions into the instruction buffer ie. set the buffer
  8121. /// to "insert" mode. The position of the insertion will be directly after
  8122. /// the "current instruction" as used be GetNextInstruction(). The
  8123. /// instructions to be inserted are any calls to the instruction specific
  8124. /// methods - Inst, TypeInst, MethodInst, etc.
  8125. /// This method cannot be called if already in "insert" mode.
  8126. /// </summary>
  8127. public void StartInsert() {
  8128. if (inserting)
  8129. throw new Exception("Cannot insert into an instruction buffer already in insert mode");
  8130. inserting = true;
  8131. saveTide = tide;
  8132. saveBuffer = buffer;
  8133. tide = 0;
  8134. buffer = new CILInstruction[INITSIZE];
  8135. }
  8136. /// <summary>
  8137. /// Stop inserting instructions into the buffer. Any instructions added after
  8138. /// this call will go at the end of the instruction buffer.
  8139. /// To be used with StartInsert().
  8140. /// This method cannot be called if not in "insert" mode.
  8141. /// </summary>
  8142. public void EndInsert() {
  8143. if (!inserting)
  8144. throw new Exception("Cannot stop inserting if not in insert mode");
  8145. CILInstruction[] newInsts = buffer;
  8146. buffer = saveBuffer;
  8147. int numNew = tide;
  8148. tide = saveTide;
  8149. int insPos = currI+1;
  8150. if (numReplace > 0) insPos--;
  8151. InsertInstructions(insPos,newInsts,numNew);
  8152. inserting = false;
  8153. numReplace = 0;
  8154. }
  8155. /// <summary>
  8156. /// Check if the buffer is ready for insertion of extra instructions.
  8157. /// The buffer only needs to be in insert mode when instructions need
  8158. /// to be added to existing instructions, not for addition of instructions
  8159. /// to the end of the buffer.
  8160. /// </summary>
  8161. /// <returns></returns>
  8162. public bool InInsertMode() { return inserting; }
  8163. /// <summary>
  8164. /// Remove the instruction at a specified position from the buffer. If you
  8165. /// remove the "current" instruction (from GetNext or GetPrev) then the
  8166. /// "current" instruction becomes the instruction before that in the buffer.
  8167. /// </summary>
  8168. /// <param name="pos">position of the instruction to be removed</param>
  8169. public void RemoveInstruction(int pos) {
  8170. if (pos < 0) return;
  8171. for (int i=pos; i < tide-1; i++) {
  8172. buffer[i] = buffer[i+1];
  8173. buffer[i].index = (uint)i;
  8174. }
  8175. tide--;
  8176. if (pos == currI) currI = pos-1;
  8177. }
  8178. /// <summary>
  8179. /// Remove the instructions from position "startRange" to (and including)
  8180. /// position "endRange" from the buffer. If the range removed contains the
  8181. /// "current" instruction (from GetNext or GetPrev) then the "current"
  8182. /// instruction becomes the instruction before startRange in the buffer.
  8183. /// </summary>
  8184. public void RemoveInstructions(int startRange, int endRange) {
  8185. if (startRange < 0) startRange = 0;
  8186. if (endRange >= tide-1) {// cut to startRange
  8187. tide = startRange;
  8188. return;
  8189. }
  8190. int offset = endRange-startRange+1;
  8191. for (int i=endRange+1; i < tide; i++) {
  8192. buffer[i-offset] = buffer[i];
  8193. buffer[i-offset].index = (uint)(i-offset);
  8194. }
  8195. tide -= offset;
  8196. if ((currI >= startRange) && (currI <= endRange)) currI = startRange-1;
  8197. }
  8198. /// <summary>
  8199. /// Replace a single IL instruction at position pos in the buffer
  8200. /// with some new instruction(s). This removes the instruction and puts
  8201. /// the instruction buffer into "insert" mode at the position of the removed
  8202. /// instruction. EndInsert must be called to insert the new instructions.
  8203. /// This method cannot be called when in "insert" mode.
  8204. /// </summary>
  8205. /// <param name="pos">position of the instruction to be replaced</param>
  8206. public void ReplaceInstruction(int pos) {
  8207. if (inserting) throw new Exception("Cannot replace instructions during insert.");
  8208. currI = pos;
  8209. if ((pos > 0) || (pos < tide)) {
  8210. numReplace = 1;
  8211. StartInsert();
  8212. }
  8213. }
  8214. /// <summary>
  8215. /// Replace a number of IL instructions beginning at position pos in the buffer
  8216. /// with some new instruction(s). This removes the instructions and puts
  8217. /// the instruction buffer into "insert" mode at the position of the removed
  8218. /// instructions. EndInsert must be called to insert the new instructions.
  8219. /// The instructions from index "from" up to and including index "to" will
  8220. /// be replaced by the new instructions entered.
  8221. /// This method cannot be called when in "insert" mode.
  8222. /// </summary>
  8223. /// <param name="from">the index to start replacing instruction from</param>
  8224. /// <param name="to">the last index of the instructions to be replaced</param>
  8225. public void ReplaceInstruction(int from, int to) {
  8226. if (inserting) throw new Exception("Cannot replace instructions during insert.");
  8227. currI = from;
  8228. if ((from < 0) || (from >= tide) || (to < 0))
  8229. throw new Exception("replace index is out of range");
  8230. if (to >=tide) to = tide-1;
  8231. numReplace = to - from + 1;
  8232. StartInsert();
  8233. }
  8234. /*---------------- public instruction specific methods ------------------------*/
  8235. /// <summary>
  8236. /// Add a simple IL instruction
  8237. /// </summary>
  8238. /// <param name="inst">the IL instruction</param>
  8239. public void Inst(Op inst) {
  8240. AddToBuffer(new Instr(inst));
  8241. }
  8242. /// <summary>
  8243. /// Add an IL instruction with an integer parameter
  8244. /// </summary>
  8245. /// <param name="inst">the IL instruction</param>
  8246. /// <param name="val">the integer parameter value</param>
  8247. public void IntInst(IntOp inst, int val) {
  8248. if ((inst == IntOp.ldc_i4_s) || (inst == IntOp.ldc_i4)) {
  8249. if ((val < 9) && (val >= -1)) {
  8250. AddToBuffer(new Instr((Op)((int)Op.ldc_i4_0 + val)));
  8251. } else {
  8252. AddToBuffer(new IntInstr(inst, val));
  8253. }
  8254. } else
  8255. AddToBuffer(new UIntInstr(inst,(uint)val));
  8256. }
  8257. /// <summary>
  8258. /// Add the load long instruction
  8259. /// </summary>
  8260. /// <param name="cVal">the long value</param>
  8261. public void ldc_i8(long cVal) {
  8262. AddToBuffer(new LongInstr(SpecialOp.ldc_i8,cVal));
  8263. }
  8264. /// <summary>
  8265. /// Add the load float32 instruction
  8266. /// </summary>
  8267. /// <param name="cVal">the float value</param>
  8268. public void ldc_r4(float cVal) {
  8269. AddToBuffer(new FloatInstr(SpecialOp.ldc_r4,cVal));
  8270. }
  8271. /// <summary>
  8272. /// Add the load float64 instruction
  8273. /// </summary>
  8274. /// <param name="cVal">the float value</param>
  8275. public void ldc_r8(double cVal) {
  8276. AddToBuffer(new DoubleInstr(SpecialOp.ldc_r8,cVal));
  8277. }
  8278. /// <summary>
  8279. /// Add the load string instruction
  8280. /// </summary>
  8281. /// <param name="str">the string value</param>
  8282. public void ldstr(string str) {
  8283. AddToBuffer(new StringInstr(SpecialOp.ldstr,str));
  8284. }
  8285. /// <summary>
  8286. /// Add the calli instruction
  8287. /// </summary>
  8288. /// <param name="sig">the signature for the calli</param>
  8289. public void calli(CalliSig sig) {
  8290. AddToBuffer(new SigInstr(SpecialOp.calli,sig));
  8291. }
  8292. /// <summary>
  8293. /// Create a new CIL label. To place the label in the CIL instruction
  8294. /// stream use CodeLabel.
  8295. /// </summary>
  8296. /// <returns>a new CIL label</returns>
  8297. public CILLabel NewLabel() {
  8298. return new CILLabel();
  8299. }
  8300. /// <summary>
  8301. /// Create a new label at this position in the code buffer
  8302. /// </summary>
  8303. /// <returns>the label at the current position</returns>
  8304. public CILLabel NewCodedLabel() {
  8305. CILLabel lab = new CILLabel();
  8306. lab.Buffer = this;
  8307. AddToBuffer(lab);
  8308. return lab;
  8309. }
  8310. /// <summary>
  8311. /// Add a label to the CIL instructions
  8312. /// </summary>
  8313. /// <param name="lab">the label to be added</param>
  8314. public void CodeLabel(CILLabel lab) {
  8315. if (lab.Buffer == null) {
  8316. lab.Buffer = this;
  8317. } else if (lab.Buffer != this) {
  8318. throw new DescriptorException("Cannot add a label to two different code buffers");
  8319. }
  8320. AddToBuffer(lab);
  8321. }
  8322. /// <summary>
  8323. /// Add an instruction with a field parameter
  8324. /// </summary>
  8325. /// <param name="inst">the CIL instruction</param>
  8326. /// <param name="f">the field parameter</param>
  8327. public void FieldInst(FieldOp inst, Field f) {
  8328. Debug.Assert(f != null);
  8329. if (f is FieldDef)
  8330. if (((FieldDef)f).GetScope() != thisMeth.GetScope())
  8331. throw new DescriptorException();
  8332. AddToBuffer(new FieldInstr(inst,f));
  8333. }
  8334. /// <summary>
  8335. /// Add an instruction with a method parameter
  8336. /// </summary>
  8337. /// <param name="inst">the CIL instruction</param>
  8338. /// <param name="m">the method parameter</param>
  8339. public void MethInst(MethodOp inst, Method m) {
  8340. Debug.Assert(m != null);
  8341. if (m is MethodDef)
  8342. if (((MethodDef)m).GetScope() != thisMeth.GetScope())
  8343. throw new DescriptorException();
  8344. AddToBuffer(new MethInstr(inst,m));
  8345. }
  8346. /// <summary>
  8347. /// Add an instruction with a type parameter
  8348. /// </summary>
  8349. /// <param name="inst">the CIL instruction</param>
  8350. /// <param name="aType">the type argument for the CIL instruction</param>
  8351. public void TypeInst(TypeOp inst, Type aType) {
  8352. Debug.Assert(aType != null);
  8353. if (aType is ClassDef) {
  8354. if (((ClassDef)aType).GetScope() != thisMeth.GetScope())
  8355. throw new DescriptorException();
  8356. }
  8357. AddToBuffer(new TypeInstr(inst,aType));
  8358. }
  8359. /// <summary>
  8360. /// Add a branch instruction
  8361. /// </summary>
  8362. /// <param name="inst">the branch instruction</param>
  8363. /// <param name="lab">the label that is the target of the branch</param>
  8364. public void Branch(BranchOp inst, CILLabel lab) {
  8365. Debug.Assert(lab != null);
  8366. AddToBuffer(new BranchInstr(inst,lab));
  8367. }
  8368. /// <summary>
  8369. /// Add a switch instruction
  8370. /// </summary>
  8371. /// <param name="labs">the target labels for the switch</param>
  8372. public void Switch(CILLabel[] labs) {
  8373. AddToBuffer(new SwitchInstr(labs));
  8374. }
  8375. /// <summary>
  8376. /// Add a byte to the CIL instructions (.emitbyte)
  8377. /// </summary>
  8378. /// <param name="bVal"></param>
  8379. public void emitbyte(byte bVal) {
  8380. AddToBuffer(new CILByte(bVal));
  8381. }
  8382. /// <summary>
  8383. /// Add an instruction which puts an integer on TOS. This method
  8384. /// selects the correct instruction based on the value of the integer.
  8385. /// </summary>
  8386. /// <param name="i">the integer value</param>
  8387. public void PushInt(int i) {
  8388. if (i == -1) {
  8389. AddToBuffer(new Instr(Op.ldc_i4_m1));
  8390. } else if ((i >= 0) && (i <= 8)) {
  8391. Op op = (Op)(Op.ldc_i4_0 + i);
  8392. AddToBuffer(new Instr(op));
  8393. } else if ((i >= minByteVal) && (i <= maxByteVal)) {
  8394. AddToBuffer(new IntInstr(IntOp.ldc_i4_s,i));
  8395. } else {
  8396. AddToBuffer(new IntInstr(IntOp.ldc_i4,i));
  8397. }
  8398. }
  8399. /// <summary>
  8400. /// Add the instruction to load a long on TOS
  8401. /// </summary>
  8402. /// <param name="l">the long value</param>
  8403. public void PushLong(long l) {
  8404. AddToBuffer(new LongInstr(SpecialOp.ldc_i8,l));
  8405. }
  8406. /// <summary>
  8407. /// Add an instruction to push the boolean value true on TOS
  8408. /// </summary>
  8409. public void PushTrue() {
  8410. AddToBuffer(new Instr(Op.ldc_i4_1));
  8411. }
  8412. /// <summary>
  8413. /// Add an instruction to push the boolean value false on TOS
  8414. /// </summary>
  8415. public void PushFalse() {
  8416. AddToBuffer(new Instr(Op.ldc_i4_0));
  8417. }
  8418. /// <summary>
  8419. /// Add the instruction to load an argument on TOS. This method
  8420. /// selects the correct instruction based on the value of argNo
  8421. /// </summary>
  8422. /// <param name="argNo">the number of the argument</param>
  8423. public void LoadArg(int argNo) {
  8424. if (argNo < 4) {
  8425. Op op = (Op)Op.ldarg_0 + argNo;
  8426. AddToBuffer(new Instr(op));
  8427. } else if (argNo <= maxUByteVal) {
  8428. AddToBuffer(new UIntInstr(IntOp.ldarg_s,(uint)argNo));
  8429. } else {
  8430. AddToBuffer(new UIntInstr(IntOp.ldarg,(uint)argNo));
  8431. }
  8432. }
  8433. /// <summary>
  8434. /// Add the instruction to load the address of an argument on TOS.
  8435. /// This method selects the correct instruction based on the value
  8436. /// of argNo.
  8437. /// </summary>
  8438. /// <param name="argNo">the number of the argument</param>
  8439. public void LoadArgAdr(int argNo) {
  8440. if (argNo <= maxUByteVal) {
  8441. AddToBuffer(new UIntInstr(IntOp.ldarga_s,(uint)argNo));
  8442. } else {
  8443. AddToBuffer(new UIntInstr(IntOp.ldarga,(uint)argNo));
  8444. }
  8445. }
  8446. /// <summary>
  8447. /// Add the instruction to load a local on TOS. This method selects
  8448. /// the correct instruction based on the value of locNo.
  8449. /// </summary>
  8450. /// <param name="locNo">the number of the local to load</param>
  8451. public void LoadLocal(int locNo) {
  8452. if (locNo < 4) {
  8453. Op op = (Op)Op.ldloc_0 + locNo;
  8454. AddToBuffer(new Instr(op));
  8455. } else if (locNo <= maxUByteVal) {
  8456. AddToBuffer(new UIntInstr(IntOp.ldloc_s,(uint)locNo));
  8457. } else {
  8458. AddToBuffer(new UIntInstr(IntOp.ldloc,(uint)locNo));
  8459. }
  8460. }
  8461. /// <summary>
  8462. /// Add the instruction to load the address of a local on TOS.
  8463. /// This method selects the correct instruction based on the
  8464. /// value of locNo.
  8465. /// </summary>
  8466. /// <param name="locNo">the number of the local</param>
  8467. public void LoadLocalAdr(int locNo) {
  8468. if (locNo <= maxUByteVal) {
  8469. AddToBuffer(new UIntInstr(IntOp.ldloca_s,(uint)locNo));
  8470. } else {
  8471. AddToBuffer(new UIntInstr(IntOp.ldloca,(uint)locNo));
  8472. }
  8473. }
  8474. /// <summary>
  8475. /// Add the instruction to store to an argument. This method
  8476. /// selects the correct instruction based on the value of argNo.
  8477. /// </summary>
  8478. /// <param name="argNo">the argument to be stored to</param>
  8479. public void StoreArg(int argNo) {
  8480. if (argNo <= maxUByteVal) {
  8481. AddToBuffer(new UIntInstr(IntOp.starg_s,(uint)argNo));
  8482. } else {
  8483. AddToBuffer(new UIntInstr(IntOp.starg,(uint)argNo));
  8484. }
  8485. }
  8486. /// <summary>
  8487. /// Add the instruction to store to a local. This method selects
  8488. /// the correct instruction based on the value of locNo.
  8489. /// </summary>
  8490. /// <param name="locNo">the local to be stored to</param>
  8491. public void StoreLocal(int locNo) {
  8492. if (locNo < 4) {
  8493. Op op = (Op)Op.stloc_0 + locNo;
  8494. AddToBuffer(new Instr(op));
  8495. } else if (locNo <= maxUByteVal) {
  8496. AddToBuffer(new UIntInstr(IntOp.stloc_s,(uint)locNo));
  8497. } else {
  8498. AddToBuffer(new UIntInstr(IntOp.stloc,(uint)locNo));
  8499. }
  8500. }
  8501. public void IntLine(int num)
  8502. {
  8503. Line((uint)num, 1);
  8504. }
  8505. /// <summary>
  8506. /// CLS compliant version of Line()
  8507. /// </summary>
  8508. /// <param name="sLin">The start line</param>
  8509. /// <param name="sCol">The start column</param>
  8510. /// <param name="eLin">The end line</param>
  8511. /// <param name="eCol">The end column</param>
  8512. public void IntLine(int sLin, int sCol, int eLin, int eCol)
  8513. {
  8514. Line((uint)sLin, (uint)sCol, (uint)eLin, (uint)eCol);
  8515. }
  8516. /// <summary>
  8517. /// Create a new line instruction.
  8518. /// </summary>
  8519. /// <param name="num">The line for the given code segment.</param>
  8520. /// <param name="startCol">The starting column for the code segment.</param>
  8521. public void Line(uint num, uint startCol) {
  8522. if (this.DefaultSourceFile == null) throw new Exception("Method can only be used if DefaultSourceFile has been set.");
  8523. AddToBuffer(new Line(num,startCol,this.DefaultSourceFile));
  8524. }
  8525. /// <summary>
  8526. /// Create a new line instruction.
  8527. /// </summary>
  8528. /// <param name="num">The line for the given code segment.</param>
  8529. /// <param name="startCol">The starting column for the code segment.</param>
  8530. /// <param name="endCol">The ending column for the code segment.</param>
  8531. public void Line(uint num, uint startCol, uint endCol) {
  8532. if (this.DefaultSourceFile == null) throw new Exception("Method can only be used if DefaultSourceFile has been set.");
  8533. AddToBuffer(new Line(num,startCol,num,endCol,this.DefaultSourceFile));
  8534. }
  8535. /// <summary>
  8536. /// Create a new line instruction.
  8537. /// </summary>
  8538. /// <param name="startNum">The starting line for the code segment.</param>
  8539. /// <param name="startCol">The starting column for the code segment.</param>
  8540. /// <param name="endNum">The ending line for the code segment.</param>
  8541. /// <param name="endCol">The ending column for the code segment.</param>
  8542. public void Line(uint startNum, uint startCol, uint endNum, uint endCol) {
  8543. if (this.DefaultSourceFile == null) throw new Exception("Method can only be used if DefaultSourceFile has bene set.");
  8544. AddToBuffer(new Line(startNum,startCol,endNum,endCol,this.DefaultSourceFile));
  8545. }
  8546. /// <summary>
  8547. /// Create a new line instruction.
  8548. /// </summary>
  8549. /// <param name="startNum">The starting line for the code segment.</param>
  8550. /// <param name="startCol">The starting column for the code segment.</param>
  8551. /// <param name="endNum">The ending line for the code segment.</param>
  8552. /// <param name="endCol">The ending column for the code segment.</param>
  8553. /// <param name="sFile">The source file for the given code segment.</param>
  8554. public void Line(uint startNum, uint startCol, uint endNum, uint endCol, SourceFile sFile) {
  8555. AddToBuffer(new Line(startNum,startCol,endNum,endCol,sFile));
  8556. }
  8557. /// <summary>
  8558. /// The current scope.
  8559. /// </summary>
  8560. public Scope CurrentScope {
  8561. get { return currentScope; }
  8562. }
  8563. /// <summary>
  8564. /// Open a new scope.
  8565. /// </summary>
  8566. public void OpenScope() {
  8567. currentScope = new Scope(currentScope, thisMeth);
  8568. AddToBuffer(new OpenScope(currentScope));
  8569. //Console.WriteLine("Open scope on " + currentScope._thisMeth.Name());
  8570. }
  8571. /// <summary>
  8572. /// Close the current scope.
  8573. /// </summary>
  8574. public void CloseScope() {
  8575. //Console.WriteLine("Close scope on " + currentScope._thisMeth.Name());
  8576. AddToBuffer(new CloseScope(currentScope));
  8577. currentScope = currentScope._parent;
  8578. }
  8579. /// <summary>
  8580. /// Bind a local to the CIL instructions.
  8581. /// </summary>
  8582. /// <param name="name">The name of the local variable..</param>
  8583. /// <param name="index">The index of the local variable.</param>
  8584. /// <returns>The LocalBinding object created with the given values.</returns>
  8585. public LocalBinding BindLocal(string name, int index) {
  8586. if (currentScope == null)
  8587. throw new Exception("Scope must be opened before locals can be bound.");
  8588. return currentScope.AddLocalBinding(name, index);
  8589. }
  8590. /// <summary>
  8591. /// Bind a local to the CIL instructions.
  8592. /// </summary>
  8593. /// <param name="local">The local variable to load.</param>
  8594. /// <returns>The LocalBinding object created for the given Local object.</returns>
  8595. public LocalBinding BindLocal(Local local) {
  8596. return BindLocal(local.Name,local.GetIndex());
  8597. }
  8598. /// <summary>
  8599. /// Bind a constant to the CIL instructions.
  8600. /// </summary>
  8601. /// <param name="name">The name of the constant.</param>
  8602. /// <param name="value">The value of the constant.</param>
  8603. /// <param name="type">The type of the constant.</param>
  8604. /// <returns>Return the ConstantBinding created with the given values.</returns>
  8605. public ConstantBinding BindConstant(string name, object value, Type type) {
  8606. if (currentScope == null)
  8607. throw new Exception("Scope must be opened before constants can be bound.");
  8608. return currentScope.AddConstantBinding(name, value, type);
  8609. }
  8610. /// <summary>
  8611. /// Mark this position as the start of a new block
  8612. /// (try, catch, filter, finally or fault)
  8613. /// </summary>
  8614. public void StartBlock() {
  8615. if (blockStack == null) blockStack = new Stack();
  8616. blockStack.Push(NewCodedLabel());
  8617. }
  8618. /// <summary>
  8619. /// Mark this position as the end of the last started block and
  8620. /// make it a try block. This try block is added to the current
  8621. /// instructions (ie do not need to call AddTryBlock)
  8622. /// </summary>
  8623. /// <returns>The try block just ended</returns>
  8624. public TryBlock EndTryBlock() {
  8625. TryBlock tBlock = new TryBlock((CILLabel)blockStack.Pop(),NewCodedLabel());
  8626. AddTryBlock(tBlock);
  8627. return tBlock;
  8628. }
  8629. /// <summary>
  8630. /// Mark this position as the end of the last started block and
  8631. /// make it a catch block. This catch block is associated with the
  8632. /// specified try block.
  8633. /// </summary>
  8634. /// <param name="exceptType">the exception type to be caught</param>
  8635. /// <param name="tryBlock">the try block associated with this catch block</param>
  8636. public void EndCatchBlock(Class exceptType, TryBlock tryBlock) {
  8637. Catch catchBlock = new Catch(exceptType,(CILLabel)blockStack.Pop(), NewCodedLabel());
  8638. tryBlock.AddHandler(catchBlock);
  8639. }
  8640. /// <summary>
  8641. /// Mark this position as the end of the last started block and
  8642. /// make it a filter block. This filter block is associated with the
  8643. /// specified try block. The format is:
  8644. /// filterLab: ...
  8645. /// ...
  8646. /// filterHandler : ...
  8647. /// ...
  8648. /// </summary>
  8649. /// <param name="filterLab">the label where the filter code is</param>
  8650. /// <param name="tryBlock">the try block associated with this filter block</param>
  8651. public void EndFilterBlock(CILLabel filterLab, TryBlock tryBlock) {
  8652. Filter filBlock = new Filter(filterLab,(CILLabel)blockStack.Pop(),NewCodedLabel());
  8653. tryBlock.AddHandler(filBlock);
  8654. }
  8655. /// <summary>
  8656. /// Mark this position as the end of the last started block and
  8657. /// make it a finally block. This finally block is associated with the
  8658. /// specified try block.
  8659. /// </summary>
  8660. /// <param name="tryBlock">the try block associated with this finally block</param>
  8661. public void EndFinallyBlock(TryBlock tryBlock) {
  8662. Finally finBlock= new Finally((CILLabel)blockStack.Pop(),NewCodedLabel());
  8663. tryBlock.AddHandler(finBlock);
  8664. }
  8665. /// <summary>
  8666. /// Mark this position as the end of the last started block and
  8667. /// make it a fault block. This fault block is associated with the
  8668. /// specified try block.
  8669. /// </summary>
  8670. /// <param name="tryBlock">the try block associated with this fault block</param>
  8671. public void EndFaultBlock(TryBlock tryBlock) {
  8672. Fault fBlock= new Fault((CILLabel)blockStack.Pop(),NewCodedLabel());
  8673. tryBlock.AddHandler(fBlock);
  8674. }
  8675. public void AddTryBlock(TryBlock tryBlock) {
  8676. if (exceptions == null)
  8677. exceptions = new ArrayList();
  8678. else if (exceptions.Contains(tryBlock)) return;
  8679. exceptions.Add(tryBlock);
  8680. }
  8681. /*------------------------- private methods ----------------------------*/
  8682. private void AddToBuffer(CILInstruction inst) {
  8683. if (tide >= buffer.Length) {
  8684. CILInstruction[] tmp = buffer;
  8685. buffer = new CILInstruction[tmp.Length * 2];
  8686. for (int i=0; i < tide; i++) {
  8687. buffer[i] = tmp[i];
  8688. }
  8689. }
  8690. //Console.WriteLine("Adding instruction at offset " + offset + " with size " + inst.size);
  8691. //inst.offset = offset;
  8692. //offset += inst.size;
  8693. inst.index = (uint)tide;
  8694. buffer[tide++] = inst;
  8695. }
  8696. private void UpdateIndexesFrom(int ix) {
  8697. for (int i=ix; i < tide; i++) {
  8698. buffer[i].index = (uint)i;
  8699. }
  8700. }
  8701. private void InsertInstructions(int ix, CILInstruction[] newInsts, int numNew) {
  8702. CILInstruction[] newBuff = buffer, oldBuff = buffer;
  8703. int newSize = tide + numNew - numReplace;
  8704. if (buffer.Length < newSize) {
  8705. newBuff = new CILInstruction[newSize];
  8706. for (int i=0; i < ix; i++) {
  8707. newBuff[i] = oldBuff[i];
  8708. }
  8709. }
  8710. // shuffle up
  8711. int offset = numNew-numReplace;
  8712. int end = ix + numReplace;
  8713. for (int i=tide-1; i >= end; i--) {
  8714. newBuff[i+offset] = oldBuff[i];
  8715. }
  8716. // insert new instructions
  8717. for (int i=0; i < numNew; i++) {
  8718. newBuff[ix+i] = newInsts[i];
  8719. }
  8720. buffer = newBuff;
  8721. tide += numNew - numReplace;
  8722. UpdateIndexesFrom(ix);
  8723. }
  8724. internal bool IsEmpty() {
  8725. return tide == 0;
  8726. }
  8727. internal static CILLabel GetLabel(ArrayList labs, uint targetOffset) {
  8728. CILLabel lab;
  8729. int i=0;
  8730. while ((i < labs.Count) && (((CILLabel)labs[i]).offset < targetOffset)) i++;
  8731. if (i < labs.Count) {
  8732. if (((CILLabel)labs[i]).offset == targetOffset) // existing label
  8733. lab = (CILLabel)labs[i];
  8734. else {
  8735. lab = new CILLabel(targetOffset);
  8736. labs.Insert(i,lab);
  8737. }
  8738. } else {
  8739. lab = new CILLabel(targetOffset);
  8740. labs.Add(lab);
  8741. }
  8742. return lab;
  8743. }
  8744. internal void AddEHClause(EHClause ehc) {
  8745. if (exceptions == null)
  8746. exceptions = new ArrayList();
  8747. exceptions.Add(ehc);
  8748. }
  8749. internal void SetAndResolveInstructions(CILInstruction[] insts) {
  8750. offset = 0;
  8751. ArrayList labels = new ArrayList();
  8752. for (int i=0; i < insts.Length; i++) {
  8753. insts[i].offset = offset;
  8754. offset += insts[i].size;
  8755. if (insts[i] is BranchInstr) {
  8756. ((BranchInstr)insts[i]).MakeTargetLabel(labels);
  8757. } else if (insts[i] is SwitchInstr) {
  8758. ((SwitchInstr)insts[i]).MakeTargetLabels(labels);
  8759. }
  8760. }
  8761. if (exceptions != null) {
  8762. for (int i=0; i < exceptions.Count; i++) {
  8763. exceptions[i] = ((EHClause)exceptions[i]).MakeTryBlock(labels);
  8764. }
  8765. }
  8766. if (labels.Count == 0) { buffer = insts; tide = buffer.Length; return; }
  8767. buffer = new CILInstruction[insts.Length + labels.Count];
  8768. int currentPos = 0;
  8769. tide = 0;
  8770. for (int i=0; i < labels.Count; i++) {
  8771. CILLabel lab = (CILLabel)labels[i];
  8772. while ((currentPos < insts.Length) && (insts[currentPos].offset < lab.offset))
  8773. buffer[tide++] = insts[currentPos++];
  8774. buffer[tide++] = lab;
  8775. }
  8776. while (currentPos < insts.Length) {
  8777. buffer[tide++] = insts[currentPos++];
  8778. }
  8779. }
  8780. internal uint GetCodeSize() {
  8781. return codeSize + paddingNeeded + exceptSize;
  8782. }
  8783. internal void BuildTables(MetaDataOut md) {
  8784. for (int i=0; i < tide; i++) {
  8785. buffer[i].BuildTables(md);
  8786. }
  8787. if (exceptions != null) {
  8788. for (int i=0; i < exceptions.Count; i++) {
  8789. ((TryBlock)exceptions[i]).BuildTables(md);
  8790. }
  8791. }
  8792. }
  8793. internal void BuildCILInfo(CILWriter output) {
  8794. for (int i=0; i < tide; i++) {
  8795. buffer[i].BuildCILInfo(output);
  8796. }
  8797. if (exceptions != null) {
  8798. for (int i=0; i < exceptions.Count; i++) {
  8799. ((TryBlock)exceptions[i]).BuildCILInfo(output);
  8800. }
  8801. }
  8802. }
  8803. internal void ChangeRefsToDefs(ClassDef newType, ClassDef[] oldTypes) {
  8804. for (int i=0; i < tide; i++) {
  8805. if (buffer[i] is SigInstr) {
  8806. CalliSig sig = ((SigInstr)buffer[i]).GetSig();
  8807. sig.ChangeRefsToDefs(newType,oldTypes);
  8808. } else if (buffer[i] is TypeInstr) {
  8809. TypeInstr tinst = (TypeInstr)buffer[i];
  8810. if (tinst.GetTypeArg() is ClassDef) {
  8811. ClassDef iType = (ClassDef)tinst.GetTypeArg();
  8812. bool changed = false;
  8813. for (int j=0; (j < oldTypes.Length) && !changed; j++) {
  8814. if (iType == oldTypes[j])
  8815. tinst.SetTypeArg(newType);
  8816. }
  8817. }
  8818. }
  8819. }
  8820. }
  8821. internal void AddToLines(Line line) {
  8822. if ((line.sourceFile == null) || (line.sourceFile.Match(defaultSourceFile))) {
  8823. if (defaultLines == null) {
  8824. if (defaultSourceFile == null)
  8825. throw new Exception("No Default Source File Set");
  8826. defaultLines = new ArrayList();
  8827. }
  8828. defaultLines.Add(line);
  8829. return;
  8830. }
  8831. if (sourceLines == null) {
  8832. sourceLines = new ArrayList();
  8833. } else {
  8834. for (int i=0; i < sourceLines.Count; i++) {
  8835. ArrayList lineList = (ArrayList)sourceLines[i];
  8836. if (((Line)lineList[0]).sourceFile.Match(line.sourceFile)) {
  8837. lineList.Add(line);
  8838. return;
  8839. }
  8840. }
  8841. ArrayList newList = new ArrayList();
  8842. newList.Add(line);
  8843. sourceLines.Add(newList);
  8844. }
  8845. }
  8846. internal void CheckCode(uint locSigIx, bool initLocals, int maxStack, MetaDataOut metaData) {
  8847. if (tide == 0) return;
  8848. offset = 0;
  8849. for (int i=0; i < tide; i++) {
  8850. buffer[i].offset = offset;
  8851. offset += buffer[i].size;
  8852. if (buffer[i] is Line)
  8853. AddToLines((Line)buffer[i]);
  8854. }
  8855. bool changed = true;
  8856. while (changed) {
  8857. changed = false;
  8858. Line prevLine = null;
  8859. for (int i=0; i < tide; i++) {
  8860. if (buffer[i] is Line) {
  8861. if (prevLine != null)
  8862. prevLine.CalcEnd((Line)buffer[i]);
  8863. prevLine = (Line)buffer[i];
  8864. }
  8865. changed = buffer[i].Check(metaData) || changed;
  8866. }
  8867. if (prevLine != null) prevLine.Last();
  8868. if (changed) {
  8869. for (int i=1; i < tide; i++) {
  8870. buffer[i].offset = buffer[i-1].offset + buffer[i-1].size;
  8871. }
  8872. offset = buffer[tide-1].offset + buffer[tide-1].size;
  8873. }
  8874. }
  8875. codeSize = offset;
  8876. if (Diag.DiagOn) Console.WriteLine("codeSize before header added = " + codeSize);
  8877. if (maxStack == 0) this.maxStack = 8;
  8878. else this.maxStack = (short)maxStack;
  8879. if ((offset < smallSize) && (maxStack <= 8) && (locSigIx == 0) && (exceptions == null)) {
  8880. // can use tiny header
  8881. if (Diag.DiagOn) Console.WriteLine("Tiny Header");
  8882. tinyFormat = true;
  8883. headerFlags = (ushort)(TinyFormat | ((ushort)codeSize << 2));
  8884. codeSize++;
  8885. if ((codeSize % 4) != 0) { paddingNeeded = 4 - (codeSize % 4); }
  8886. } else {
  8887. if (Diag.DiagOn) Console.WriteLine("Fat Header");
  8888. tinyFormat = false;
  8889. localSigIx = locSigIx;
  8890. //this.maxStack = (short)maxStack;
  8891. headerFlags = FatFormatHeader;
  8892. if (exceptions != null) {
  8893. // Console.WriteLine("Got exceptions");
  8894. headerFlags |= MoreSects;
  8895. uint numExceptClauses = 0;
  8896. for (int i=0; i < exceptions.Count; i++) {
  8897. TryBlock tryBlock = (TryBlock)exceptions[i];
  8898. tryBlock.SetSize();
  8899. numExceptClauses += (uint)tryBlock.NumHandlers();
  8900. if (tryBlock.isFat()) fatExceptionFormat = true;
  8901. }
  8902. if (numExceptClauses > MaxClauses) fatExceptionFormat = true;
  8903. if (Diag.DiagOn) Console.WriteLine("numexceptclauses = " + numExceptClauses);
  8904. if (fatExceptionFormat) {
  8905. if (Diag.DiagOn) Console.WriteLine("Fat exception format");
  8906. exceptHeader = FatExceptTable;
  8907. exceptSize = ExHeaderSize + numExceptClauses * FatExClauseSize;
  8908. } else {
  8909. if (Diag.DiagOn) Console.WriteLine("Tiny exception format");
  8910. exceptHeader = SmlExceptTable;
  8911. exceptSize = ExHeaderSize + numExceptClauses * SmlExClauseSize;
  8912. }
  8913. if (Diag.DiagOn) Console.WriteLine("exceptSize = " + exceptSize);
  8914. }
  8915. if (initLocals) headerFlags |= InitLocals;
  8916. if ((offset % 4) != 0) { paddingNeeded = 4 - (offset % 4); }
  8917. codeSize += FatSize;
  8918. }
  8919. if (Diag.DiagOn)
  8920. Console.WriteLine("codeSize = " + codeSize + " headerFlags = " + Hex.Short(headerFlags));
  8921. }
  8922. /// <summary>
  8923. /// Returns the maximum stack depth required by these CIL instructions.
  8924. /// </summary>
  8925. /// <returns>The integer value of the stck depth.</returns>
  8926. public int GetMaxStackDepthRequired() {
  8927. if (tide == 0) return 0;
  8928. // Store the code blocks we find
  8929. SCG.List<CodeBlock> codeBlocks = new SCG.List<CodeBlock>();
  8930. SCG.Dictionary<CILLabel, CodeBlock> cbTable = new SCG.Dictionary<CILLabel, CodeBlock>();
  8931. SCG.List<CodeBlock> extraStartingBlocks = new SCG.List<CodeBlock>();
  8932. // Start a default code block
  8933. CodeBlock codeBlock = new CodeBlock(this);
  8934. codeBlock.StartIndex = 0;
  8935. //
  8936. // Identify the code blocks
  8937. //
  8938. for (int i = 0; i < tide; i++) {
  8939. /* Handling the tail instruction:
  8940. * The tail instruction has not been handled even though
  8941. * it indicates the end of a code block is coming. The
  8942. * reason for this is because any valid tail instruction
  8943. * must be followed by a call* instruction and then a ret
  8944. * instruction. Given a ret instruction must be the second
  8945. * next instruction anyway it has been decided to just let
  8946. * the end block be caught then.
  8947. */
  8948. // If we reach a branch instruction or a switch instruction
  8949. // then end the current code block inclusive of the instruction.
  8950. if ((buffer[i] is BranchInstr) || (buffer[i] is SwitchInstr)) {
  8951. // Close the old block
  8952. codeBlock.EndIndex = i;
  8953. if (codeBlock.EndIndex >= codeBlock.StartIndex) // Don't add empty blocks
  8954. codeBlocks.Add(codeBlock);
  8955. // Open a new block
  8956. codeBlock = new CodeBlock(this);
  8957. codeBlock.StartIndex = i + 1;
  8958. // If we reach a label then we need to start a new
  8959. // code block as the label is an entry point.
  8960. } else if (buffer[i] is CILLabel) {
  8961. // Close the old block
  8962. codeBlock.EndIndex = i - 1;
  8963. if (codeBlock.EndIndex >= codeBlock.StartIndex) // Don't add empty blocks
  8964. codeBlocks.Add(codeBlock);
  8965. // Open a new block
  8966. codeBlock = new CodeBlock(this);
  8967. codeBlock.StartIndex = i;
  8968. // Set this label as the entry point for the code block
  8969. codeBlock.EntryLabel = (CILLabel)buffer[i];
  8970. // AND ... list in the dictionary.
  8971. cbTable.Add(codeBlock.EntryLabel, codeBlock);
  8972. // Check for the ret, throw, rethrow, or jmp instruction as they also end a block
  8973. } else if (buffer[i] is Instr) {
  8974. if (
  8975. (((Instr)buffer[i]).GetOp() == Op.ret) ||
  8976. (((Instr)buffer[i]).GetOp() == Op.throwOp) ||
  8977. (((Instr)buffer[i]).GetOp() == Op.rethrow) ||
  8978. ((buffer[i] is MethInstr) && (((MethInstr)buffer[i]).GetMethodOp() == MethodOp.jmp))
  8979. ) {
  8980. // Close the old block
  8981. codeBlock.EndIndex = i;
  8982. if (codeBlock.EndIndex >= codeBlock.StartIndex) // Don't add empty blocks
  8983. codeBlocks.Add(codeBlock);
  8984. // Open a new block
  8985. // In theory this should never happen but just in case
  8986. // someone feels like adding dead code it is supported.
  8987. codeBlock = new CodeBlock(this);
  8988. codeBlock.StartIndex = i + 1;
  8989. }
  8990. }
  8991. }
  8992. // Close the last block
  8993. codeBlock.EndIndex = tide - 1;
  8994. if (codeBlock.EndIndex >= codeBlock.StartIndex) // Don't add empty blocks
  8995. codeBlocks.Add(codeBlock);
  8996. codeBlock = null;
  8997. // Check how many code blocks there are. If an blocks return 0.
  8998. if (codeBlocks.Count == 0) return 0;
  8999. //
  9000. // Loop through each code block and calculate the delta distance
  9001. //
  9002. for (int j = 0; j < codeBlocks.Count; j++) {
  9003. CodeBlock block = codeBlocks[j];
  9004. int maxDepth = 0;
  9005. int currentDepth = 0;
  9006. // Loop through each instruction to work out the max depth
  9007. for (int i = block.StartIndex; i <= block.EndIndex; i++) {
  9008. // Get the depth after the next instruction
  9009. currentDepth += buffer[i].GetDeltaDistance();
  9010. // If the new current depth is greater then the maxDepth adjust the maxDepth to reflect
  9011. if (currentDepth > maxDepth)
  9012. maxDepth = currentDepth;
  9013. }
  9014. // Set the depth of the block
  9015. block.MaxDepth = maxDepth;
  9016. block.DeltaDistance = currentDepth;
  9017. //
  9018. // Link up the next blocks
  9019. //
  9020. // If the block ends with a branch statement set the jump and fall through.
  9021. if (buffer[block.EndIndex] is BranchInstr) {
  9022. BranchInstr branchInst = (BranchInstr)buffer[block.EndIndex];
  9023. // If this is not a "br" or "br.s" then set the fall through code block
  9024. if ((branchInst.GetBranchOp() != BranchOp.br) &&
  9025. (branchInst.GetBranchOp() != BranchOp.br_s))
  9026. // If there is a following code block set it as the fall through
  9027. if (j < (codeBlocks.Count - 1))
  9028. block.NextBlocks.Add(codeBlocks[j + 1]);
  9029. // Set the code block we are jumping to
  9030. CodeBlock cb = null;
  9031. cbTable.TryGetValue(branchInst.GetDest(), out cb);
  9032. if (cb == null)
  9033. throw new Exception("Missing Branch Label");
  9034. block.NextBlocks.Add(cb);
  9035. // If the block ends in a switch instruction work out the possible next blocks
  9036. } else if (buffer[block.EndIndex] is SwitchInstr) {
  9037. SwitchInstr switchInstr = (SwitchInstr)buffer[block.EndIndex];
  9038. // If there is a following code block set it as the fall through
  9039. if (j < (codeBlocks.Count - 1))
  9040. block.NextBlocks.Add(codeBlocks[j + 1]);
  9041. // Add each destination block
  9042. foreach (CILLabel label in switchInstr.GetDests()) {
  9043. // Check all of the code blocks to find the jump destination
  9044. CodeBlock cb = null;
  9045. cbTable.TryGetValue(label, out cb);
  9046. if (cb == null) throw new Exception("Missing Case Label");
  9047. block.NextBlocks.Add(cb);
  9048. }
  9049. // So long as the block doesn't end with a terminating instruction like ret or throw, just fall through to the next block
  9050. } else if (!IsTerminatingInstruction(buffer[block.EndIndex])) {
  9051. // If there is a following code block set it as the fall through
  9052. if (j < (codeBlocks.Count - 1))
  9053. block.NextBlocks.Add(codeBlocks[j + 1]);
  9054. }
  9055. }
  9056. //
  9057. // Join up any exception blocks
  9058. //
  9059. if (exceptions != null) {
  9060. foreach (TryBlock tryBlock in exceptions) {
  9061. // Try to find the code block where this try block starts
  9062. CodeBlock tryCodeBlock;
  9063. cbTable.TryGetValue(tryBlock.Start, out tryCodeBlock);
  9064. // Declare that the entry to this code block must be empty
  9065. tryCodeBlock.RequireEmptyEntry = true;
  9066. // Work with each of the handlers
  9067. foreach (HandlerBlock hb in tryBlock.GetHandlers()) {
  9068. // Find the code block where this handler block starts.
  9069. CodeBlock handlerCodeBlock;
  9070. cbTable.TryGetValue(hb.Start, out handlerCodeBlock);
  9071. // If the code block is a catch or filter block increment the delta
  9072. // distance by 1. This is to factor in the exception object that will
  9073. // be secretly placed on the stack by the runtime engine.
  9074. // However, this also means that the MaxDepth is up by one also!
  9075. if (hb is Catch || hb is Filter)
  9076. {
  9077. handlerCodeBlock.DeltaDistance++;
  9078. handlerCodeBlock.MaxDepth++;
  9079. }
  9080. // If the code block is a filter block increment the delta distance by 1
  9081. // This is to factor in the exception object that will be placed on the stack.
  9082. // if (hb is Filter) handlerCodeBlock.DeltaDistance++;
  9083. // Add this handler to the list of starting places
  9084. extraStartingBlocks.Add(handlerCodeBlock);
  9085. }
  9086. }
  9087. }
  9088. //
  9089. // Traverse the code blocks and get the depth
  9090. //
  9091. // Get the max depth at the starting entry point
  9092. int finalMaxDepth = this.TraverseMaxDepth(codeBlocks[0]);
  9093. // Check the additional entry points
  9094. // If the additional points have a greater depth update the max depth
  9095. foreach (CodeBlock cb in extraStartingBlocks) {
  9096. // int tmpMaxDepth = cb.TraverseMaxDepth();
  9097. int tmpMaxDepth = this.TraverseMaxDepth(cb);
  9098. if (tmpMaxDepth > finalMaxDepth) finalMaxDepth = tmpMaxDepth;
  9099. }
  9100. // Return the max depth we have found
  9101. return finalMaxDepth;
  9102. }
  9103. int TraverseMaxDepth(CodeBlock entryBlock)
  9104. {
  9105. int max = 0;
  9106. SCG.Queue<CodeBlock> worklist = new SCG.Queue<CodeBlock>();
  9107. entryBlock.Visited = true;
  9108. entryBlock.LastVisitEntryDepth = 0;
  9109. worklist.Enqueue(entryBlock);
  9110. while (worklist.Count > 0)
  9111. {
  9112. int count = worklist.Count;
  9113. CodeBlock unit = worklist.Dequeue();
  9114. int maxDepth = unit.LastVisitEntryDepth + unit.MaxDepth;
  9115. int exitDepth = unit.LastVisitEntryDepth + unit.DeltaDistance;
  9116. if (maxDepth > max) max = maxDepth;
  9117. foreach (CodeBlock succ in unit.NextBlocks)
  9118. {
  9119. if (succ.Visited)
  9120. {
  9121. if (succ.LastVisitEntryDepth != exitDepth)
  9122. throw new InvalidStackDepth("inconsistent stack depth at offset " + succ.StartIndex.ToString());
  9123. }
  9124. else
  9125. {
  9126. succ.Visited = true;
  9127. succ.LastVisitEntryDepth = exitDepth;
  9128. worklist.Enqueue(succ);
  9129. }
  9130. }
  9131. }
  9132. return max;
  9133. }
  9134. private bool IsTerminatingInstruction(CILInstruction cilInstr) {
  9135. // Return or throw instructions are terminating instructions
  9136. if (cilInstr is Instr) {
  9137. if (((Instr)cilInstr).GetOp() == Op.ret) return true;
  9138. if (((Instr)cilInstr).GetOp() == Op.throwOp) return true;
  9139. if (((Instr)cilInstr).GetOp() == Op.rethrow) return true;
  9140. }
  9141. // jmp is a terminating instruction
  9142. if (cilInstr is MethInstr) {
  9143. if (((MethInstr)cilInstr).GetMethodOp() == MethodOp.jmp) return true;
  9144. }
  9145. return false;
  9146. }
  9147. internal void Write(PEWriter output) {
  9148. if (Diag.DiagOn) Console.WriteLine("Writing header flags = " + Hex.Short(headerFlags));
  9149. if (tinyFormat) {
  9150. if (Diag.DiagOn) Console.WriteLine("Writing tiny code");
  9151. output.Write((byte)headerFlags);
  9152. } else {
  9153. if (Diag.DiagOn) Console.WriteLine("Writing fat code");
  9154. output.Write(headerFlags);
  9155. output.Write((ushort)maxStack);
  9156. output.Write(offset);
  9157. output.Write(localSigIx);
  9158. }
  9159. if (Diag.DiagOn) {
  9160. Console.WriteLine(Hex.Int(tide) + " CIL instructions");
  9161. Console.WriteLine("starting instructions at " + output.Seek(0,SeekOrigin.Current));
  9162. }
  9163. // Added to enable PDB generation
  9164. if (output.pdbWriter != null) {
  9165. // Open the method
  9166. output.pdbWriter.OpenMethod((int)thisMeth.Token());
  9167. // Check if this is the entry point method
  9168. if (thisMeth.HasEntryPoint()) output.pdbWriter.SetEntryPoint((int)thisMeth.Token());
  9169. }
  9170. // Write out each memember of the buffer
  9171. for (int i=0; i < tide; i++) {
  9172. buffer[i].Write(output);
  9173. }
  9174. // Added to enable PDB generation
  9175. if (output.pdbWriter != null && tide > 0) {
  9176. output.pdbWriter.CloseMethod();
  9177. }
  9178. if (Diag.DiagOn) Console.WriteLine("ending instructions at " + output.Seek(0,SeekOrigin.Current));
  9179. for (int i=0; i < paddingNeeded; i++) { output.Write((byte)0); }
  9180. if (exceptions != null) {
  9181. // Console.WriteLine("Writing exceptions");
  9182. // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
  9183. output.Write(exceptHeader);
  9184. output.Write3Bytes((uint)exceptSize);
  9185. for (int i=0; i < exceptions.Count; i++) {
  9186. TryBlock tryBlock = (TryBlock)exceptions[i];
  9187. tryBlock.Write(output,fatExceptionFormat);
  9188. }
  9189. }
  9190. }
  9191. internal void Write(CILWriter output) {
  9192. for (int i=0; i < tide; i++) {
  9193. if (!(buffer[i] is CILLabel)) {
  9194. output.Write(" ");
  9195. }
  9196. output.Write(" ");
  9197. buffer[i].Write(output);
  9198. }
  9199. if (exceptions != null) {
  9200. throw new NotYetImplementedException("Exceptions not yet implemented for CIL Instructions");
  9201. // Console.WriteLine("Writing exceptions");
  9202. // Console.WriteLine("header = " + Hex.Short(exceptHeader) + " exceptSize = " + Hex.Int(exceptSize));
  9203. //output.Write(exceptHeader);
  9204. //output.Write3Bytes((uint)exceptSize);
  9205. //for (int i = 0; i < exceptions.Count; i++) {
  9206. // TryBlock tryBlock = (TryBlock)exceptions[i];
  9207. // tryBlock.Write(output, fatExceptionFormat);
  9208. //}
  9209. }
  9210. }
  9211. /// <summary>
  9212. /// Stores the details of a given code block
  9213. /// </summary>
  9214. private class CodeBlock {
  9215. internal int StartIndex;
  9216. internal int EndIndex;
  9217. internal int DeltaDistance;
  9218. internal int MaxDepth;
  9219. internal CILLabel EntryLabel;
  9220. internal ArrayList NextBlocks = new ArrayList(); // List of CodeBlock objects
  9221. // internal int Visits;
  9222. internal int LastVisitEntryDepth;
  9223. internal bool RequireEmptyEntry;
  9224. internal bool Visited = false;
  9225. private CILInstructions cilInstr;
  9226. /// <summary>
  9227. /// Create a new code block definition
  9228. /// </summary>
  9229. /// <param name="instructions">The buffer the code block relates to</param>
  9230. internal CodeBlock(CILInstructions instructions) {
  9231. cilInstr = instructions;
  9232. }
  9233. }
  9234. }
  9235. /**************************************************************************/
  9236. /// <summary>
  9237. /// Descriptor for an IL instruction
  9238. /// </summary>
  9239. public abstract class CILInstruction {
  9240. protected static readonly sbyte maxByteVal = 127;
  9241. protected static readonly sbyte minByteVal = -128;
  9242. protected static readonly byte leadByte = 0xFE;
  9243. protected static readonly uint USHeapIndex = 0x70000000;
  9244. protected static readonly uint longInstrStart = (uint)Op.arglist;
  9245. protected static readonly string[] opcode = {
  9246. "nop", "break", "ldarg.0", "ldarg.1", "ldarg.2", "ldarg.3", "ldloc.0", "ldloc.1",
  9247. "ldloc.2", "ldloc.3", "stloc.0", "stloc.1", "stloc.2", "stloc.3", "ldarg.s", "ldarga.s",
  9248. "starg.s", "ldloc.s", "ldloca.s","stloc.s", "ldnull", "ldc.i4.m1","ldc.i4.0","ldc.i4.1",
  9249. "ldc.i4.2","ldc.i4.3","ldc.i4.4","ldc.i4.5","ldc.i4.6","ldc.i4.7","ldc.i4.8","ldc.i4.s",
  9250. "ldc.i4", "ldc.i8", "ldc.r4", "ldc.r8", "ERROR", "dup", "pop", "jmp",
  9251. "call", "calli", "ret", "br.s", "brfalse.s","brtrue.s","beq.s", "bge.s",
  9252. "bgt.s", "ble.s", "blt.s", "bne.un.s","bge.un.s","bgt.un.s","ble.un.s","blt.un.s",
  9253. "br", "brfalse", "brtrue", "beq", "bge", "bgt", "ble", "blt",
  9254. "bne.un", "bge.un", "bgt.un", "ble.un", "blt.un", "switch", "ldind.i1","ldind.u1",
  9255. "ldind.i2","ldind.u2","ldind.i4","ldind.u4","ldind.i8","ldind.i", "ldind.r4","ldind.r8",
  9256. "ldind.ref","stind.ref","stind.i1","stind.i2","stind.i4","stind.i8","stind.r4","stind.r8",
  9257. "add", "sub", "mul", "div", "div.un", "rem", "rem.un", "and",
  9258. "or", "xor", "shl", "shr", "shr.un", "neg", "not", "conv.i1",
  9259. "conv.i2", "conv.i4", "conv.i8", "conv.r4", "conv.r8", "conv.u4", "conv.u8", "callvirt",
  9260. "cpobj", "ldobj", "ldstr", "newobj", "castclass","isinst", "conv.r.un","ERROR",
  9261. "ERROR", "unbox", "throw", "ldfld", "ldflda", "stfld", "ldsfld", "ldsflda",
  9262. "stsfld", "stobj", "conv.ovf.i1.un", "conv.ovf.i2.un",
  9263. "conv.ovf.i4.un", "conv.ovf.i8.un", "conv.ovf.u1.un", "conv.ovf.u2.un",
  9264. "conv.ovf.u4.un", "conv.ovf.u8.un", "conv.ovf.i.un", "conv.ovf.u.un",
  9265. "box", "newarr", "ldlen", "ldelema",
  9266. "ldelem.i1", "ldelem.u1", "ldelem.i2", "ldelem.u2",
  9267. "ldelem.i4", "ldelem.u4", "ldelem.i8", "ldelem.i",
  9268. "ldelem.r4", "ldelem.r8", "ldelem.ref", "stelem.i",
  9269. "stelem.i1", "stelem.i2", "stelem.i4", "stelem.i8",
  9270. "stelem.r4", "stelem.r8", "stelem.ref", "ERROR",
  9271. "ERROR", "ERROR", "ERROR", "ERROR",
  9272. "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR",
  9273. "ERROR", "ERROR", "ERROR", "conv.ovf.i1",
  9274. "conv.ovf.u1", "conv.ovf.i2", "conv.ovf.u2", "conv.ovf.i4",
  9275. "conv.ovf.u4", "conv.ovf.i8", "conv.ovf.u8", "ERROR",
  9276. "ERROR", "ERROR", "ERROR", "ERROR",
  9277. "ERROR", "ERROR", "refanyval","ckfinite","ERROR", "ERROR", "mkrefany","ERROR",
  9278. "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR", "ERROR",
  9279. "ldtoken","conv.u2","conv.u1","conv.i","conv.ovf.i","conv.ovf.u","add.ovf","add.ovf.un",
  9280. "mul.ovf","mul.ovf.un","sub.ovf","sub.ovf.un","endfinally","leave","leave.s","stind.i",
  9281. "conv.u"};
  9282. protected static readonly int[] opDeltaDistance = {
  9283. 0 /* nop */, 0 /* break */, 1 /* ldarg.0 */, 1 /* ldarg.1 */, 1 /* ldarg.2 */, 1 /* ldarg.3 */, 1 /* ldloc.0 */, 1 /* ldloc.1 */,
  9284. 1 /* ldloc.2 */, 1 /* ldloc.3 */, -1 /* stloc.0 */, -1 /* stloc.1 */, -1 /* stloc.2 */, -1 /* stloc.3 */, 1 /* ldarg.s */, 1 /* ldarga.s */,
  9285. -1 /* starg.s */, 1 /* ldloc.s */, 1 /* ldloca.s */, -1 /* stloc.s */, 1 /* ldnull */, 1 /* ldc.i4.m1 */, 1 /* ldc.i4.0 */, 1 /* ldc.i4.1 */,
  9286. 1 /* ldc.i4.2 */, 1 /* ldc.i4.3 */, 1 /* ldc.i4.4 */, 1 /* ldc.i4.5 */, 1 /* ldc.i4.6 */, 1 /* ldc.i4.7 */, 1 /* ldc.i4.8 */, 1 /* ldc.i4.s */,
  9287. 1 /* ldc.i4 */, 1 /* ldc.i8 */, 1 /* ldc.r4 */, 1 /* ldc.r8 */, -99 /* ERROR */, 1 /* dup */, -1 /* pop */, 0 /* jmp */,
  9288. -99 /* call */, -99 /* calli */, 0 /* ret */, 0 /* br.s */, -1 /* brfalse.s */,-1 /* brtrue.s */, -2 /* beq.s */, -2 /* bge.s */,
  9289. -2 /* bgt.s */, -2 /* ble.s */, -2 /* blt.s */, -2 /* bne.un.s */, -2 /* bge.un.s */, -2 /* bgt.un.s */, -2 /* ble.un.s */, -2 /* blt.un.s */,
  9290. 0 /* br */, -1 /* brfalse */, -1 /* brtrue */, -2 /* beq */, -2 /* bge */, -2 /* bgt */, -2 /* ble */, -2 /* blt */,
  9291. -2 /* bne.un */, -2 /* bge.un */, -2 /* bgt.un */, -2 /* ble.un */, -2 /* blt.un */, -1 /* switch */, 0 /* ldind.i1 */, 0 /* ldind.u1 */,
  9292. 0 /* ldind.i2 */, 0 /* ldind.u2 */, 0 /* ldind.i4 */, 0 /* ldind.u4 */, 0 /* ldind.i8 */, 0 /* ldind.i */, 0 /* ldind.r4 */, 0 /* ldind.r8 */,
  9293. 0 /* ldind.ref */, -2 /* stind.ref */, -2 /* stind.i1 */, -2 /* stind.i2 */, -2 /* stind.i4 */, -2 /* stind.i8 */, -2 /* stind.r4 */, -2 /* stind.r8 */,
  9294. -1 /* add */, -1 /* sub */, -1 /* mul */, -1 /* div */, -1 /* div.un */, -1 /* rem */, -1 /* rem.un */, -1 /* and */,
  9295. -1 /* or */, -1 /* xor */, -1 /* shl */, -1 /* shr */, -1 /* shr.un */, 0 /* neg */, 0 /* not */, 0 /* conv.i1 */,
  9296. 0 /* conv.i2 */, 0 /* conv.i4 */, 0 /* conv.i8 */, 0 /* conv.r4 */, 0 /* conv.r8 */, 0 /* conv.u4 */, 0 /* conv.u8 */, -99 /* callvirt */,
  9297. -2 /* cpobj */, 0 /* ldobj */, 1 /* ldstr */, -99 /* newobj */, 0 /* castclass */, 0 /* isinst */, 0 /* conv.r.un */, -99 /* ERROR */,
  9298. -99 /* ERROR */, 0 /* unbox */, -1 /* throw */, 0 /* ldfld */, 0 /* ldflda */, -2 /* stfld */, 1 /* ldsfld */, 1 /* ldsflda */,
  9299. -1 /* stsfld */, -2 /* stobj */, 0 /* conv.ovf.i1.un */, 0 /* conv.ovf.i2.un */,
  9300. 0 /* conv.ovf.i4.un */, 0 /* conv.ovf.i8.un */, 0 /* conv.ovf.u1.un */, 0 /* conv.ovf.u2.un */,
  9301. 0 /* conv.ovf.u4.un */, 0 /* conv.ovf.u8.un */, 0 /* conv.ovf.i.un */, 0 /* conv.ovf.u.un */,
  9302. 0 /* box */, 0 /* newarr */, 0 /* ldlen */, -1 /* ldelema */,
  9303. -1 /* ldelem.i1 */, -1 /* ldelem.u1 */, -1 /* ldelem.i2 */, -1 /* ldelem.u2 */,
  9304. -1 /* ldelem.i4 */, -1 /* ldelem.u4 */, -1 /* ldelem.i8 */, -1 /* ldelem.i */,
  9305. -1 /* ldelem.r4 */, -1 /* ldelem.r8 */, -1 /* ldelem.ref */, -3 /* stelem.i */,
  9306. -3 /* stelem.i1 */, -3 /* stelem.i2 */, -3 /* stelem.i4 */, -3 /* stelem.i8 */,
  9307. -3 /* stelem.r4 */, -3 /* stelem.r8 */, -3 /* stelem.ref */, -99 /* ERROR */,
  9308. -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */,
  9309. -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */,
  9310. -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, 0 /* conv.ovf.i1 */,
  9311. 0 /* conv.ovf.u1 */, 0 /* conv.ovf.i2 */, 0 /* conv.ovf.u2 */, 0 /* conv.ovf.i4 */,
  9312. 0 /* conv.ovf.u4 */, 0 /* conv.ovf.i8 */, 0 /* conv.ovf.u8 */, -99 /* ERROR */,
  9313. -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */,
  9314. -99 /* ERROR */, -99 /* ERROR */, 0 /* refanyval */, 0 /* ckfinite */, -99 /* ERROR */, -99 /* ERROR */, 0 /* mkrefany */, -99 /* ERROR */,
  9315. -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */, -99 /* ERROR */,
  9316. 1 /* ldtoken */, 0 /* conv.u2 */, 0 /* conv.u1 */, 0 /* conv.i */, 0 /* conv.ovf.i */,0 /* conv.ovf.u */,-1 /* add.ovf */, -1 /* add.ovf.un */,
  9317. -1 /* mul.ovf */, -1 /* mul.ovf.un */, -1 /* sub.ovf */, -1 /* sub.ovf.un */, 0 /* endfinally */,0 /* leave */, 0 /* leave.s */, -2 /* stind.i */,
  9318. 0 /* conv.u */};
  9319. /// <summary>
  9320. /// A list of the delta distances for the given CIL instructions.
  9321. /// </summary>
  9322. protected static readonly string[] FEopcode = {
  9323. "arglist", "ceq", "cgt", "cgt.un", "clt", "clt.un", "ldftn", "ldvirtftn",
  9324. "ERROR", "ldarg", "ldarga", "starg", "ldloc", "ldloca", "stloc", "localloc",
  9325. "ERROR", "endfilter", "unaligned", "volatile", "tail", "initobj", "ERROR", "cpblk",
  9326. "initblk", "ERROR", "rethrow", "ERROR", "sizeof", "refanytype", "readonly"};
  9327. /// <summary>
  9328. /// A list of the delta distances for the given FE CIL instructions.
  9329. /// </summary>
  9330. protected static readonly int[] FEopDeltaDistance = {
  9331. 1 /* arglist */, -1 /* ceq */, -1 /* cgt */, -1 /* cgt.un */, -1 /* clt */, -1 /* clt.un */, 1 /* ldftn */, 0 /* ldvirtftn */,
  9332. -99 /* ERROR */, 1 /* ldarg */, 1 /* ldarga */, -1 /* starg */, 1 /* ldloc */, 1 /* ldloca */, -1 /* stloc */, 0 /* localloc */,
  9333. -99 /* ERROR */, -1 /* endfilter */, 0 /* unaligned */, 0 /* volatile */, 0 /* tail */, -1 /* initobj */, -99 /* ERROR */, -3 /* cpblk */,
  9334. -3 /* initblk */, -99 /* ERROR */, 0 /* rethrow */, -99 /* ERROR */, 1 /* sizeof */, 0 /* refanytype */, 0 /* readonly */};
  9335. internal bool twoByteInstr = false;
  9336. internal uint size = 1;
  9337. internal uint offset, index;
  9338. internal virtual bool Check(MetaDataOut md) {
  9339. return false;
  9340. }
  9341. internal virtual void Resolve() { }
  9342. public int GetPos() { return (int)index; }
  9343. internal abstract string GetInstName();
  9344. /// <summary>
  9345. /// Get the delta distance for this instruction.
  9346. /// </summary>
  9347. /// <remarks>
  9348. /// The delta distance is the resulting difference of items
  9349. /// left on the stack after calling this instruction.
  9350. /// </remarks>
  9351. /// <returns>An integer value representing the delta distance.</returns>
  9352. internal abstract int GetDeltaDistance();
  9353. internal virtual void BuildTables(MetaDataOut md) { }
  9354. internal virtual void BuildCILInfo(CILWriter output) { }
  9355. internal virtual void Write(PEWriter output) { }
  9356. internal virtual void Write(CILWriter output) { }
  9357. }
  9358. /**************************************************************************/
  9359. public class CILByte : CILInstruction {
  9360. byte byteVal;
  9361. /*-------------------- Constructors ---------------------------------*/
  9362. internal CILByte(byte bVal) {
  9363. byteVal = bVal;
  9364. }
  9365. public byte GetByte() { return byteVal; }
  9366. internal override string GetInstName() {
  9367. return Hex.Byte(byteVal);
  9368. }
  9369. /// <summary>
  9370. /// Get the delta distance for this instruction.
  9371. /// </summary>
  9372. /// <remarks>
  9373. /// The delta distance is the resulting difference of items
  9374. /// left on the stack after calling this instruction.
  9375. /// </remarks>
  9376. /// <returns>Zero, the delta distance for a CILByte</returns>
  9377. internal override int GetDeltaDistance() {
  9378. return 0;
  9379. }
  9380. internal override void Write(PEWriter output) {
  9381. output.Write(byteVal);
  9382. }
  9383. internal override void Write(CILWriter output) {
  9384. output.WriteLine(".emitbyte " + Hex.Byte(byteVal)); // ???? CHECK THIS ????
  9385. }
  9386. }
  9387. /**************************************************************************/
  9388. public class Instr : CILInstruction {
  9389. protected uint instr;
  9390. /*-------------------- Constructors ---------------------------------*/
  9391. public Instr(Op inst) {
  9392. instr = (uint)inst;
  9393. if (instr >= longInstrStart) {
  9394. instr -= longInstrStart;
  9395. twoByteInstr = true;
  9396. size++;
  9397. }
  9398. }
  9399. internal Instr(uint inst) {
  9400. instr = (uint)inst;
  9401. if (instr >= longInstrStart) {
  9402. instr -= longInstrStart;
  9403. twoByteInstr = true;
  9404. size++;
  9405. }
  9406. }
  9407. public Op GetOp() {
  9408. if (twoByteInstr)
  9409. return (Op)(longInstrStart + instr);
  9410. return (Op)instr;
  9411. }
  9412. internal override string GetInstName() {
  9413. Op opInst = GetOp();
  9414. return "" + opInst;
  9415. }
  9416. internal override void Write(PEWriter output) {
  9417. //Console.WriteLine("Writing instruction " + instr + " with size " + size);
  9418. if (twoByteInstr) output.Write(leadByte);
  9419. output.Write((byte)instr);
  9420. }
  9421. internal string GetInstrString() {
  9422. if (twoByteInstr) {
  9423. return FEopcode[instr] + " ";
  9424. } else {
  9425. return opcode[instr] + " ";
  9426. }
  9427. }
  9428. /// <summary>
  9429. /// Get the delta distance for this instruction.
  9430. /// </summary>
  9431. /// <remarks>
  9432. /// The delta distance is the resulting difference of items
  9433. /// left on the stack after calling this instruction.
  9434. /// </remarks>
  9435. /// <returns>An integer value representing the delta distance.</returns>
  9436. internal override int GetDeltaDistance() {
  9437. if (twoByteInstr) {
  9438. return FEopDeltaDistance[instr];
  9439. } else {
  9440. return opDeltaDistance[instr];
  9441. }
  9442. }
  9443. internal override void Write(CILWriter output) {
  9444. if (twoByteInstr) {
  9445. output.WriteLine(FEopcode[instr]);
  9446. } else {
  9447. output.WriteLine(opcode[instr]);
  9448. }
  9449. }
  9450. }
  9451. /**************************************************************************/
  9452. public class IntInstr : Instr {
  9453. int val;
  9454. bool byteNum;
  9455. /*-------------------- Constructors ---------------------------------*/
  9456. public IntInstr(IntOp inst, int num) : base((uint)inst) {
  9457. byteNum = inst == IntOp.ldc_i4_s;
  9458. val = num;
  9459. if (byteNum) size++;
  9460. else size += 4;
  9461. }
  9462. public int GetInt() { return val; }
  9463. public void SetInt(int num) { val = num; }
  9464. internal sealed override void Write(PEWriter output) {
  9465. base.Write(output);
  9466. if (byteNum)
  9467. output.Write((sbyte)val);
  9468. else
  9469. output.Write(val);
  9470. }
  9471. /// <summary>
  9472. /// Get the delta distance for this instruction.
  9473. /// </summary>
  9474. /// <remarks>
  9475. /// The delta distance is the resulting difference of items
  9476. /// left on the stack after calling this instruction.
  9477. /// </remarks>
  9478. /// <returns>An integer value representing the delta distance.</returns>
  9479. internal override int GetDeltaDistance() {
  9480. return opDeltaDistance[instr];
  9481. }
  9482. internal override void Write(CILWriter output) {
  9483. output.WriteLine(opcode[instr] + " " + val);
  9484. }
  9485. }
  9486. /**************************************************************************/
  9487. public class UIntInstr : Instr {
  9488. uint val;
  9489. bool byteNum;
  9490. /*-------------------- Constructors ---------------------------------*/
  9491. public UIntInstr(IntOp inst, uint num) : base((uint)inst) {
  9492. byteNum = (inst < IntOp.ldc_i4_s) || (inst == IntOp.unaligned);
  9493. val = num;
  9494. if (byteNum) size++;
  9495. else size += 2;
  9496. }
  9497. public uint GetUInt() { return val; }
  9498. public void SetUInt(uint num) { val = num; }
  9499. /// <summary>
  9500. /// Get the delta distance for this instruction.
  9501. /// </summary>
  9502. /// <remarks>
  9503. /// The delta distance is the resulting difference of items
  9504. /// left on the stack after calling this instruction.
  9505. /// </remarks>
  9506. /// <returns>An integer value representing the delta distance.</returns>
  9507. internal override int GetDeltaDistance() {
  9508. if (twoByteInstr) {
  9509. return FEopDeltaDistance[instr];
  9510. } else {
  9511. return opDeltaDistance[instr];
  9512. }
  9513. }
  9514. internal sealed override void Write(PEWriter output) {
  9515. base.Write(output);
  9516. if (byteNum)
  9517. output.Write((byte)val);
  9518. else
  9519. output.Write((ushort)val);
  9520. }
  9521. internal override void Write(CILWriter output) {
  9522. if (twoByteInstr) {
  9523. output.Write(FEopcode[instr]);
  9524. } else {
  9525. output.Write(opcode[instr]);
  9526. }
  9527. output.WriteLine(" " + val);
  9528. }
  9529. }
  9530. /**************************************************************************/
  9531. public class LongInstr : Instr {
  9532. long val;
  9533. /*-------------------- Constructors ---------------------------------*/
  9534. public LongInstr(SpecialOp inst, long l) : base((uint)inst) {
  9535. val = l;
  9536. size += 8;
  9537. }
  9538. public long GetLong() { return val; }
  9539. public void SetLong(long num) { val = num; }
  9540. internal sealed override void Write(PEWriter output) {
  9541. base.Write(output);
  9542. output.Write(val);
  9543. }
  9544. internal override void Write(CILWriter output) {
  9545. output.WriteLine("ldc.i8 " + val);
  9546. }
  9547. }
  9548. /**************************************************************************/
  9549. public class FloatInstr : Instr {
  9550. float fVal;
  9551. /*-------------------- Constructors ---------------------------------*/
  9552. public FloatInstr(SpecialOp inst, float f) : base((uint)inst) {
  9553. fVal = f;
  9554. size += 4;
  9555. }
  9556. public float GetFloat() { return fVal; }
  9557. public void SetFloat(float num) { fVal = num; }
  9558. internal sealed override void Write(PEWriter output) {
  9559. output.Write((byte)0x22);
  9560. output.Write(fVal);
  9561. }
  9562. internal override void Write(CILWriter output) {
  9563. output.WriteLine("ldc.r4 " + fVal);
  9564. }
  9565. }
  9566. /**************************************************************************/
  9567. public class DoubleInstr : Instr {
  9568. double val;
  9569. /*-------------------- Constructors ---------------------------------*/
  9570. public DoubleInstr(SpecialOp inst, double d) : base((uint)inst) {
  9571. val = d;
  9572. size += 8;
  9573. }
  9574. public double GetDouble() { return val; }
  9575. public void SetDouble(double num) { val = num; }
  9576. internal sealed override void Write(PEWriter output) {
  9577. base.Write(output);
  9578. output.Write(val);
  9579. }
  9580. internal override void Write(CILWriter output) {
  9581. output.WriteLine("ldc.r8 " + val);
  9582. }
  9583. }
  9584. /**************************************************************************/
  9585. public class StringInstr : Instr {
  9586. string val;
  9587. uint strIndex;
  9588. /*-------------------- Constructors ---------------------------------*/
  9589. public StringInstr(SpecialOp inst, string str) : base((uint)inst) {
  9590. val = str;
  9591. size += 4;
  9592. }
  9593. public string GetString() { return val; }
  9594. public void SetString(string str) { val = str; }
  9595. internal sealed override void BuildTables(MetaDataOut md) {
  9596. if (Diag.DiagOn) Console.WriteLine("Adding a code string to the US heap");
  9597. strIndex = md.AddToUSHeap(val);
  9598. }
  9599. internal sealed override void Write(PEWriter output) {
  9600. base.Write(output);
  9601. output.Write(USHeapIndex | strIndex);
  9602. }
  9603. internal override void Write(CILWriter output) {
  9604. output.WriteLine("ldstr \"" + val + "\"");
  9605. }
  9606. }
  9607. /**************************************************************************/
  9608. public class CILLabel : CILInstruction {
  9609. private static int labelNum = 0;
  9610. private int num = -1;
  9611. private CILInstructions buffer;
  9612. /*-------------------- Constructors ---------------------------------*/
  9613. public CILLabel() {
  9614. size = 0;
  9615. }
  9616. internal CILLabel(uint offs) {
  9617. size = 0;
  9618. offset = offs;
  9619. }
  9620. internal uint GetLabelOffset() {
  9621. return offset;
  9622. }
  9623. internal override string GetInstName() {
  9624. return "Label" + num;
  9625. }
  9626. internal CILInstructions Buffer {
  9627. get { return buffer; }
  9628. set { buffer = value; }
  9629. }
  9630. internal override void BuildCILInfo(CILWriter output) {
  9631. if (num == -1) {
  9632. num = labelNum++;
  9633. }
  9634. }
  9635. /// <summary>
  9636. /// Get the delta distance for this instruction.
  9637. /// </summary>
  9638. /// <remarks>
  9639. /// The delta distance is the resulting difference of items
  9640. /// left on the stack after calling this instruction.
  9641. /// </remarks>
  9642. /// <returns>An integer value representing the delta distance.</returns>
  9643. internal override int GetDeltaDistance() {
  9644. return 0;
  9645. }
  9646. internal override void Write(CILWriter output) {
  9647. output.WriteLine("Label" + num + ":");
  9648. }
  9649. }
  9650. /**************************************************************************/
  9651. /// <summary>
  9652. /// Abstract model for debug instructions.
  9653. /// </summary>
  9654. public abstract class DebugInst : CILInstruction { }
  9655. /**************************************************************************/
  9656. /// <summary>
  9657. /// Defines a line instruction.
  9658. /// </summary>
  9659. public class Line : DebugInst {
  9660. private static uint MaxCol = 100;
  9661. uint startLine, startCol, endLine, endCol;
  9662. bool hasEnd = false;
  9663. internal SourceFile sourceFile;
  9664. /*-------------------- Constructors ---------------------------------*/
  9665. /// <summary>
  9666. /// Create a new line instruction.
  9667. /// </summary>
  9668. /// <param name="sLine">Start of the line in the source file.</param>
  9669. /// <param name="sCol">Starting column in the source file.</param>
  9670. /// <param name="sFile">The filename of the souce file.</param>
  9671. internal Line(uint sLine, uint sCol, SourceFile sFile) {
  9672. startLine = sLine;
  9673. startCol = sCol;
  9674. sourceFile = sFile;
  9675. size = 0;
  9676. }
  9677. /// <summary>
  9678. /// Create a new line instruction.
  9679. /// </summary>
  9680. /// <param name="sLine">Start of the line in the source file.</param>
  9681. /// <param name="sCol">Starting column in the source file.</param>
  9682. /// <param name="eLine">Ending line in the source file.</param>
  9683. /// <param name="eCol">Ending column in the source file.</param>
  9684. /// <param name="sFile">The filename of the souce file.</param>
  9685. internal Line(uint sLine, uint sCol, uint eLine, uint eCol, SourceFile sFile) {
  9686. startLine = sLine;
  9687. startCol = sCol;
  9688. endLine = eLine;
  9689. endCol = eCol;
  9690. hasEnd = true;
  9691. sourceFile = sFile;
  9692. size = 0;
  9693. }
  9694. internal void CalcEnd(Line next) {
  9695. if (hasEnd) return;
  9696. if (sourceFile != next.sourceFile) {
  9697. endLine = startLine;
  9698. endCol = MaxCol;
  9699. } else {
  9700. endLine = next.startLine;
  9701. endCol = next.startCol;
  9702. if (endCol < 0) endCol = MaxCol;
  9703. }
  9704. hasEnd = true;
  9705. }
  9706. internal void Last() {
  9707. if (hasEnd) return;
  9708. endLine = startLine;
  9709. endCol = MaxCol;
  9710. hasEnd = true;
  9711. }
  9712. /// <summary>
  9713. /// Get the name of this instruction.
  9714. /// </summary>
  9715. /// <returns>A string with the value ".line".</returns>
  9716. internal override string GetInstName() {
  9717. return ".line";
  9718. }
  9719. /// <summary>
  9720. /// Write this instruction to a PDB file.
  9721. /// </summary>
  9722. /// <param name="output">The PE writer being used to write the PE and PDB files.</param>
  9723. internal override void Write(PEWriter output) {
  9724. string sf = "";
  9725. Guid doclang = Guid.Empty;
  9726. Guid docvend = Guid.Empty;
  9727. Guid doctype = Guid.Empty;
  9728. if (sourceFile != null) {
  9729. sf = sourceFile.name;
  9730. doclang = sourceFile.language;
  9731. docvend = sourceFile.vendor;
  9732. doctype = sourceFile.document;
  9733. }
  9734. if (output.pdbWriter != null)
  9735. output.pdbWriter.AddSequencePoint(sf, doclang, docvend, doctype, offset,
  9736. startLine, startCol, endLine, endCol);
  9737. }
  9738. /// <summary>
  9739. /// Get the delta distance for this instruction.
  9740. /// </summary>
  9741. /// <remarks>
  9742. /// The delta distance is the resulting difference of items
  9743. /// left on the stack after calling this instruction.
  9744. /// </remarks>
  9745. /// <returns>An integer value representing the delta distance.</returns>
  9746. internal override int GetDeltaDistance() {
  9747. return 0;
  9748. }
  9749. /// <summary>
  9750. /// Write out a line instruction to the CIL file.
  9751. /// </summary>
  9752. /// <param name="output">The CIL instruction writer to use to write this instruction.</param>
  9753. internal override void Write(CILWriter output) {
  9754. if (output.Debug) {
  9755. string lineDetails = startLine + ", " + startCol;
  9756. if (hasEnd) {
  9757. lineDetails += ", " + endLine + ", " + endCol;
  9758. if (sourceFile != null) {
  9759. lineDetails += ", " + sourceFile.Name;
  9760. }
  9761. }
  9762. output.WriteLine(".line " + lineDetails);
  9763. }
  9764. }
  9765. }
  9766. /**************************************************************************/
  9767. /// <summary>
  9768. /// A local binding instruction that can be added to a list of CILInstructions.
  9769. /// </summary>
  9770. public class LocalBinding : DebugInst {
  9771. internal int _index;
  9772. internal string _name;
  9773. internal DebugLocalSig _debugsig;
  9774. /*-------------------- Constructors ---------------------------------*/
  9775. /// <summary>
  9776. /// Create a new local binding object.
  9777. /// </summary>
  9778. /// <param name="index">The index of the local in the locals tables.</param>
  9779. /// <param name="name">The name of the local.</param>
  9780. internal LocalBinding(int index, string name)
  9781. {
  9782. _index = index;
  9783. _name = name;
  9784. }
  9785. /// <summary>
  9786. /// The index of the local in the locals table.
  9787. /// </summary>
  9788. public int Index {
  9789. get { return _index; }
  9790. }
  9791. /// <summary>
  9792. /// The name of the local binding.
  9793. /// </summary>
  9794. public string Name {
  9795. get { return _name; }
  9796. }
  9797. /// <summary>
  9798. /// Get the delta distance for this instruction.
  9799. /// </summary>
  9800. /// <remarks>
  9801. /// The delta distance is the resulting difference of items
  9802. /// left on the stack after calling this instruction.
  9803. /// </remarks>
  9804. /// <returns>An integer value representing the delta distance.</returns>
  9805. internal override int GetDeltaDistance() {
  9806. return 0;
  9807. }
  9808. /// <summary>
  9809. /// Get the name of this instruction.
  9810. /// </summary>
  9811. /// <returns>A string with the name of this instruction.</returns>
  9812. internal override string GetInstName() {
  9813. return "debug - local binding";
  9814. }
  9815. }
  9816. /**************************************************************************/
  9817. /// <summary>
  9818. /// Used to delcare constants that exist in a given scope.
  9819. /// </summary>
  9820. public class ConstantBinding : DebugInst {
  9821. private string _name;
  9822. private object _value;
  9823. private Type _type;
  9824. private uint _token;
  9825. /*-------------------- Constructors ---------------------------------*/
  9826. /// <summary>
  9827. /// Create a new constant binding.
  9828. /// </summary>
  9829. /// <param name="name">The name of the constant.</param>
  9830. /// <param name="value">The value of the constant.</param>
  9831. /// <param name="type">The data type of the constant.</param>
  9832. internal ConstantBinding(string name, object value, Type type, uint token) {
  9833. _value = value;
  9834. _name = name;
  9835. _type = type;
  9836. _token = token;
  9837. }
  9838. /// <summary>
  9839. /// Value of the constant.
  9840. /// </summary>
  9841. public object Value {
  9842. get { return _value; }
  9843. }
  9844. /// <summary>
  9845. /// The name of the constant.
  9846. /// </summary>
  9847. public string Name {
  9848. get { return _name; }
  9849. }
  9850. /// <summary>
  9851. /// The data type of the constant.
  9852. /// </summary>
  9853. public Type Type {
  9854. get { return _type; }
  9855. }
  9856. /// <summary>
  9857. /// The token for this constant.
  9858. /// </summary>
  9859. public uint Token {
  9860. get { return _token; }
  9861. }
  9862. /// <summary>
  9863. /// Get the type signature for this constant.
  9864. /// </summary>
  9865. /// <returns>A byte array of the type signature.</returns>
  9866. public byte[] GetSig() {
  9867. MemoryStream str = new MemoryStream();
  9868. _type.TypeSig(str);
  9869. return str.ToArray();
  9870. }
  9871. /// <summary>
  9872. /// Get the name of this instruction.
  9873. /// </summary>
  9874. /// <returns>A string with the name of this instruction.</returns>
  9875. internal override string GetInstName() {
  9876. return "debug - constant binding";
  9877. }
  9878. /// <summary>
  9879. /// Get the delta distance for this instruction.
  9880. /// </summary>
  9881. /// <remarks>
  9882. /// The delta distance is the resulting difference of items
  9883. /// left on the stack after calling this instruction.
  9884. /// </remarks>
  9885. /// <returns>An integer value representing the delta distance.</returns>
  9886. internal override int GetDeltaDistance() {
  9887. return 0;
  9888. }
  9889. }
  9890. /*************************************************************************/
  9891. public class Scope {
  9892. private ArrayList _localBindings = new ArrayList();
  9893. private ArrayList _constantBindings = new ArrayList();
  9894. internal Scope _parent;
  9895. internal MethodDef _thisMeth;
  9896. internal Scope(MethodDef thisMeth) : this(null, thisMeth) {
  9897. }
  9898. internal Scope(Scope parent, MethodDef thisMeth) {
  9899. _thisMeth = thisMeth;
  9900. _parent = parent;
  9901. }
  9902. /// <summary>
  9903. /// Add a constant to this scope.
  9904. /// </summary>
  9905. /// <param name="name">The name of the constant.</param>
  9906. /// <param name="value">The value of the constant.</param>
  9907. /// <param name="type">The type of the constant.</param>
  9908. /// <returns>The ConstantBinding object for the new constant.</returns>
  9909. internal ConstantBinding AddConstantBinding(string name, object value, Type type) {
  9910. ConstantBinding binding;
  9911. if ((binding = FindConstantBinding(name)) != null)
  9912. return binding;
  9913. binding = new ConstantBinding(name, value, type, _thisMeth.locToken);
  9914. _constantBindings.Add(binding);
  9915. return binding;
  9916. }
  9917. /// <summary>
  9918. /// Find a constant in this scope.
  9919. /// </summary>
  9920. /// <param name="name">The name of the constant.</param>
  9921. /// <returns>The ConstantBinding object of this constant.</returns>
  9922. internal ConstantBinding FindConstantBinding(string name) {
  9923. foreach (ConstantBinding binding in _constantBindings)
  9924. if (binding.Name == name)
  9925. return binding;
  9926. return null;
  9927. }
  9928. /// <summary>
  9929. /// Provide a complete list of all constants bound in this scope.
  9930. /// </summary>
  9931. public ConstantBinding[] ConstantBindings {
  9932. get { return (ConstantBinding[])_constantBindings.ToArray(typeof(ConstantBinding)); }
  9933. }
  9934. internal LocalBinding AddLocalBinding(string name, int index) {
  9935. LocalBinding binding;
  9936. if ((binding = FindLocalBinding(name)) != null)
  9937. return binding;
  9938. binding = new LocalBinding(index, name);
  9939. _localBindings.Add(binding);
  9940. return binding;
  9941. }
  9942. internal LocalBinding FindLocalBinding(string name) {
  9943. foreach (LocalBinding binding in _localBindings)
  9944. if (binding._name == name)
  9945. return binding;
  9946. return null;
  9947. }
  9948. internal LocalBinding FindLocalBinding(int index) {
  9949. foreach (LocalBinding binding in _localBindings)
  9950. if (binding._index == index)
  9951. return binding;
  9952. return null;
  9953. }
  9954. public LocalBinding[] LocalBindings {
  9955. get { return (LocalBinding[]) _localBindings.ToArray(typeof(LocalBinding)); }
  9956. }
  9957. internal void BuildSignatures(MetaDataOut md) {
  9958. if (!md.Debug) return;
  9959. try {
  9960. Local[] locals = _thisMeth.GetLocals();
  9961. foreach (LocalBinding binding in _localBindings) {
  9962. if (binding._debugsig == null) {
  9963. locals[binding._index].BuildTables(md);
  9964. binding._debugsig = md.GetDebugSig(locals[binding._index]);
  9965. }
  9966. binding._debugsig.BuildMDTables(md);
  9967. }
  9968. } catch (Exception e) {
  9969. throw new Exception("Exception while writing debug info for: " +
  9970. this._thisMeth.NameString()+"\r\n"+e.ToString());
  9971. }
  9972. }
  9973. internal void WriteLocals(PDBWriter writer) {
  9974. try {
  9975. Local[] locals = _thisMeth.GetLocals();
  9976. foreach (LocalBinding binding in _localBindings) {
  9977. writer.BindLocal(binding._name, binding._index, _thisMeth.locToken,0,0);
  9978. }
  9979. } catch (Exception e) {
  9980. throw new Exception("Exception while writing debug info for: " +
  9981. this._thisMeth.NameString()+"\r\n"+e.ToString(),e);
  9982. }
  9983. }
  9984. /* Constants does not work. AKB 2007-02-03
  9985. internal void WriteConstants(PDBWriter writer) {
  9986. try {
  9987. // Add each constant to the current scope
  9988. foreach (ConstantBinding binding in _constantBindings)
  9989. writer.BindConstant(binding);
  9990. } catch (Exception e) {
  9991. throw new Exception("Exception while writing debug info for: " +
  9992. this._thisMeth.NameString() + "\r\n" + e.ToString(), e);
  9993. }
  9994. }
  9995. */
  9996. }
  9997. /*************************************************************************/
  9998. /// <summary>
  9999. /// A marker instruction for when a scope should be opened in the sequence of instructions.
  10000. /// </summary>
  10001. public class OpenScope : DebugInst {
  10002. internal Scope _scope;
  10003. /// <summary>
  10004. /// Create a new OpenScope instruction.
  10005. /// </summary>
  10006. /// <param name="scope">The scope that is being opened.</param>
  10007. public OpenScope(Scope scope) {
  10008. size = 0;
  10009. _scope = scope;
  10010. }
  10011. /// <summary>
  10012. /// Get the name for this instruction.
  10013. /// </summary>
  10014. /// <returns>A string with the name of the instruction.</returns>
  10015. internal override string GetInstName() {
  10016. return "debug - open scope";
  10017. }
  10018. /// <summary>
  10019. /// Build the signatures for this instruction.
  10020. /// </summary>
  10021. /// <param name="md">The meta data table to write the instructions to.</param>
  10022. internal void BuildSignatures(MetaDataOut md) {
  10023. _scope.BuildSignatures(md);
  10024. }
  10025. /// <summary>
  10026. /// Get the delta distance for this instruction.
  10027. /// </summary>
  10028. /// <remarks>
  10029. /// The delta distance is the resulting difference of items
  10030. /// left on the stack after calling this instruction.
  10031. /// </remarks>
  10032. /// <returns>An integer value representing the delta distance.</returns>
  10033. ///
  10034. internal override int GetDeltaDistance() {
  10035. return 0;
  10036. }
  10037. /// <summary>
  10038. /// Write this instruction to the PDB file.
  10039. /// </summary>
  10040. /// <param name="output">The PEWriter being used to write the PE and PDB files.</param>
  10041. internal override void Write(PEWriter output) {
  10042. if (output.pdbWriter != null) {
  10043. output.pdbWriter.OpenScope((int) offset);
  10044. _scope.WriteLocals(output.pdbWriter);
  10045. /* Constants do not work. AKB 2007-02-03
  10046. * _scope.WriteConstants(output.pdbWriter);
  10047. */
  10048. }
  10049. }
  10050. }
  10051. /************************************************************************/
  10052. /// <summary>
  10053. /// A marker instruction for when a scope should be closed.
  10054. /// </summary>
  10055. public class CloseScope : DebugInst {
  10056. internal Scope _scope;
  10057. /// <summary>
  10058. /// The constructor to build a new CloseScope instruction.
  10059. /// </summary>
  10060. /// <param name="scope">The scope to close.</param>
  10061. public CloseScope(Scope scope) {
  10062. size = 0;
  10063. _scope = scope;
  10064. }
  10065. /// <summary>
  10066. /// Provide access to the name of this instruction.
  10067. /// </summary>
  10068. /// <returns>A string containing the name of this instruction.</returns>
  10069. internal override string GetInstName() {
  10070. return "debug - close scope";
  10071. }
  10072. /// <summary>
  10073. /// Get the delta distance for this instruction.
  10074. /// </summary>
  10075. /// <remarks>
  10076. /// The delta distance is the resulting difference of items
  10077. /// left on the stack after calling this instruction.
  10078. /// </remarks>
  10079. /// <returns>An integer value representing the delta distance.</returns>
  10080. internal override int GetDeltaDistance() {
  10081. return 0;
  10082. }
  10083. /// <summary>
  10084. /// Write this instruction. This instruction does not get written
  10085. /// to the PE file. It only applys to the PDB file.
  10086. /// </summary>
  10087. /// <param name="output">The PEWriter that is writing the PE file.</param>
  10088. internal override void Write(PEWriter output) {
  10089. if (output.pdbWriter != null)
  10090. output.pdbWriter.CloseScope((int) offset);
  10091. }
  10092. }
  10093. /**************************************************************************/
  10094. public class FieldInstr : Instr {
  10095. Field field;
  10096. /*-------------------- Constructors ---------------------------------*/
  10097. public FieldInstr(FieldOp inst, Field f) : base((uint)inst) {
  10098. field = f;
  10099. size += 4;
  10100. }
  10101. public Field GetField() { return field; }
  10102. public void SetField(Field fld) { field = fld; }
  10103. internal override string GetInstName() {
  10104. return "" + (FieldOp)instr;
  10105. }
  10106. internal sealed override void BuildTables(MetaDataOut md) {
  10107. if (field == null) throw new InstructionException(IType.fieldOp,instr);
  10108. if (field is FieldRef) field.BuildMDTables(md);
  10109. }
  10110. internal override void BuildCILInfo(CILWriter output) {
  10111. if (field == null) throw new InstructionException(IType.fieldOp,instr);
  10112. if (field is FieldRef) field.BuildCILInfo(output);
  10113. }
  10114. internal sealed override void Write(PEWriter output) {
  10115. base.Write(output);
  10116. output.Write(field.Token());
  10117. }
  10118. internal override void Write(CILWriter output) {
  10119. output.Write(GetInstrString());
  10120. field.WriteType(output);
  10121. output.WriteLine();
  10122. }
  10123. }
  10124. /**************************************************************************/
  10125. public class MethInstr : Instr {
  10126. Method meth;
  10127. /*-------------------- Constructors ---------------------------------*/
  10128. public MethInstr(MethodOp inst, Method m) : base((uint)inst) {
  10129. meth = m;
  10130. size += 4;
  10131. }
  10132. public Method GetMethod() { return meth; }
  10133. public void SetMethod(Method mth) { meth = mth; }
  10134. internal override string GetInstName() {
  10135. return "" + (MethodOp)instr;
  10136. }
  10137. internal sealed override void BuildTables(MetaDataOut md) {
  10138. if (meth == null)
  10139. throw new InstructionException(IType.methOp,instr);
  10140. if ((meth is MethodRef) || (meth is MethodSpec)) meth.BuildMDTables(md);
  10141. }
  10142. internal override void BuildCILInfo(CILWriter output) {
  10143. if (meth == null) throw new InstructionException(IType.methOp,instr);
  10144. if ((meth is MethodRef) || (meth is MethodSpec)) meth.BuildCILInfo(output);
  10145. }
  10146. /// <summary>
  10147. /// Get the MethodOp this instruction represents.
  10148. /// </summary>
  10149. /// <returns>The method operator from the MethodOp enum.</returns>
  10150. public MethodOp GetMethodOp() {
  10151. return (MethodOp)instr;
  10152. }
  10153. /// <summary>
  10154. /// Get the delta distance for this instruction.
  10155. /// </summary>
  10156. /// <remarks>
  10157. /// The delta distance is the resulting difference of items
  10158. /// left on the stack after calling this instruction.
  10159. /// </remarks>
  10160. /// <returns>An integer value representing the delta distance.</returns>
  10161. internal override int GetDeltaDistance() {
  10162. switch ((MethodOp)instr) {
  10163. case MethodOp.callvirt:
  10164. case MethodOp.call: {
  10165. // Add the parameter count to the depth
  10166. int depth = (int)meth.GetSig().numPars * -1;
  10167. // Check to see if this is an instance method
  10168. if (meth.GetSig().HasCallConv(CallConv.Instance)) depth--;
  10169. // Check to see if this method uses the optional parameters
  10170. if (meth.GetSig().HasCallConv(CallConv.Vararg)) depth += (int)meth.GetSig().numOptPars * -1;
  10171. // Check to see if this method uses the generic parameters
  10172. if (meth.GetSig().HasCallConv(CallConv.Generic)) depth += (int)meth.GetSig().numGenPars * -1;
  10173. // Check if a return value will be placed on the stack.
  10174. if (!meth.GetRetType().SameType(PrimitiveType.Void)) depth++;
  10175. return depth;
  10176. }
  10177. case MethodOp.newobj: {
  10178. // Add the parameter count to the depth
  10179. int depth = (int)meth.GetSig().numPars * -1;
  10180. // Check to see if this method uses the optional parameters
  10181. if (meth.GetSig().HasCallConv(CallConv.Vararg)) depth += (int)meth.GetSig().numOptPars * -1;
  10182. // Check to see if this method uses the generic parameters
  10183. if (meth.GetSig().HasCallConv(CallConv.Generic)) depth += (int)meth.GetSig().numGenPars * -1;
  10184. // Add the object reference that is loaded onto the stack
  10185. depth++;
  10186. return depth;
  10187. }
  10188. case MethodOp.ldtoken:
  10189. case MethodOp.ldftn:
  10190. return 1;
  10191. case MethodOp.jmp:
  10192. case MethodOp.ldvirtfn:
  10193. return 0;
  10194. default:
  10195. // Someone has added a new MethodOp and not added a case for it here.
  10196. throw new Exception("The MethodOp for this MethoInstr is not supported.");
  10197. }
  10198. }
  10199. internal sealed override void Write(PEWriter output) {
  10200. base.Write(output);
  10201. output.Write(meth.Token());
  10202. }
  10203. internal override void Write(CILWriter output) {
  10204. output.Write(GetInstrString());
  10205. meth.WriteType(output);
  10206. output.WriteLine();
  10207. }
  10208. }
  10209. /**************************************************************************/
  10210. public class SigInstr : Instr {
  10211. CalliSig signature;
  10212. /*-------------------- Constructors ---------------------------------*/
  10213. public SigInstr(SpecialOp inst, CalliSig sig) : base((uint)inst) {
  10214. signature = sig;
  10215. size += 4;
  10216. }
  10217. public CalliSig GetSig() { return signature; }
  10218. public void SetSig(CalliSig sig) { signature = sig; }
  10219. internal override string GetInstName() {
  10220. return "" + (SpecialOp)instr;
  10221. }
  10222. /// <summary>
  10223. /// Get the delta distance for this instruction.
  10224. /// </summary>
  10225. /// <remarks>
  10226. /// The delta distance is the resulting difference of items
  10227. /// left on the stack after calling this instruction.
  10228. /// </remarks>
  10229. /// <returns>An integer value representing the delta distance.</returns>
  10230. internal override int GetDeltaDistance() {
  10231. // Add the parameter count to the depth
  10232. int depth = (int)signature.NumPars * -1;
  10233. // Check to see if this is an instance method
  10234. if (signature.HasCallConv(CallConv.Instance)) depth--;
  10235. // Check to see if this method uses the optional parameters
  10236. if (signature.HasCallConv(CallConv.Vararg)) depth += (int)signature.NumOptPars * -1;
  10237. // Check if a return value will be placed on the stack.
  10238. if (signature.ReturnType.SameType(PrimitiveType.Void)) depth++;
  10239. return depth;
  10240. }
  10241. internal sealed override void BuildTables(MetaDataOut md) {
  10242. if (signature == null) throw new InstructionException(IType.specialOp,instr);
  10243. signature.BuildMDTables(md);
  10244. }
  10245. internal override void BuildCILInfo(CILWriter output) {
  10246. if (signature == null) throw new InstructionException(IType.specialOp,instr);
  10247. signature.BuildCILInfo(output);
  10248. }
  10249. internal sealed override void Write(PEWriter output) {
  10250. base.Write(output);
  10251. output.Write(signature.Token());
  10252. }
  10253. internal override void Write(CILWriter output) {
  10254. output.Write(GetInstrString());
  10255. signature.Write(output);
  10256. output.WriteLine();
  10257. }
  10258. }
  10259. /**************************************************************************/
  10260. public class TypeInstr : Instr {
  10261. Type theType;
  10262. /*-------------------- Constructors ---------------------------------*/
  10263. public TypeInstr(TypeOp inst, Type aType) : base((uint)inst) {
  10264. theType = aType;
  10265. size += 4;
  10266. }
  10267. public Type GetTypeArg() { return theType; }
  10268. public void SetTypeArg(Type ty) { theType = ty; }
  10269. internal override string GetInstName() {
  10270. return "" + (TypeOp)instr;
  10271. }
  10272. internal sealed override void BuildTables(MetaDataOut md) {
  10273. if (theType == null) throw new InstructionException(IType.typeOp,instr);
  10274. theType = theType.AddTypeSpec(md);
  10275. }
  10276. internal override void BuildCILInfo(CILWriter output) {
  10277. if (theType == null) throw new InstructionException(IType.typeOp,instr);
  10278. if (!theType.isDef()) {
  10279. theType.BuildCILInfo(output);
  10280. }
  10281. }
  10282. internal sealed override void Write(PEWriter output) {
  10283. base.Write(output);
  10284. output.Write(theType.Token());
  10285. }
  10286. internal override void Write(CILWriter output) {
  10287. output.Write(GetInstrString());
  10288. theType.WriteName(output);
  10289. output.WriteLine();
  10290. }
  10291. }
  10292. /**************************************************************************/
  10293. public class BranchInstr : Instr {
  10294. CILLabel dest;
  10295. private bool shortVer = true;
  10296. private static readonly byte longInstrOffset = 13;
  10297. private int target = 0;
  10298. /*-------------------- Constructors ---------------------------------*/
  10299. public BranchInstr(BranchOp inst, CILLabel dst) : base((uint)inst) {
  10300. dest = dst;
  10301. shortVer = (inst < BranchOp.br) || (inst == BranchOp.leave_s);
  10302. if (shortVer)
  10303. size++;
  10304. else
  10305. size += 4;
  10306. }
  10307. internal BranchInstr(uint inst, int dst) : base(inst) {
  10308. target = dst;
  10309. shortVer = (inst < (uint)BranchOp.br) || (inst == (uint)BranchOp.leave_s);
  10310. if (shortVer)
  10311. size++;
  10312. else
  10313. size += 4;
  10314. }
  10315. public CILLabel GetDest() { return dest; }
  10316. public void SetDest(CILLabel lab) { dest = lab; }
  10317. /// <summary>
  10318. /// Provide access to the branch operator
  10319. /// </summary>
  10320. /// <returns>The branch operator from the BranchOp enum that this instruction represents.</returns>
  10321. public BranchOp GetBranchOp() {
  10322. return (BranchOp)instr;
  10323. }
  10324. internal override string GetInstName() {
  10325. return "" + (BranchOp)instr;
  10326. }
  10327. internal void MakeTargetLabel(ArrayList labs) {
  10328. uint targetOffset = (uint)(offset + size + target);
  10329. dest = CILInstructions.GetLabel(labs,targetOffset);
  10330. }
  10331. internal sealed override bool Check(MetaDataOut md) {
  10332. target = (int)dest.GetLabelOffset() - (int)(offset + size);
  10333. if ((target < minByteVal) || (target > maxByteVal)) { // check for longver
  10334. if (shortVer) {
  10335. if (instr == (uint)BranchOp.leave_s)
  10336. instr = (uint)BranchOp.leave;
  10337. else
  10338. instr = instr += longInstrOffset;
  10339. size += 3;
  10340. shortVer = false;
  10341. return true;
  10342. }
  10343. } else if (!shortVer) { // check for short ver
  10344. if (instr == (uint)BranchOp.leave)
  10345. instr = (uint)BranchOp.leave_s;
  10346. else
  10347. instr = instr -= longInstrOffset;
  10348. size -= 3;
  10349. shortVer = true;
  10350. return true;
  10351. }
  10352. /*
  10353. if (shortVer && ((target < minByteVal) || (target > maxByteVal))) {
  10354. if (instr < (int)BranchOp.leave) instr += longInstrOffset;
  10355. else instr--;
  10356. shortVer = false;
  10357. size += 3;
  10358. return true;
  10359. }
  10360. */
  10361. return false;
  10362. }
  10363. internal sealed override void Write(PEWriter output) {
  10364. base.Write(output);
  10365. if (shortVer)
  10366. output.Write((sbyte)target);
  10367. else
  10368. output.Write(target);
  10369. }
  10370. internal override void Write(CILWriter output) {
  10371. output.WriteLine(GetInstrString() + dest.GetInstName());
  10372. }
  10373. }
  10374. /**************************************************************************/
  10375. public class SwitchInstr : Instr {
  10376. CILLabel[] cases;
  10377. uint numCases = 0;
  10378. int[] targets;
  10379. /*-------------------- Constructors ---------------------------------*/
  10380. public SwitchInstr(CILLabel[] dsts) : base(0x45) {
  10381. cases = dsts;
  10382. if (cases != null) numCases = (uint)cases.Length;
  10383. size += 4 + (numCases * 4);
  10384. }
  10385. internal SwitchInstr(int[] offsets) : base(0x45) {
  10386. numCases = (uint)offsets.Length;
  10387. targets = offsets;
  10388. size += 4 + (numCases * 4);
  10389. }
  10390. public CILLabel[] GetDests() { return cases; }
  10391. public void SetDests(CILLabel[] dests) { cases = dests; }
  10392. internal override string GetInstName() {
  10393. return "switch";
  10394. }
  10395. internal void MakeTargetLabels(ArrayList labs) {
  10396. cases = new CILLabel[numCases];
  10397. for (int i=0; i < numCases; i++) {
  10398. cases[i] = CILInstructions.GetLabel(labs,(uint)(offset + size + targets[i]));
  10399. }
  10400. }
  10401. internal sealed override void Write(PEWriter output) {
  10402. base.Write(output);
  10403. output.Write(numCases);
  10404. for (int i=0; i < numCases; i++) {
  10405. int target = (int)cases[i].GetLabelOffset() - (int)(offset + size);
  10406. output.Write(target);
  10407. }
  10408. }
  10409. internal override void Write(CILWriter output) {
  10410. throw new NotImplementedException("Switch instruction for CIL");
  10411. }
  10412. }
  10413. /**************************************************************************/
  10414. internal enum EHClauseType {Exception, Filter, Finally, Fault = 4 }
  10415. internal class EHClause {
  10416. EHClauseType clauseType;
  10417. uint tryOffset, tryLength, handlerOffset, handlerLength, filterOffset = 0;
  10418. MetaDataElement classToken = null;
  10419. internal EHClause(EHClauseType cType, uint tOff, uint tLen, uint hOff, uint hLen) {
  10420. clauseType = cType;
  10421. tryOffset = tOff;
  10422. tryLength = tLen;
  10423. handlerOffset = hOff;
  10424. handlerLength = hLen;
  10425. }
  10426. internal void ClassToken(MetaDataElement cToken) {
  10427. classToken = cToken;
  10428. }
  10429. internal void FilterOffset(uint fOff) {
  10430. filterOffset = fOff;
  10431. }
  10432. internal TryBlock MakeTryBlock(ArrayList labels) {
  10433. TryBlock tBlock = new TryBlock(CILInstructions.GetLabel(labels,tryOffset),
  10434. CILInstructions.GetLabel(labels,tryOffset + tryLength));
  10435. CILLabel hStart = CILInstructions.GetLabel(labels,handlerOffset);
  10436. CILLabel hEnd = CILInstructions.GetLabel(labels,handlerOffset+handlerLength);
  10437. HandlerBlock handler = null;
  10438. switch (clauseType) {
  10439. case (EHClauseType.Exception) :
  10440. handler = new Catch((Class)classToken,hStart,hEnd);
  10441. break;
  10442. case (EHClauseType.Filter) :
  10443. handler = new Filter(CILInstructions.GetLabel(labels,filterOffset),hStart,hEnd);
  10444. break;
  10445. case (EHClauseType.Finally) :
  10446. handler = new Finally(hStart,hEnd);
  10447. break;
  10448. case (EHClauseType.Fault) :
  10449. handler = new Fault(hStart,hEnd);
  10450. break;
  10451. }
  10452. tBlock.AddHandler(handler);
  10453. return tBlock;
  10454. }
  10455. }
  10456. /**************************************************************************/
  10457. public abstract class CodeBlock {
  10458. private static readonly int maxCodeSize = 255;
  10459. protected CILLabel start, end;
  10460. protected bool small = true;
  10461. /*-------------------- Constructors ---------------------------------*/
  10462. public CodeBlock(CILLabel start, CILLabel end) {
  10463. this.start = start;
  10464. this.end = end;
  10465. }
  10466. /// <summary>
  10467. /// The label that marks the start of this code block
  10468. /// </summary>
  10469. public CILLabel Start { get { return start; } }
  10470. /// <summary>
  10471. /// The label that marks the end of this code block
  10472. /// </summary>
  10473. public CILLabel End { get { return end; } }
  10474. internal virtual bool isFat() {
  10475. // Console.WriteLine("block start = " + start.GetLabelOffset() +
  10476. // " block end = " + end.GetLabelOffset());
  10477. return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
  10478. }
  10479. internal virtual void Write(PEWriter output, bool fatFormat) {
  10480. if (fatFormat) output.Write(start.GetLabelOffset());
  10481. else output.Write((short)start.GetLabelOffset());
  10482. uint len = end.GetLabelOffset() - start.GetLabelOffset();
  10483. if (Diag.DiagOn) Console.WriteLine("block start = " + start.GetLabelOffset() + " len = " + len);
  10484. if (fatFormat) output.Write(len);
  10485. else output.Write((byte)len);
  10486. }
  10487. }
  10488. /**************************************************************************/
  10489. /// <summary>
  10490. /// The descriptor for a guarded block (.try)
  10491. /// </summary>
  10492. public class TryBlock : CodeBlock {
  10493. protected bool fatFormat = false;
  10494. protected ushort flags = 0;
  10495. ArrayList handlers = new ArrayList();
  10496. /*-------------------- Constructors ---------------------------------*/
  10497. /// <summary>
  10498. /// Create a new try block
  10499. /// </summary>
  10500. /// <param name="start">start label for the try block</param>
  10501. /// <param name="end">end label for the try block</param>
  10502. public TryBlock(CILLabel start, CILLabel end) : base(start,end) { }
  10503. /// <summary>
  10504. /// Add a handler to this try block
  10505. /// </summary>
  10506. /// <param name="handler">a handler to be added to the try block</param>
  10507. public void AddHandler(HandlerBlock handler) {
  10508. //flags = handler.GetFlag();
  10509. handlers.Add(handler);
  10510. }
  10511. /// <summary>
  10512. /// Get an array containing all the handlers.
  10513. /// </summary>
  10514. /// <returns>The list of handlers.</returns>
  10515. public HandlerBlock[] GetHandlers() {
  10516. return (HandlerBlock[])handlers.ToArray(typeof(HandlerBlock));
  10517. }
  10518. internal void SetSize() {
  10519. fatFormat = base.isFat();
  10520. if (fatFormat) return;
  10521. for (int i=0; i < handlers.Count; i++) {
  10522. HandlerBlock handler = (HandlerBlock)handlers[i];
  10523. if (handler.isFat()) {
  10524. fatFormat = true;
  10525. return;
  10526. }
  10527. }
  10528. }
  10529. internal int NumHandlers() {
  10530. return handlers.Count;
  10531. }
  10532. internal override bool isFat() {
  10533. return fatFormat;
  10534. }
  10535. internal void BuildTables(MetaDataOut md) {
  10536. for (int i=0; i < handlers.Count; i++) {
  10537. ((HandlerBlock)handlers[i]).BuildTables(md);
  10538. }
  10539. }
  10540. internal void BuildCILInfo(CILWriter output) {
  10541. for (int i=0; i < handlers.Count; i++) {
  10542. ((HandlerBlock)handlers[i]).BuildCILInfo(output);
  10543. }
  10544. }
  10545. internal override void Write(PEWriter output, bool fatFormat) {
  10546. if (Diag.DiagOn) Console.WriteLine("writing exception details");
  10547. for (int i=0; i < handlers.Count; i++) {
  10548. if (Diag.DiagOn) Console.WriteLine("Except block " + i);
  10549. HandlerBlock handler = (HandlerBlock)handlers[i];
  10550. flags = handler.GetFlag();
  10551. if (Diag.DiagOn) Console.WriteLine("flags = " + flags);
  10552. if (fatFormat) output.Write((uint)flags);
  10553. else output.Write(flags);
  10554. base.Write(output,fatFormat);
  10555. handler.Write(output,fatFormat);
  10556. }
  10557. }
  10558. }
  10559. /**************************************************************************/
  10560. public abstract class HandlerBlock : CodeBlock {
  10561. protected static readonly ushort ExceptionFlag = 0;
  10562. protected static readonly ushort FilterFlag = 0x01;
  10563. protected static readonly ushort FinallyFlag = 0x02;
  10564. protected static readonly ushort FaultFlag = 0x04;
  10565. /*-------------------- Constructors ---------------------------------*/
  10566. public HandlerBlock(CILLabel start, CILLabel end) : base(start,end) { }
  10567. internal virtual ushort GetFlag() {
  10568. if (Diag.DiagOn) Console.WriteLine("Catch Block");
  10569. return ExceptionFlag;
  10570. }
  10571. internal virtual void BuildTables(MetaDataOut md) { }
  10572. internal virtual void BuildCILInfo(CILWriter output) { }
  10573. internal override void Write(PEWriter output, bool fatFormat) {
  10574. base.Write(output,fatFormat);
  10575. }
  10576. }
  10577. /**************************************************************************/
  10578. /// <summary>
  10579. /// The descriptor for a catch clause (.catch)
  10580. /// </summary>
  10581. public class Catch : HandlerBlock {
  10582. Class exceptType;
  10583. /*-------------------- Constructors ---------------------------------*/
  10584. /// <summary>
  10585. /// Create a new catch clause
  10586. /// </summary>
  10587. /// <param name="except">the exception to be caught</param>
  10588. /// <param name="handlerStart">start of the handler code</param>
  10589. /// <param name="handlerEnd">end of the handler code</param>
  10590. public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
  10591. : base(handlerStart,handlerEnd) {
  10592. exceptType = except;
  10593. }
  10594. internal override void BuildTables(MetaDataOut md) {
  10595. if (!(exceptType is ClassDef)) exceptType.BuildMDTables(md);
  10596. }
  10597. internal override void BuildCILInfo(CILWriter output) {
  10598. if (!(exceptType is ClassDef)) exceptType.BuildCILInfo(output);
  10599. }
  10600. internal override void Write(PEWriter output, bool fatFormat) {
  10601. base.Write(output,fatFormat);
  10602. output.Write(exceptType.Token());
  10603. }
  10604. }
  10605. /**************************************************************************/
  10606. /// <summary>
  10607. /// The descriptor for a filter clause (.filter)
  10608. /// </summary>
  10609. public class Filter : HandlerBlock {
  10610. CILLabel filterLabel;
  10611. /*-------------------- Constructors ---------------------------------*/
  10612. /// <summary>
  10613. /// Create a new filter clause
  10614. /// </summary>
  10615. /// <param name="filterLabel">the label where the filter code starts</param>
  10616. /// <param name="handlerStart">the start of the handler code</param>
  10617. /// <param name="handlerEnd">the end of the handler code</param>
  10618. public Filter(CILLabel filterLabel, CILLabel handlerStart,
  10619. CILLabel handlerEnd) : base(handlerStart,handlerEnd) {
  10620. this.filterLabel = filterLabel;
  10621. }
  10622. internal override ushort GetFlag() {
  10623. if (Diag.DiagOn) Console.WriteLine("Filter Block");
  10624. return FilterFlag;
  10625. }
  10626. internal override void Write(PEWriter output, bool fatFormat) {
  10627. base.Write(output,fatFormat);
  10628. output.Write(filterLabel.GetLabelOffset());
  10629. }
  10630. }
  10631. /**************************************************************************/
  10632. /// <summary>
  10633. /// Descriptor for a finally block (.finally)
  10634. /// </summary>
  10635. public class Finally : HandlerBlock {
  10636. /*-------------------- Constructors ---------------------------------*/
  10637. /// <summary>
  10638. /// Create a new finally clause
  10639. /// </summary>
  10640. /// <param name="finallyStart">start of finally code</param>
  10641. /// <param name="finallyEnd">end of finally code</param>
  10642. public Finally(CILLabel finallyStart, CILLabel finallyEnd)
  10643. : base(finallyStart,finallyEnd) { }
  10644. internal override ushort GetFlag() {
  10645. if (Diag.DiagOn) Console.WriteLine("Finally Block");
  10646. return FinallyFlag;
  10647. }
  10648. internal override void Write(PEWriter output, bool fatFormat) {
  10649. base.Write(output,fatFormat);
  10650. output.Write((int)0);
  10651. }
  10652. }
  10653. /**************************************************************************/
  10654. /// <summary>
  10655. /// Descriptor for a fault block (.fault)
  10656. /// </summary>
  10657. public class Fault : HandlerBlock {
  10658. /*-------------------- Constructors ---------------------------------*/
  10659. /// <summary>
  10660. /// Create a new fault clause
  10661. /// </summary>
  10662. /// <param name="faultStart">start of the fault code</param>
  10663. /// <param name="faultEnd">end of the fault code</param>
  10664. public Fault(CILLabel faultStart, CILLabel faultEnd)
  10665. : base(faultStart,faultEnd) { }
  10666. internal override ushort GetFlag() {
  10667. if (Diag.DiagOn) Console.WriteLine("Fault Block");
  10668. return FaultFlag;
  10669. }
  10670. internal override void Write(PEWriter output, bool fatFormat) {
  10671. base.Write(output,fatFormat);
  10672. output.Write((int)0);
  10673. }
  10674. }
  10675. /**************************************************************************/
  10676. // Classes used to describe constant values
  10677. /**************************************************************************/
  10678. /// <summary>
  10679. /// Descriptor for a constant value, to be written in the blob heap
  10680. /// </summary>
  10681. public abstract class Constant {
  10682. protected uint size = 0;
  10683. internal ElementType type;
  10684. protected uint blobIndex;
  10685. internal MetaDataOut addedToBlobHeap;
  10686. /*-------------------- Constructors ---------------------------------*/
  10687. internal Constant() { }
  10688. internal virtual uint GetBlobIndex(MetaDataOut md) { return 0; }
  10689. internal uint GetSize() { return size; }
  10690. internal byte GetTypeIndex() { return (byte)type; }
  10691. internal virtual void Write(BinaryWriter bw) { }
  10692. internal virtual void Write(CILWriter output) {
  10693. throw new NotYetImplementedException("Constant values for CIL");
  10694. }
  10695. }
  10696. /**************************************************************************/
  10697. public abstract class BlobConstant : Constant { }
  10698. /**************************************************************************/
  10699. /// <summary>
  10700. /// Boolean constant
  10701. /// </summary>
  10702. public class BoolConst : BlobConstant {
  10703. bool val;
  10704. /*-------------------- Constructors ---------------------------------*/
  10705. /// <summary>
  10706. /// Create a new boolean constant with the value "val"
  10707. /// </summary>
  10708. /// <param name="val">value of this boolean constant</param>
  10709. public BoolConst(bool val) {
  10710. this.val = val;
  10711. size = 1;
  10712. type = ElementType.Boolean;
  10713. }
  10714. public bool GetBool() {
  10715. return val;
  10716. }
  10717. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  10718. if (addedToBlobHeap != md) {
  10719. if (val) blobIndex = md.AddToBlobHeap(1,1);
  10720. else blobIndex = md.AddToBlobHeap(0,1);
  10721. addedToBlobHeap = md;
  10722. }
  10723. return blobIndex;
  10724. }
  10725. internal sealed override void Write(BinaryWriter bw) {
  10726. if (val) bw.Write((sbyte)1);
  10727. else bw.Write((sbyte)0);
  10728. }
  10729. }
  10730. /**************************************************************************/
  10731. public class CharConst : BlobConstant {
  10732. char val;
  10733. /*-------------------- Constructors ---------------------------------*/
  10734. public CharConst(char val) {
  10735. this.val = val;
  10736. size = 2;
  10737. type = ElementType.Char;
  10738. }
  10739. internal CharConst(PEReader buff) {
  10740. val = buff.ReadChar();
  10741. size = 2;
  10742. type = ElementType.Char;
  10743. }
  10744. public char GetChar() { // KJG addition 2005-Mar-01
  10745. return val;
  10746. }
  10747. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  10748. if (addedToBlobHeap != md) {
  10749. blobIndex = md.AddToBlobHeap(val);
  10750. addedToBlobHeap = md;
  10751. }
  10752. return blobIndex;
  10753. }
  10754. internal sealed override void Write(BinaryWriter bw) {
  10755. bw.Write(val);
  10756. }
  10757. }
  10758. /**************************************************************************/
  10759. public class NullRefConst : BlobConstant {
  10760. /*-------------------- Constructors ---------------------------------*/
  10761. public NullRefConst() {
  10762. size = 4;
  10763. type = ElementType.Class;
  10764. }
  10765. internal NullRefConst(PEReader buff) {
  10766. uint junk = buff.ReadUInt32();
  10767. size = 4;
  10768. type = ElementType.Class;
  10769. }
  10770. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  10771. if (addedToBlobHeap != md) {
  10772. blobIndex = md.AddToBlobHeap(0,4);
  10773. addedToBlobHeap = md;
  10774. }
  10775. return blobIndex;
  10776. }
  10777. internal sealed override void Write(BinaryWriter bw) {
  10778. bw.Write((int)0);
  10779. }
  10780. }
  10781. /**************************************************************************/
  10782. /// <summary>
  10783. /// Constant array
  10784. /// </summary>
  10785. public class ArrayConst : BlobConstant {
  10786. Constant[] elements;
  10787. /*-------------------- Constructors ---------------------------------*/
  10788. public ArrayConst(Constant[] elems) {
  10789. type = ElementType.SZArray;
  10790. size = 5; // one byte for SZARRAY, 4 bytes for length
  10791. elements = elems;
  10792. for (int i=0; i < elements.Length; i++) {
  10793. size += elements[i].GetSize();
  10794. }
  10795. }
  10796. public Constant[] GetArray() {
  10797. return elements;
  10798. }
  10799. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  10800. if (addedToBlobHeap != md) {
  10801. MemoryStream str = new MemoryStream();
  10802. BinaryWriter bw = new BinaryWriter(str);
  10803. Write(bw);
  10804. blobIndex = md.AddToBlobHeap(str.ToArray());
  10805. addedToBlobHeap = md;
  10806. }
  10807. return blobIndex;
  10808. }
  10809. internal sealed override void Write(BinaryWriter bw) {
  10810. bw.Write((byte)type);
  10811. bw.Write(elements.Length);
  10812. for (int i=0; i < elements.Length; i++) {
  10813. elements[i].Write(bw);
  10814. }
  10815. }
  10816. }
  10817. /**************************************************************************/
  10818. public class ClassTypeConst : BlobConstant {
  10819. string name;
  10820. Class desc;
  10821. /*-------------------- Constructors ---------------------------------*/
  10822. public ClassTypeConst(string className) {
  10823. name = className;
  10824. type = ElementType.ClassType;
  10825. }
  10826. public ClassTypeConst(Class classDesc) {
  10827. desc = classDesc;
  10828. type = ElementType.ClassType;
  10829. }
  10830. public Class GetClass() {
  10831. return desc;
  10832. }
  10833. public String GetClassName() {
  10834. if (name == null) name = desc.TypeName();
  10835. // CHECK - ClassName or TypeName
  10836. // if (name == null) return desc.ClassName();
  10837. return name;
  10838. }
  10839. internal override void Write(BinaryWriter bw) {
  10840. if (name == null) name = desc.TypeName();
  10841. // CHECK - ClassName or TypeName
  10842. // if (name == null) name = desc.ClassName();
  10843. bw.Write(name);
  10844. }
  10845. }
  10846. /**************************************************************************/
  10847. public class BoxedSimpleConst : BlobConstant {
  10848. SimpleConstant sConst;
  10849. /*-------------------- Constructors ---------------------------------*/
  10850. public BoxedSimpleConst(SimpleConstant con) {
  10851. sConst = con;
  10852. type = (ElementType)sConst.GetTypeIndex();
  10853. }
  10854. public SimpleConstant GetConst() {
  10855. return sConst;
  10856. }
  10857. internal override void Write(BinaryWriter bw) {
  10858. bw.Write((byte)type);
  10859. sConst.Write(bw);
  10860. }
  10861. }
  10862. /**************************************************************************/
  10863. /// <summary>
  10864. /// Descriptor for a constant value
  10865. /// </summary>
  10866. public abstract class DataConstant : Constant {
  10867. private uint dataOffset = 0;
  10868. /*-------------------- Constructors ---------------------------------*/
  10869. internal DataConstant() { }
  10870. public uint DataOffset {
  10871. get { return dataOffset; }
  10872. set { dataOffset = value; }
  10873. }
  10874. }
  10875. /**************************************************************************/
  10876. /// <summary>
  10877. /// Constant for a memory address
  10878. /// </summary>
  10879. public class AddressConstant : DataConstant {
  10880. DataConstant data;
  10881. /*-------------------- Constructors ---------------------------------*/
  10882. public AddressConstant(DataConstant dConst) {
  10883. data = dConst;
  10884. size = 4;
  10885. type = ElementType.TypedByRef;
  10886. }
  10887. internal AddressConstant(PEReader buff) {
  10888. }
  10889. public DataConstant GetConst() {
  10890. return data;
  10891. }
  10892. internal sealed override void Write(BinaryWriter bw) {
  10893. ((PEWriter)bw).WriteDataRVA(data.DataOffset);
  10894. }
  10895. }
  10896. /**************************************************************************/
  10897. public class ByteArrConst : DataConstant {
  10898. byte[] val;
  10899. /*-------------------- Constructors ---------------------------------*/
  10900. public ByteArrConst(byte[] val) {
  10901. this.val = val;
  10902. size = (uint)val.Length;
  10903. }
  10904. public byte[] GetArray() {
  10905. return val;
  10906. }
  10907. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  10908. if (addedToBlobHeap != md) {
  10909. blobIndex = md.AddToBlobHeap(val);
  10910. addedToBlobHeap = md;
  10911. }
  10912. return blobIndex;
  10913. }
  10914. internal sealed override void Write(BinaryWriter bw) {
  10915. bw.Write(val);
  10916. }
  10917. }
  10918. /**************************************************************************/
  10919. public class RepeatedConstant : DataConstant {
  10920. DataConstant data;
  10921. uint repCount;
  10922. /*-------------------- Constructors ---------------------------------*/
  10923. public RepeatedConstant(DataConstant dConst, int repeatCount) {
  10924. data = dConst;
  10925. repCount = (uint)repeatCount;
  10926. type = ElementType.SZArray;
  10927. size = data.GetSize() * repCount;
  10928. }
  10929. public DataConstant GetConst() {
  10930. return data;
  10931. }
  10932. public uint GetCount() {
  10933. return repCount;
  10934. }
  10935. internal sealed override void Write(BinaryWriter bw) {
  10936. for (int i=0; i < repCount; i++) {
  10937. data.Write(bw);
  10938. }
  10939. }
  10940. }
  10941. /**************************************************************************/
  10942. public class StringConst : DataConstant {
  10943. string val;
  10944. byte[] strBytes;
  10945. /*-------------------- Constructors ---------------------------------*/
  10946. public StringConst(string val) {
  10947. this.val = val;
  10948. size = (uint)val.Length; // need to add null ??
  10949. type = ElementType.String;
  10950. }
  10951. internal StringConst(byte[] sBytes) {
  10952. strBytes = sBytes;
  10953. size = (uint)strBytes.Length;
  10954. type = ElementType.String;
  10955. }
  10956. public string GetString() {
  10957. return val;
  10958. }
  10959. public byte[] GetStringBytes() {
  10960. return strBytes;
  10961. }
  10962. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  10963. if (addedToBlobHeap != md) {
  10964. if (val == null)
  10965. blobIndex = md.AddToBlobHeap(strBytes);
  10966. else
  10967. blobIndex = md.AddToBlobHeap(val);
  10968. addedToBlobHeap = md;
  10969. }
  10970. return blobIndex;
  10971. }
  10972. internal sealed override void Write(BinaryWriter bw) {
  10973. if ((val == null) && (strBytes != null)) {
  10974. bw.Write(strBytes);
  10975. } else
  10976. bw.Write(val);
  10977. }
  10978. }
  10979. /**************************************************************************/
  10980. public abstract class SimpleConstant : DataConstant { }
  10981. /**************************************************************************/
  10982. public class IntConst : SimpleConstant {
  10983. long val;
  10984. /*-------------------- Constructors ---------------------------------*/
  10985. public IntConst(sbyte val) {
  10986. this.val = val;
  10987. size = 1; //8;
  10988. type = ElementType.I8;
  10989. }
  10990. public IntConst(short val) {
  10991. this.val = val;
  10992. size = 2; //16;
  10993. type = ElementType.I2;
  10994. }
  10995. public IntConst(int val) {
  10996. this.val = val;
  10997. size = 4; //32;
  10998. type = ElementType.I4;
  10999. }
  11000. public IntConst(long val) {
  11001. this.val = val;
  11002. size = 8; //64;
  11003. type = ElementType.I8;
  11004. }
  11005. internal IntConst(PEReader buff, int numBytes) {
  11006. switch (numBytes) {
  11007. case (1) : val = buff.ReadSByte();
  11008. type = ElementType.I8;
  11009. break;
  11010. case (2) : val = buff.ReadInt16();
  11011. type = ElementType.I2;
  11012. break;
  11013. case (4) : val = buff.ReadInt32();
  11014. type = ElementType.I4;
  11015. break;
  11016. case (8) : val = buff.ReadInt64();
  11017. type = ElementType.I8;
  11018. break;
  11019. default: val = 0;
  11020. break;
  11021. }
  11022. size = (uint)numBytes; // * 4;
  11023. }
  11024. public int GetIntSize() {
  11025. return (int)size;
  11026. }
  11027. public ElementType GetIntType() {
  11028. return type;
  11029. }
  11030. public int GetInt() {
  11031. if (size < 8)
  11032. return (int)val;
  11033. else
  11034. throw new Exception("Constant is long");
  11035. }
  11036. public long GetLong() {
  11037. return val;
  11038. }
  11039. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  11040. if (addedToBlobHeap != md) {
  11041. blobIndex = md.AddToBlobHeap(val,size);
  11042. //switch (size) {
  11043. // case (1) : md.AddToBlobHeap((sbyte)val); break;
  11044. // case (2) : md.AddToBlobHeap((short)val); break;
  11045. // case (4) : md.AddToBlobHeap((int)val); break;
  11046. // default : md.AddToBlobHeap(val); break;
  11047. //}
  11048. addedToBlobHeap = md;
  11049. }
  11050. return blobIndex;
  11051. }
  11052. internal sealed override void Write(BinaryWriter bw) {
  11053. switch (size) {
  11054. case (1) : bw.Write((sbyte)val); break;
  11055. case (2) : bw.Write((short)val); break;
  11056. case (4) : bw.Write((int)val); break;
  11057. default : bw.Write(val); break;
  11058. }
  11059. }
  11060. }
  11061. /**************************************************************************/
  11062. public class UIntConst : SimpleConstant {
  11063. ulong val;
  11064. /*-------------------- Constructors ---------------------------------*/
  11065. public UIntConst(byte val) {
  11066. this.val = val;
  11067. size = 1;
  11068. type = ElementType.U8;
  11069. }
  11070. public UIntConst(ushort val) {
  11071. this.val = val;
  11072. size = 2;
  11073. type = ElementType.U2;
  11074. }
  11075. public UIntConst(uint val) {
  11076. this.val = val;
  11077. size = 4;
  11078. type = ElementType.U4;
  11079. }
  11080. public UIntConst(ulong val) {
  11081. this.val = val;
  11082. size = 8;
  11083. type = ElementType.U8;
  11084. }
  11085. public int GetIntSize() {
  11086. return (int)size;
  11087. }
  11088. public ElementType GetUIntType() {
  11089. return type;
  11090. }
  11091. public uint GetUInt() {
  11092. return (uint)val;
  11093. }
  11094. public ulong GetULong() {
  11095. return val;
  11096. }
  11097. public long GetLong() { // KJG addition
  11098. if (val <= (ulong)(System.Int64.MaxValue))
  11099. return (long) val;
  11100. else
  11101. throw new Exception("UInt Constant too large");
  11102. }
  11103. public long GetULongAsLong() { // KJG addition
  11104. return (long) val;
  11105. }
  11106. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  11107. if (addedToBlobHeap != md) {
  11108. blobIndex = md.AddToBlobHeap(val,size);
  11109. //switch (size) {
  11110. // case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
  11111. // case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
  11112. // case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
  11113. // default : blobIndex = md.AddToBlobHeap(val); break;
  11114. //}
  11115. addedToBlobHeap = md;
  11116. }
  11117. return blobIndex;
  11118. }
  11119. internal sealed override void Write(BinaryWriter bw) {
  11120. switch (size) {
  11121. case (1) : bw.Write((byte)val); break;
  11122. case (2) : bw.Write((ushort)val); break;
  11123. case (4) : bw.Write((uint)val); break;
  11124. default : bw.Write(val); break;
  11125. }
  11126. }
  11127. }
  11128. /**************************************************************************/
  11129. public class FloatConst : SimpleConstant {
  11130. float val;
  11131. /*-------------------- Constructors ---------------------------------*/
  11132. public FloatConst(float val) {
  11133. this.val = val;
  11134. size = 4;
  11135. type = ElementType.R4;
  11136. }
  11137. internal FloatConst(PEReader buff) {
  11138. val = buff.ReadSingle();
  11139. size = 4;
  11140. type = ElementType.R4;
  11141. }
  11142. public float GetFloat() {
  11143. return val;
  11144. }
  11145. public double GetDouble() { // KJG addition 2005-Mar-01
  11146. return (double) val;
  11147. }
  11148. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  11149. if (addedToBlobHeap != md) {
  11150. blobIndex = md.AddToBlobHeap(val);
  11151. addedToBlobHeap = md;
  11152. }
  11153. return blobIndex;
  11154. }
  11155. internal sealed override void Write(BinaryWriter bw) {
  11156. bw.Write(val);
  11157. }
  11158. }
  11159. /**************************************************************************/
  11160. public class DoubleConst : SimpleConstant {
  11161. double val;
  11162. /*-------------------- Constructors ---------------------------------*/
  11163. public DoubleConst(double val) {
  11164. this.val = val;
  11165. size = 8;
  11166. type = ElementType.R8;
  11167. }
  11168. internal DoubleConst(PEReader buff) {
  11169. val = buff.ReadDouble();
  11170. size = 8;
  11171. type = ElementType.R8;
  11172. }
  11173. public double GetDouble() { // KJG addition 2005-Mar-01
  11174. return val;
  11175. }
  11176. internal sealed override uint GetBlobIndex(MetaDataOut md) {
  11177. if (addedToBlobHeap != md) {
  11178. blobIndex = md.AddToBlobHeap(val);
  11179. addedToBlobHeap = md;
  11180. }
  11181. return blobIndex;
  11182. }
  11183. internal sealed override void Write(BinaryWriter bw) {
  11184. bw.Write(val);
  11185. }
  11186. }
  11187. /**************************************************************************/
  11188. // Class to describe procedure locals
  11189. /**************************************************************************/
  11190. /// <summary>
  11191. /// Descriptor for a local of a method
  11192. /// </summary>
  11193. public class Local {
  11194. private static readonly byte PINNED = 0x45;
  11195. string name;
  11196. public Type type;
  11197. bool pinned = false;
  11198. int index = 0;
  11199. /*-------------------- Constructors ---------------------------------*/
  11200. /// <summary>
  11201. /// Create a new local variable
  11202. /// </summary>
  11203. /// <param name="lName">name of the local variable</param>
  11204. /// <param name="lType">type of the local variable</param>
  11205. public Local(string lName, Type lType) {
  11206. name = lName;
  11207. type = lType;
  11208. }
  11209. /// <summary>
  11210. /// Create a new local variable that is byref and/or pinned
  11211. /// </summary>
  11212. /// <param name="lName">local name</param>
  11213. /// <param name="lType">local type</param>
  11214. /// <param name="isPinned">has pinned attribute</param>
  11215. public Local(string lName, Type lType, bool isPinned) {
  11216. name = lName;
  11217. type = lType;
  11218. pinned = isPinned;
  11219. }
  11220. public int GetIndex() { return index; }
  11221. /// <summary>
  11222. /// The name of the local variable.
  11223. /// </summary>
  11224. public string Name { get { return name; } }
  11225. public bool Pinned {
  11226. get { return pinned; }
  11227. set { pinned = value; }
  11228. }
  11229. /// <summary>
  11230. /// Gets the signature for this local variable.
  11231. /// </summary>
  11232. /// <returns>A byte array of the signature.</returns>
  11233. public byte[] GetSig() {
  11234. MemoryStream str = new MemoryStream();
  11235. type.TypeSig(str);
  11236. return str.ToArray();
  11237. }
  11238. internal void SetIndex(int ix) {
  11239. index = ix;
  11240. }
  11241. internal void TypeSig(MemoryStream str) {
  11242. if (pinned) str.WriteByte(PINNED);
  11243. type.TypeSig(str);
  11244. }
  11245. internal void BuildTables(MetaDataOut md) {
  11246. if (!(type is ClassDef))
  11247. type.BuildMDTables(md);
  11248. }
  11249. internal void BuildCILInfo(CILWriter output) {
  11250. if (!(type is ClassDef))
  11251. type.BuildCILInfo(output);
  11252. }
  11253. internal void Write(CILWriter output) {
  11254. type.WriteType(output);
  11255. output.Write("\t" + name);
  11256. }
  11257. }
  11258. /**************************************************************************/
  11259. // Class of PEFile constant values
  11260. /**************************************************************************/
  11261. /// <summary>
  11262. /// Image for a PEFile
  11263. /// File Structure
  11264. /// DOS Header (128 bytes)
  11265. /// PE Signature ("PE\0\0")
  11266. /// PEFileHeader (20 bytes)
  11267. /// PEOptionalHeader (224 bytes)
  11268. /// SectionHeaders (40 bytes * NumSections)
  11269. ///
  11270. /// Sections .text (always present - contains metadata)
  11271. /// .sdata (contains any initialised data in the file - may not be present)
  11272. /// (for ilams /debug this contains the Debug table)
  11273. /// .reloc (always present - in pure CIL only has one fixup)
  11274. /// others??? c# produces .rsrc section containing a Resource Table
  11275. ///
  11276. /// .text layout
  11277. /// IAT (single entry 8 bytes for pure CIL)
  11278. /// CLIHeader (72 bytes)
  11279. /// CIL instructions for all methods (variable size)
  11280. /// MetaData
  11281. /// Root (20 bytes + UTF-8 Version String + quad align padding)
  11282. /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
  11283. /// Streams
  11284. /// #~ (always present - holds metadata tables)
  11285. /// #Strings (always present - holds identifier strings)
  11286. /// #US (Userstring heap)
  11287. /// #Blob (signature blobs)
  11288. /// #GUID (guids for assemblies or Modules)
  11289. /// ImportTable (40 bytes)
  11290. /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
  11291. /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
  11292. /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
  11293. /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
  11294. ///
  11295. /// #~ stream structure
  11296. /// Header (24 bytes)
  11297. /// Rows (4 bytes * numTables)
  11298. /// Tables
  11299. /// </summary>
  11300. internal class FileImage {
  11301. internal readonly static uint DelaySignSize = 128; // Current assemblies are always 128
  11302. internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
  11303. internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
  11304. 0x0000000000FF0000, 0x00000000FF000000,
  11305. 0x000000FF00000000, 0x0000FF0000000000,
  11306. 0x00FF000000000000, 0xFF00000000000000 };
  11307. internal readonly static uint nibble0Mask = 0x0000000F;
  11308. internal readonly static uint nibble1Mask = 0x000000F0;
  11309. internal static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
  11310. 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
  11311. 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  11312. 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  11313. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  11314. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  11315. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  11316. 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
  11317. 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
  11318. 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
  11319. 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
  11320. 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
  11321. 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
  11322. 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
  11323. 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
  11324. 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  11325. 0x50,0x45,0x00,0x00};
  11326. internal static readonly int PESigOffset = 0x3C;
  11327. internal static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  11328. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  11329. 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
  11330. 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
  11331. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  11332. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  11333. };
  11334. internal static IType[] instrMap = {
  11335. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x00 - 0x08
  11336. IType.op, IType.op, IType.op, IType.op, IType.op, IType.uint8Op, IType.uint8Op, // 0x09 - 0x0F
  11337. IType.uint8Op, IType.uint8Op, IType.uint8Op, IType.uint8Op, // 0x10 - 0x13
  11338. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x14 - 0x1C
  11339. IType.op, IType.op, IType.int8Op, IType.int32Op, IType.specialOp, // 0x1D - 0x21
  11340. IType.specialOp, IType.specialOp,IType.op,IType.op,IType.op,IType.methOp, // 0x22 - 0x27
  11341. IType.methOp, IType.specialOp, IType.op, IType.branchOp, IType.branchOp,// 0x28 - 0x2C
  11342. IType.branchOp, IType.branchOp, IType.branchOp, IType.branchOp, // 0x2D - 0x30
  11343. IType.branchOp, IType.branchOp, IType.branchOp, IType.branchOp, // 0x31 - 0x34
  11344. IType.branchOp, IType.branchOp, IType.branchOp, IType.branchOp, // 0x35 - 0x38
  11345. IType.branchOp, IType.branchOp, IType.branchOp, IType.branchOp, // 0x39 - 0x3C
  11346. IType.branchOp, IType.branchOp, IType.branchOp, IType.branchOp, // 0x3D - 0x40
  11347. IType.branchOp, IType.branchOp, IType.branchOp, IType.branchOp, // 0x41 - 0x44
  11348. IType.specialOp, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x45 - 0x4B
  11349. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x4C - 0x54
  11350. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x55 - 0x5D
  11351. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x5E - 0x66
  11352. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x67 - 0x6E
  11353. IType.methOp, IType.typeOp, IType.typeOp, IType.specialOp, // 0x6F - 0x72
  11354. IType.methOp, IType.typeOp, IType.typeOp, IType.op, IType.op, IType.op, // 0x73 - 0x78
  11355. IType.typeOp, IType.op, IType.fieldOp, IType.fieldOp, IType.fieldOp,// 0x79 - 0x7D
  11356. IType.fieldOp, IType.fieldOp, IType.fieldOp, IType.typeOp, // 0x7E - 0x81
  11357. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x82 - 0x8A
  11358. IType.op, IType.typeOp, IType.typeOp, IType.op, IType.typeOp, IType.op, // 0x8B - 0x90
  11359. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x91 - 0x99
  11360. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0x9A - 0xA2
  11361. IType.typeOp, IType.typeOp, IType.typeOp, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0xA3 - 0xAB
  11362. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0xAC - 0xB4
  11363. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0xB5 - 0xBD
  11364. IType.op, IType.op, IType.op, IType.op, IType.typeOp, IType.op, IType.op, IType.op, // 0xBE - 0xC5
  11365. IType.typeOp, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0xC6 - 0xCD
  11366. IType.op, IType.op, IType.specialOp, IType.op, IType.op, IType.op, IType.op, // 0xCE - 0xD4
  11367. IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, // 0xD5 - 0xDC
  11368. IType.branchOp, IType.branchOp, IType.op, IType.op }; // 0xDD - 0xE0
  11369. internal static IType[] longInstrMap = { IType.op, IType.op, IType.op, IType.op, IType.op, IType.op, IType.methOp, // 0x00 - 0x06
  11370. IType.methOp, IType.uint16Op, IType.uint16Op, // 0x07 - 0x09
  11371. IType.uint16Op, IType.uint16Op, IType.uint16Op, // 0x0A - 0x0C
  11372. IType.uint16Op, IType.uint16Op, IType.op, IType.op, IType.op, // 0x0D - 0x11
  11373. IType.uint8Op, IType.op, IType.op, IType.typeOp, IType.typeOp, IType.op, // 0x12 - 0x17
  11374. IType.op, IType.op, IType.op, IType.op, IType.typeOp, IType.op, IType.op}; // 0x18 - 0x1D
  11375. internal static readonly uint bitmask0 = 0x00000001;
  11376. internal static readonly uint bitmask1 = 0x00000002;
  11377. internal static readonly uint bitmask2 = 0x00000004;
  11378. internal static readonly uint bitmask3 = 0x00000008;
  11379. internal static readonly uint bitmask4 = 0x00000010;
  11380. internal static readonly uint bitmask5 = 0x00000020;
  11381. internal static readonly uint bitmask6 = 0x00000040;
  11382. internal static readonly uint bitmask7 = 0x00000080;
  11383. internal static readonly uint bitmask8 = 0x00000100;
  11384. internal static readonly uint bitmask9 = 0x00000200;
  11385. internal static readonly uint bitmask10 = 0x00000400;
  11386. internal static readonly uint bitmask11 = 0x00000800;
  11387. internal static readonly uint bitmask12 = 0x00001000;
  11388. internal static readonly uint bitmask13 = 0x00002000;
  11389. internal static readonly uint bitmask14 = 0x00004000;
  11390. internal static readonly uint bitmask15 = 0x00008000;
  11391. internal static readonly uint bitmask16 = 0x00010000;
  11392. internal static readonly uint bitmask17 = 0x00020000;
  11393. internal static readonly uint bitmask18 = 0x00040000;
  11394. internal static readonly uint bitmask19 = 0x00080000;
  11395. internal static readonly uint bitmask20 = 0x00100000;
  11396. internal static readonly uint bitmask21 = 0x00200000;
  11397. internal static readonly uint bitmask22 = 0x00400000;
  11398. internal static readonly uint bitmask23 = 0x00800000;
  11399. internal static readonly uint bitmask24 = 0x01000000;
  11400. internal static readonly uint bitmask25 = 0x02000000;
  11401. internal static readonly uint bitmask26 = 0x04000000;
  11402. internal static readonly uint bitmask27 = 0x08000000;
  11403. internal static readonly uint bitmask28 = 0x10000000;
  11404. internal static readonly uint bitmask29 = 0x20000000;
  11405. internal stati