MDClassElems.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  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. //if ((fType is GenericParam) && (((GenericParam)fType).GetParent() == genClass)) {
  346. // fType = gPars[((GenericParam)fType).Index];
  347. //}
  348. fields.Add(new FieldRef(this, ((Field)classFields[i]).Name(), fType));
  349. }
  350. }
  351. /*------------------------- public set and get methods --------------------------*/
  352. /// <summary>
  353. /// Get the generic class that this is an instantiation of
  354. /// </summary>
  355. /// <returns>generic class</returns>
  356. public override MetaDataElement GetParent()
  357. {
  358. return null;
  359. }
  360. /// <summary>
  361. /// Get the specified generic parameter number
  362. /// </summary>
  363. /// <param name="ix">generic parameter number</param>
  364. /// <returns>generic parameter number ix</returns>
  365. public Type GetGenericParamType(int ix)
  366. {
  367. if (ix >= genericParams.Count) return null;
  368. return (Type)genericParams[ix];
  369. }
  370. /// <summary>
  371. /// Get the generic parameters of this class
  372. /// </summary>
  373. /// <returns>list of generic parameters</returns>
  374. public Type[] GetGenericParamTypes()
  375. {
  376. return (Type[])genericParams.ToArray(typeof(Type));
  377. }
  378. /// <summary>
  379. /// Get the generic class that this class instantiates
  380. /// </summary>
  381. /// <returns>generic class</returns>
  382. public Class GetGenericClass()
  383. {
  384. return genClass;
  385. }
  386. /// <summary>
  387. /// Count how many generic parameters this class has
  388. /// </summary>
  389. /// <returns>number of generic parameters</returns>
  390. public int GetGenericParCount()
  391. {
  392. return genericParams.Count;
  393. }
  394. /*----------------------------- internal functions ------------------------------*/
  395. internal void AddMethod(Method meth)
  396. {
  397. methods.Add(meth);
  398. meth.SetParent(this);
  399. }
  400. internal override string ClassName()
  401. {
  402. // need to return something here??
  403. return null;
  404. }
  405. internal override sealed uint TypeDefOrRefToken()
  406. {
  407. uint cIx = Row;
  408. cIx = (cIx << 2) | 0x2;
  409. return cIx;
  410. }
  411. internal override Type GetGenPar(uint ix)
  412. {
  413. if (genClass == null) return new GenericParam(null, this, (int)ix);
  414. return genClass.GetGenPar(ix);
  415. //if (ix >= genericParams.Count) return null;
  416. //return (Type)genericParams[(int)ix];
  417. }
  418. internal override sealed Type AddTypeSpec(MetaDataOut md)
  419. {
  420. md.AddToTable(MDTable.TypeSpec, this);
  421. BuildMDTables(md);
  422. return this;
  423. }
  424. internal override void BuildTables(MetaDataOut md)
  425. {
  426. //md.AddToTable(MDTable.TypeSpec,this);
  427. if (!genClass.isDef())
  428. genClass.BuildMDTables(md);
  429. for (int i = 0; i < genericParams.Count; i++)
  430. {
  431. if (!((Type)genericParams[i]).isDef() &&
  432. (!(genericParams[i] is GenericParam)))
  433. ((Type)genericParams[i]).BuildMDTables(md);
  434. }
  435. }
  436. internal override void BuildSignatures(MetaDataOut md)
  437. {
  438. MemoryStream outSig = new MemoryStream();
  439. TypeSig(outSig);
  440. sigIx = md.AddToBlobHeap(outSig.ToArray());
  441. }
  442. internal sealed override void TypeSig(MemoryStream sig)
  443. {
  444. sig.WriteByte(typeIndex);
  445. genClass.TypeSig(sig);
  446. //MetaDataOut.CompressNum((uint)genericParams.Count, sig);
  447. MetaDataOut.CompressNum(BlobUtil.CompressUInt((uint)genericParams.Count), sig);
  448. for (int i = 0; i < genericParams.Count; i++)
  449. {
  450. ((Type)genericParams[i]).TypeSig(sig);
  451. }
  452. }
  453. internal sealed override void Write(PEWriter output)
  454. {
  455. //Console.WriteLine("Writing the blob index for a TypeSpec");
  456. output.BlobIndex(sigIx);
  457. }
  458. internal sealed override uint GetCodedIx(CIx code)
  459. {
  460. switch (code)
  461. {
  462. case (CIx.TypeDefOrRef): return 2;
  463. case (CIx.HasCustomAttr): return 13;
  464. case (CIx.MemberRefParent): return 4;
  465. }
  466. return 0;
  467. }
  468. }
  469. /**************************************************************************/
  470. /// <summary>
  471. /// wrapper for TypeSpec parent of MethodRef or FieldRef
  472. /// </summary>
  473. public class ConstructedTypeSpec : Class
  474. {
  475. TypeSpec constrType;
  476. public ConstructedTypeSpec(TypeSpec tySpec)
  477. : base()
  478. {
  479. constrType = tySpec;
  480. this.typeIndex = constrType.GetTypeIndex();
  481. }
  482. public TypeSpec Spec { get { return constrType; } }
  483. public override MetaDataElement GetParent()
  484. {
  485. return null;
  486. }
  487. internal override string ClassName()
  488. {
  489. return constrType.NameString();
  490. }
  491. }
  492. /**************************************************************************/
  493. public abstract class ClassDesc : Class
  494. {
  495. /*-------------------- Constructors ---------------------------------*/
  496. internal ClassDesc(string nameSpaceName, string className)
  497. {
  498. nameSpace = nameSpaceName;
  499. name = className;
  500. }
  501. internal ClassDesc()
  502. {
  503. }
  504. /*------------------------- public set and get methods --------------------------*/
  505. public GenericParam GetGenericParam(int ix)
  506. {
  507. if (ix >= genericParams.Count) return null;
  508. return (GenericParam)genericParams[ix];
  509. }
  510. public GenericParam[] GetGenericParams()
  511. {
  512. return (GenericParam[])genericParams.ToArray(typeof(GenericParam));
  513. }
  514. public virtual void SetGenericParams(GenericParam[] genPars)
  515. {
  516. for (int i = 0; i < genPars.Length; i++)
  517. {
  518. genPars[i].SetClassParam(this, i);
  519. }
  520. genericParams = new ArrayList(genPars);
  521. }
  522. /*----------------------------- internal functions ------------------------------*/
  523. protected void DeleteGenericParam(int pos)
  524. {
  525. genericParams.RemoveAt(pos);
  526. for (int i = pos; i < genericParams.Count; i++)
  527. {
  528. GenericParam gp = (GenericParam)genericParams[i];
  529. gp.Index = (uint)i;
  530. }
  531. }
  532. internal void AddGenericParam(GenericParam par)
  533. {
  534. genericParams.Add(par);
  535. //par.SetClassParam(this,genericParams.Count-1);
  536. }
  537. internal override Type GetGenPar(uint ix)
  538. {
  539. // create generic param descriptor if one does not exist
  540. // - used when reading exported interface
  541. // The next two lines are *required* for v2.0 beta release! (kjg)
  542. for (int i = genericParams.Count; i <= ix; i++)
  543. genericParams.Add(new GenericParam("gp" + i, this, i));
  544. return (GenericParam)genericParams[(int)ix];
  545. }
  546. }
  547. }