MDClassElems.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  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. using System;
  18. using System.IO;
  19. using System.Collections;
  20. using System.Security.Cryptography;
  21. namespace QUT.PERWAPI
  22. {
  23. /**************************************************************************/
  24. /// <summary>
  25. /// The base descriptor for a class
  26. /// </summary>
  27. public abstract class Class : Type
  28. {
  29. //protected int row = 0;
  30. protected string name, nameSpace;
  31. protected uint nameIx, nameSpaceIx;
  32. protected ArrayList nestedClasses = new ArrayList();
  33. protected bool special = false;
  34. protected ArrayList fields = new ArrayList();
  35. protected ArrayList methods = new ArrayList();
  36. internal uint fieldIx = 0, methodIx = 0, fieldEndIx = 0, methodEndIx = 0;
  37. protected string[] fieldNames, methodNames;
  38. protected ArrayList genericParams = new ArrayList();
  39. /*-------------------- Constructors ---------------------------------*/
  40. internal Class() : base((byte)ElementType.Class) { }
  41. /*------------------------- public set and get methods --------------------------*/
  42. public virtual void MakeValueClass()
  43. {
  44. typeIndex = (byte)ElementType.ValueType;
  45. }
  46. /// <summary>
  47. /// Get the name of this class
  48. /// </summary>
  49. /// <returns>class name</returns>
  50. public string Name() { return name; }
  51. /// <summary>
  52. /// Get the namespace that includes this class
  53. /// </summary>
  54. /// <returns>namespace name</returns>
  55. public string NameSpace() { return nameSpace; }
  56. /// <summary>
  57. /// Get the string representation of the qualified name
  58. /// of this class
  59. /// </summary>
  60. /// <returns>class qualified name</returns>
  61. public override string TypeName()
  62. {
  63. if ((nameSpace == null) || (nameSpace == "")) return name;
  64. return nameSpace + "." + name;
  65. }
  66. /// <summary>
  67. /// Get the descriptor for the method "name" of this class
  68. /// </summary>
  69. /// <param name="name">The name of the method to be retrieved</param>
  70. /// <returns>The method descriptor for "name"</returns>
  71. public Method GetMethodDesc(string name)
  72. {
  73. for (int i = 0; i < methods.Count; i++)
  74. {
  75. if (((Method)methods[i]).HasName(name))
  76. return (Method)methods[i];
  77. }
  78. return null;
  79. }
  80. /// <summary>
  81. /// Get the descriptor for the method called "name" with the signature "parTypes"
  82. /// </summary>
  83. /// <param name="name">The name of the method</param>
  84. /// <param name="parTypes">The signature of the method</param>
  85. /// <returns>The method descriptor for name(parTypes)</returns>
  86. public Method GetMethodDesc(string name, Type[] parTypes)
  87. {
  88. for (int i = 0; i < methods.Count; i++)
  89. {
  90. if (((Method)methods[i]).HasNameAndSig(name, parTypes))
  91. return (Method)methods[i];
  92. }
  93. return null;
  94. }
  95. /// <summary>
  96. /// Get the vararg method "name(parTypes,optTypes)" for this class
  97. /// </summary>
  98. /// <param name="name">Method name</param>
  99. /// <param name="parTypes">Method parameter types</param>
  100. /// <param name="optParTypes">Optional parameter types</param>
  101. /// <returns>Descriptor for "name(parTypes,optTypes)"</returns>
  102. public Method GetMethodDesc(string name, Type[] parTypes, Type[] optParTypes)
  103. {
  104. for (int i = 0; i < methods.Count; i++)
  105. {
  106. if (((Method)methods[i]).HasNameAndSig(name, parTypes, optParTypes))
  107. return (Method)methods[i];
  108. }
  109. return null;
  110. }
  111. /// <summary>
  112. /// Get all the methods of this class called "name"
  113. /// </summary>
  114. /// <param name="name">The method name</param>
  115. /// <returns>List of methods called "name"</returns>
  116. public Method[] GetMethodDescs(string name)
  117. {
  118. ArrayList meths = GetMeths(name);
  119. return (Method[])meths.ToArray(typeof(Method));
  120. }
  121. /// <summary>
  122. /// Get all the methods for this class
  123. /// </summary>
  124. /// <returns>List of methods for this class</returns>
  125. public Method[] GetMethodDescs()
  126. {
  127. return (Method[])methods.ToArray(typeof(Method));
  128. }
  129. /// <summary>
  130. /// Remove the specified method from this class
  131. /// </summary>
  132. /// <param name="name">method name</param>
  133. public void RemoveMethod(string name)
  134. {
  135. Method meth = GetMethodDesc(name);
  136. if (meth != null) methods.Remove(meth);
  137. }
  138. /// <summary>
  139. /// Remove the specified method from this class
  140. /// </summary>
  141. /// <param name="name">method name</param>
  142. /// <param name="parTypes">method parameter types</param>
  143. public void RemoveMethod(string name, Type[] parTypes)
  144. {
  145. Method meth = GetMethodDesc(name, parTypes);
  146. if (meth != null) methods.Remove(meth);
  147. }
  148. /// <summary>
  149. /// Remove the specified method from this class
  150. /// </summary>
  151. /// <param name="name">method name</param>
  152. /// <param name="parTypes">method parameter types</param>
  153. /// <param name="optTypes">optional method parameter types</param>
  154. public void RemoveMethod(string name, Type[] parTypes, Type[] optTypes)
  155. {
  156. Method meth = GetMethodDesc(name, parTypes, optTypes);
  157. if (meth != null) methods.Remove(meth);
  158. }
  159. /// <summary>
  160. /// Remove the specified method from this class
  161. /// </summary>
  162. /// <param name="meth">method descriptor</param>
  163. public void RemoveMethod(Method meth)
  164. {
  165. methods.Remove(meth);
  166. }
  167. /// <summary>
  168. /// Remove the specified method from this class
  169. /// </summary>
  170. /// <param name="ix">index into list of methods for specified method</param>
  171. public void RemoveMethod(int ix)
  172. {
  173. methods.RemoveAt(ix);
  174. }
  175. /// <summary>
  176. /// Get the descriptor for the field "name" for this class
  177. /// </summary>
  178. /// <param name="name">Field name</param>
  179. /// <returns>Descriptor for field "name"</returns>
  180. public Field GetFieldDesc(string name)
  181. {
  182. return FindField(name);
  183. }
  184. /// <summary>
  185. /// Get all the fields for this class
  186. /// </summary>
  187. /// <returns>List of fields for this class</returns>
  188. public Field[] GetFieldDescs()
  189. {
  190. return (Field[])fields.ToArray(typeof(Field));
  191. }
  192. /// <summary>
  193. /// Remove the specified field from this class
  194. /// </summary>
  195. /// <param name="name">field name</param>
  196. public void RemoveField(string name)
  197. {
  198. Field f = FindField(name);
  199. if (f != null) fields.Remove(f);
  200. }
  201. /// <summary>
  202. /// Instantiate this generic type with the supplied types
  203. /// </summary>
  204. /// <param name="genTypes">types to instantiate with</param>
  205. /// <returns>descriptor for instantiated generic type</returns>
  206. public virtual ClassSpec Instantiate(Type[] genTypes)
  207. {
  208. return new ClassSpec(this, genTypes);
  209. }
  210. /// <summary>
  211. /// Denote this class as "special" such as a default module class
  212. /// </summary>
  213. public virtual void MakeSpecial()
  214. {
  215. special = true;
  216. }
  217. /// <summary>
  218. /// Get the owing scope of this class
  219. /// </summary>
  220. /// <returns>owner of this class</returns>
  221. public abstract MetaDataElement GetParent();
  222. /// <summary>
  223. /// Get any nested classes of this class
  224. /// </summary>
  225. /// <returns>list of nested classes</returns>
  226. public Class[] GetNestedClasses()
  227. {
  228. return (Class[])nestedClasses.ToArray(typeof(Class));
  229. }
  230. /// <summary>
  231. /// How many nested classes does this class have?
  232. /// </summary>
  233. /// <returns>number of nested classes</returns>
  234. public int GetNestedClassCount()
  235. {
  236. return nestedClasses.Count;
  237. }
  238. /*------------------------- internal functions --------------------------*/
  239. internal virtual Type GetGenPar(uint ix) { return null; }
  240. protected ArrayList GetMeths(string name)
  241. {
  242. ArrayList meths = new ArrayList();
  243. for (int i = 0; i < methods.Count; i++)
  244. {
  245. if (((Method)methods[i]).HasName(name))
  246. meths.Add(methods[i]);
  247. }
  248. return meths;
  249. }
  250. internal ArrayList GetFieldList() { return fields; }
  251. internal ArrayList GetMethodList() { return methods; }
  252. internal bool isValueType()
  253. {
  254. return typeIndex == (byte)ElementType.ValueType;
  255. }
  256. internal bool isSpecial() { return special; }
  257. internal void AddToFieldList(Field f)
  258. {
  259. f.SetParent(this);
  260. fields.Add(f);
  261. }
  262. internal void AddToList(ArrayList list, MDTable tabIx)
  263. {
  264. switch (tabIx)
  265. {
  266. case (MDTable.Field): fields.AddRange(list); break;
  267. case (MDTable.Method): methods.AddRange(list); break;
  268. case (MDTable.TypeDef): nestedClasses.AddRange(list); break;
  269. default: throw new Exception("Unknown list type");
  270. }
  271. }
  272. internal void AddToMethodList(Method m)
  273. {
  274. m.SetParent(this);
  275. methods.Add(m);
  276. }
  277. internal void AddToClassList(Class nClass)
  278. {
  279. nestedClasses.Add(nClass);
  280. }
  281. internal Class GetNested(string name)
  282. {
  283. for (int i = 0; i < nestedClasses.Count; i++)
  284. {
  285. if (((Class)nestedClasses[i]).Name() == name)
  286. return (Class)nestedClasses[i];
  287. }
  288. return null;
  289. }
  290. internal Method GetMethod(MethSig mSig)
  291. {
  292. return GetMethodDesc(mSig.name, mSig.parTypes, mSig.optParTypes);
  293. }
  294. protected Field FindField(string name)
  295. {
  296. for (int i = 0; i < fields.Count; i++)
  297. {
  298. if (((Field)fields[i]).Name() == name)
  299. return (Field)fields[i];
  300. }
  301. return null;
  302. }
  303. internal void SetBuffer(PEReader buff) { buffer = buff; }
  304. internal override void TypeSig(MemoryStream sig)
  305. {
  306. sig.WriteByte(typeIndex);
  307. MetaDataOut.CompressNum(BlobUtil.CompressUInt(TypeDefOrRefToken()), sig);
  308. }
  309. internal abstract string ClassName();
  310. internal virtual uint TypeDefOrRefToken() { return 0; }
  311. }
  312. /**************************************************************************/
  313. /// <summary>
  314. ///
  315. /// </summary>
  316. public class ClassSpec : Class
  317. {
  318. Class genClass;
  319. uint sigIx;
  320. private static byte GENERICINST = 0x15;
  321. /*-------------------- Constructors ---------------------------------*/
  322. internal ClassSpec(Class clType, Type[] gPars)
  323. {
  324. this.typeIndex = GENERICINST;
  325. genClass = clType;
  326. genericParams = new ArrayList(gPars);
  327. tabIx = MDTable.TypeSpec;
  328. typeIndex = GENERICINST;
  329. ArrayList classMethods = clType.GetMethodList();
  330. ArrayList classFields = clType.GetFieldList();
  331. for (int i = 0; i < classMethods.Count; i++)
  332. {
  333. MethSig mSig = ((Method)classMethods[i]).GetSig(); //.InstantiateGenTypes(this,gPars);
  334. if (mSig != null)
  335. {
  336. MethodRef newMeth = new MethodRef(mSig);
  337. newMeth.SetParent(this);
  338. newMeth.GenericParams = ((Method)classMethods[i]).GenericParams;
  339. methods.Add(newMeth);
  340. }
  341. }
  342. for (int i = 0; i < classFields.Count; i++)
  343. {
  344. Type fType = ((Field)classFields[i]).GetFieldType();
  345. fields.Add(new FieldRef(this, ((Field)classFields[i]).Name(), fType));
  346. }
  347. }
  348. /*------------------------- public set and get methods --------------------------*/
  349. /// <summary>
  350. /// Get the generic class that this is an instantiation of
  351. /// </summary>
  352. /// <returns>generic class</returns>
  353. public override MetaDataElement GetParent()
  354. {
  355. return null;
  356. }
  357. /// <summary>
  358. /// Get the specified generic parameter number
  359. /// </summary>
  360. /// <param name="ix">generic parameter number</param>
  361. /// <returns>generic parameter number ix</returns>
  362. public Type GetGenericParamType(int ix)
  363. {
  364. if (ix >= genericParams.Count) return null;
  365. return (Type)genericParams[ix];
  366. }
  367. /// <summary>
  368. /// Get the generic parameters of this class
  369. /// </summary>
  370. /// <returns>list of generic parameters</returns>
  371. public Type[] GetGenericParamTypes()
  372. {
  373. return (Type[])genericParams.ToArray(typeof(Type));
  374. }
  375. /// <summary>
  376. /// Get the generic class that this class instantiates
  377. /// </summary>
  378. /// <returns>generic class</returns>
  379. public Class GetGenericClass()
  380. {
  381. return genClass;
  382. }
  383. /// <summary>
  384. /// Count how many generic parameters this class has
  385. /// </summary>
  386. /// <returns>number of generic parameters</returns>
  387. public int GetGenericParCount()
  388. {
  389. return genericParams.Count;
  390. }
  391. /*----------------------------- internal functions ------------------------------*/
  392. internal void AddMethod(Method meth)
  393. {
  394. methods.Add(meth);
  395. meth.SetParent(this);
  396. }
  397. internal override string ClassName()
  398. {
  399. // need to return something here??
  400. return null;
  401. }
  402. internal override sealed uint TypeDefOrRefToken()
  403. {
  404. uint cIx = Row;
  405. cIx = (cIx << 2) | 0x2;
  406. return cIx;
  407. }
  408. internal override Type GetGenPar(uint ix)
  409. {
  410. if (genClass == null) return new GenericParam(null, this, (int)ix);
  411. return genClass.GetGenPar(ix);
  412. //if (ix >= genericParams.Count) return null;
  413. //return (Type)genericParams[(int)ix];
  414. }
  415. internal override sealed Type AddTypeSpec(MetaDataOut md) {
  416. md.ConditionalAddTypeSpec(this);
  417. BuildMDTables(md);
  418. return this;
  419. }
  420. internal override void BuildTables(MetaDataOut md)
  421. {
  422. if (!genClass.isDef())
  423. genClass.BuildMDTables(md);
  424. for (int i = 0; i < genericParams.Count; i++)
  425. {
  426. if (!((Type)genericParams[i]).isDef() &&
  427. (!(genericParams[i] is GenericParam)))
  428. ((Type)genericParams[i]).BuildMDTables(md);
  429. }
  430. }
  431. internal override void BuildSignatures(MetaDataOut md)
  432. {
  433. MemoryStream outSig = new MemoryStream();
  434. TypeSig(outSig);
  435. sigIx = md.AddToBlobHeap(outSig.ToArray());
  436. }
  437. internal sealed override void TypeSig(MemoryStream sig)
  438. {
  439. sig.WriteByte(typeIndex);
  440. genClass.TypeSig(sig);
  441. //MetaDataOut.CompressNum((uint)genericParams.Count, sig);
  442. MetaDataOut.CompressNum(BlobUtil.CompressUInt((uint)genericParams.Count), sig);
  443. for (int i = 0; i < genericParams.Count; i++)
  444. {
  445. ((Type)genericParams[i]).TypeSig(sig);
  446. }
  447. }
  448. internal sealed override void Write(PEWriter output)
  449. {
  450. //Console.WriteLine("Writing the blob index for a TypeSpec");
  451. output.BlobIndex(sigIx);
  452. }
  453. internal sealed override uint GetCodedIx(CIx code)
  454. {
  455. switch (code)
  456. {
  457. case (CIx.TypeDefOrRef): return 2;
  458. case (CIx.HasCustomAttr): return 13;
  459. case (CIx.MemberRefParent): return 4;
  460. }
  461. return 0;
  462. }
  463. }
  464. /**************************************************************************/
  465. /// <summary>
  466. /// wrapper for TypeSpec parent of MethodRef or FieldRef
  467. /// </summary>
  468. public class ConstructedTypeSpec : Class
  469. {
  470. TypeSpec constrType;
  471. public ConstructedTypeSpec(TypeSpec tySpec)
  472. : base()
  473. {
  474. constrType = tySpec;
  475. this.typeIndex = constrType.GetTypeIndex();
  476. }
  477. public TypeSpec Spec { get { return constrType; } }
  478. public override MetaDataElement GetParent()
  479. {
  480. return null;
  481. }
  482. internal override string ClassName()
  483. {
  484. return constrType.NameString();
  485. }
  486. }
  487. /**************************************************************************/
  488. public abstract class ClassDesc : Class
  489. {
  490. /*-------------------- Constructors ---------------------------------*/
  491. internal ClassDesc(string nameSpaceName, string className)
  492. {
  493. nameSpace = nameSpaceName;
  494. name = className;
  495. }
  496. internal ClassDesc()
  497. {
  498. }
  499. /*------------------------- public set and get methods --------------------------*/
  500. public GenericParam GetGenericParam(int ix)
  501. {
  502. if (ix >= genericParams.Count) return null;
  503. return (GenericParam)genericParams[ix];
  504. }
  505. public GenericParam[] GetGenericParams()
  506. {
  507. return (GenericParam[])genericParams.ToArray(typeof(GenericParam));
  508. }
  509. public virtual void SetGenericParams(GenericParam[] genPars)
  510. {
  511. for (int i = 0; i < genPars.Length; i++)
  512. {
  513. genPars[i].SetClassParam(this, i);
  514. }
  515. genericParams = new ArrayList(genPars);
  516. }
  517. /*----------------------------- internal functions ------------------------------*/
  518. protected void DeleteGenericParam(int pos)
  519. {
  520. genericParams.RemoveAt(pos);
  521. for (int i = pos; i < genericParams.Count; i++)
  522. {
  523. GenericParam gp = (GenericParam)genericParams[i];
  524. gp.Index = (uint)i;
  525. }
  526. }
  527. internal void AddGenericParam(GenericParam par)
  528. {
  529. genericParams.Add(par);
  530. //par.SetClassParam(this,genericParams.Count-1);
  531. }
  532. internal override Type GetGenPar(uint ix)
  533. {
  534. // create generic param descriptor if one does not exist
  535. // - used when reading exported interface
  536. // The next two lines are *required* for v2.0 beta release! (kjg)
  537. for (int i = genericParams.Count; i <= ix; i++)
  538. genericParams.Add(new GenericParam("gp" + i, this, i));
  539. return (GenericParam)genericParams[(int)ix];
  540. }
  541. }
  542. }