MDClassRefElems.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  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. /// Descriptor for a class/interface declared in another module of THIS
  26. /// assembly, or in another assembly.
  27. /// </summary>
  28. public class ClassRef : ClassDesc
  29. {
  30. protected ReferenceScope scope;
  31. protected uint resScopeIx = 0;
  32. internal ExternClass externClass;
  33. internal ClassDef defOf;
  34. internal bool readAsDef = false;
  35. /*-------------------- Constructors ---------------------------------*/
  36. internal ClassRef(ReferenceScope scope, string nsName, string name)
  37. : base(nsName, name)
  38. {
  39. this.scope = scope;
  40. tabIx = MDTable.TypeRef;
  41. }
  42. internal ClassRef(uint scopeIx, string nsName, string name)
  43. : base(nsName, name)
  44. {
  45. resScopeIx = scopeIx;
  46. tabIx = MDTable.TypeRef;
  47. }
  48. internal static ClassRef ReadDef(PEReader buff, ReferenceScope resScope, uint index)
  49. {
  50. uint junk = buff.ReadUInt32();
  51. string cName = buff.GetString();
  52. string nsName = buff.GetString();
  53. ClassRef newClass = (ClassRef)resScope.GetExistingClass(nsName, cName);
  54. if (newClass == null)
  55. {
  56. newClass = new ClassRef(resScope, nsName, cName);
  57. resScope.AddToClassList(newClass);
  58. }
  59. newClass.readAsDef = true;
  60. newClass.Row = index;
  61. junk = buff.GetCodedIndex(CIx.TypeDefOrRef);
  62. newClass.fieldIx = buff.GetIndex(MDTable.Field);
  63. newClass.methodIx = buff.GetIndex(MDTable.Method);
  64. return newClass;
  65. }
  66. internal static void Read(PEReader buff, TableRow[] typeRefs, bool resolve)
  67. {
  68. for (uint i = 0; i < typeRefs.Length; i++)
  69. {
  70. uint resScopeIx = buff.GetCodedIndex(CIx.ResolutionScope);
  71. string name = buff.GetString();
  72. string nameSpace = buff.GetString();
  73. if (buff.CodedTable(CIx.ResolutionScope, resScopeIx) == MDTable.TypeRef)
  74. typeRefs[i] = new NestedClassRef(resScopeIx, nameSpace, name);
  75. else
  76. typeRefs[i] = new ClassRef(resScopeIx, nameSpace, name);
  77. typeRefs[i].Row = i + 1;
  78. }
  79. if (resolve)
  80. {
  81. for (int i = 0; i < typeRefs.Length; i++)
  82. {
  83. ((ClassRef)typeRefs[i]).ResolveParent(buff, false);
  84. }
  85. }
  86. }
  87. internal static ClassRef ReadClass(PEReader buff, ReferenceScope resScope)
  88. {
  89. uint resScopeIx = buff.GetCodedIndex(CIx.ResolutionScope);
  90. string name = buff.GetString();
  91. string nameSpace = buff.GetString();
  92. ClassRef newClass = (ClassRef)resScope.GetExistingClass(nameSpace, name);
  93. if (newClass == null)
  94. newClass = new ClassRef(resScope, nameSpace, name);
  95. return newClass;
  96. }
  97. internal virtual void ResolveParent(PEReader buff, bool isExtern)
  98. {
  99. CIx cIx = CIx.ResolutionScope;
  100. if (isExtern) cIx = CIx.Implementation;
  101. if (scope != null) return;
  102. MetaDataElement parentScope = buff.GetCodedElement(cIx, resScopeIx);
  103. if (parentScope is Module)
  104. { // special code for glitch in Everett ilasm
  105. ClassDef newDef = new ClassDef((PEFile)parentScope, 0, nameSpace, name);
  106. ((Module)parentScope).AddToClassList(newDef);
  107. buff.InsertInTable(MDTable.TypeRef, Row, newDef);
  108. }
  109. else
  110. {
  111. scope = (ReferenceScope)buff.GetCodedElement(cIx, resScopeIx);
  112. ClassRef existing = (ClassRef)scope.GetExistingClass(nameSpace, name);
  113. if (existing == null)
  114. {
  115. scope.AddToClassList(this);
  116. }
  117. else
  118. {
  119. if (isExtern)
  120. buff.InsertInTable(MDTable.ExportedType, Row, existing);
  121. else
  122. buff.InsertInTable(MDTable.TypeRef, Row, existing);
  123. }
  124. }
  125. }
  126. /*------------------------- public set and get methods --------------------------*/
  127. /// <summary>
  128. /// Add a method to this class
  129. /// </summary>
  130. /// <param name="name">method name</param>
  131. /// <param name="retType">return type</param>
  132. /// <param name="pars">parameter types</param>
  133. /// <returns>a descriptor for this method</returns>
  134. public MethodRef AddMethod(string name, Type retType, Type[] pars)
  135. {
  136. System.Diagnostics.Debug.Assert(retType != null);
  137. MethodRef meth = (MethodRef)GetMethodDesc(name, pars);
  138. if (meth != null) DescriptorError(meth);
  139. meth = new MethodRef(this, name, retType, pars);
  140. methods.Add(meth);
  141. return meth;
  142. }
  143. /// <summary>
  144. /// Add a method to this class
  145. /// </summary>
  146. /// <param name="name">method name</param>
  147. /// <param name="genPars">generic parameters</param>
  148. /// <param name="retType">return type</param>
  149. /// <param name="pars">parameter types</param>
  150. /// <returns>a descriptor for this method</returns>
  151. public MethodRef AddMethod(string name, GenericParam[] genPars, Type retType, Type[] pars)
  152. {
  153. MethodRef meth = AddMethod(name, retType, pars);
  154. if ((genPars != null) && (genPars.Length > 0))
  155. {
  156. for (int i = 0; i < genPars.Length; i++)
  157. {
  158. genPars[i].SetMethParam(meth, i);
  159. }
  160. meth.SetGenericParams(genPars);
  161. }
  162. return meth;
  163. }
  164. /// <summary>
  165. /// Add a method to this class
  166. /// </summary>
  167. /// <param name="name">method name</param>
  168. /// <param name="retType">return type</param>
  169. /// <param name="pars">parameter types</param>
  170. /// <param name="optPars">optional parameter types</param>
  171. /// <returns>a descriptor for this method</returns>
  172. public MethodRef AddVarArgMethod(string name, Type retType, Type[] pars, Type[] optPars)
  173. {
  174. MethodRef meth = AddMethod(name, retType, pars);
  175. meth.MakeVarArgMethod(null, optPars);
  176. return meth;
  177. }
  178. /// <summary>
  179. /// Add a method to this class
  180. /// </summary>
  181. /// <param name="name">method name</param>
  182. /// <param name="genPars">generic parameters</param>
  183. /// <param name="retType">return type</param>
  184. /// <param name="pars">parameter types</param>
  185. /// <param name="optPars">optional parameter types</param>
  186. /// <returns>a descriptor for this method</returns>
  187. public MethodRef AddVarArgMethod(string name, GenericParam[] genPars, Type retType, Type[] pars, Type[] optPars)
  188. {
  189. MethodRef meth = AddMethod(name, genPars, retType, pars);
  190. meth.MakeVarArgMethod(null, optPars);
  191. return meth;
  192. }
  193. /// <summary>
  194. /// Get the method "name" for this class
  195. /// </summary>
  196. /// <param name="name">The method name</param>
  197. /// <returns>Descriptor for the method "name" for this class</returns>
  198. public MethodRef GetMethod(string name)
  199. {
  200. return (MethodRef)GetMethodDesc(name);
  201. }
  202. /// <summary>
  203. /// Get the method "name(parTypes)" for this class
  204. /// </summary>
  205. /// <param name="name">Method name</param>
  206. /// <param name="parTypes">Method signature</param>
  207. /// <returns>Descriptor for "name(parTypes)"</returns>
  208. public MethodRef GetMethod(string name, Type[] parTypes)
  209. {
  210. return (MethodRef)GetMethodDesc(name, parTypes);
  211. }
  212. /// <summary>
  213. /// Get the vararg method "name(parTypes,optTypes)" for this class
  214. /// </summary>
  215. /// <param name="name">Method name</param>
  216. /// <param name="parTypes">Method parameter types</param>
  217. /// <param name="optTypes">Optional parameter types</param>
  218. /// <returns>Descriptor for "name(parTypes,optTypes)"</returns>
  219. public MethodRef GetMethod(string name, Type[] parTypes, Type[] optTypes)
  220. {
  221. return (MethodRef)GetMethodDesc(name, parTypes, optTypes);
  222. }
  223. /// <summary>
  224. /// Get the descriptors for the all methods name "name" for this class
  225. /// </summary>
  226. /// <param name="name">Method name</param>
  227. /// <returns>List of methods called "name"</returns>
  228. public MethodRef[] GetMethods(string name)
  229. {
  230. ArrayList meths = GetMeths(name);
  231. return (MethodRef[])meths.ToArray(typeof(MethodRef));
  232. }
  233. /// <summary>
  234. /// Get all the methods for this class
  235. /// </summary>
  236. /// <returns>List of methods for this class</returns>
  237. public MethodRef[] GetMethods()
  238. {
  239. return (MethodRef[])methods.ToArray(typeof(MethodRef));
  240. }
  241. /// <summary>
  242. /// Add a field to this class
  243. /// </summary>
  244. /// <param name="name">field name</param>
  245. /// <param name="fType">field type</param>
  246. /// <returns>a descriptor for this field</returns>
  247. public FieldRef AddField(string name, Type fType)
  248. {
  249. FieldRef fld = (FieldRef)FindField(name);
  250. if (fld != null) DescriptorError(fld);
  251. fld = new FieldRef(this, name, fType);
  252. fields.Add(fld);
  253. return fld;
  254. }
  255. /// <summary>
  256. /// Get the descriptor for the field "name" for this class
  257. /// </summary>
  258. /// <param name="name">Field name</param>
  259. /// <returns>Descriptor for field "name"</returns>
  260. public FieldRef GetField(string name)
  261. {
  262. return (FieldRef)FindField(name);
  263. }
  264. /// <summary>
  265. /// Get all the fields for this class
  266. /// </summary>
  267. /// <returns>List of fields for this class</returns>
  268. public FieldRef[] GetFields()
  269. {
  270. return (FieldRef[])fields.ToArray(typeof(FieldRef));
  271. }
  272. /// <summary>
  273. /// Add a nested class to this class
  274. /// </summary>
  275. /// <param name="name">Nested class name</param>
  276. /// <returns>Descriptor for the nested class "name"</returns>
  277. public NestedClassRef AddNestedClass(string name)
  278. {
  279. NestedClassRef nestedClass = (NestedClassRef)GetNested(name);
  280. if (nestedClass != null) DescriptorError(nestedClass);
  281. nestedClass = new NestedClassRef(this, name);
  282. AddToClassList(nestedClass);
  283. return nestedClass;
  284. }
  285. /// <summary>
  286. /// Get the nested class "name"
  287. /// </summary>
  288. /// <param name="name">Nestec class name</param>
  289. /// <returns>Descriptor for the nested class "name"</returns>
  290. public NestedClassRef GetNestedClass(string name)
  291. {
  292. // check nested names
  293. return (NestedClassRef)GetNested(name);
  294. }
  295. /// <summary>
  296. /// Make this Class exported from an Assembly (ie. add to ExportedType table)
  297. /// </summary>
  298. public void MakeExported()
  299. {
  300. if ((scope == null) || (!(scope is ModuleRef)))
  301. throw new Exception("Module not set for class to be exported");
  302. ((ModuleRef)scope).AddToExportedClassList(this);
  303. }
  304. /// <summary>
  305. /// Get the scope or "parent" of this ClassRef (either ModuleRef or AssemblyRef)
  306. /// </summary>
  307. /// <returns>Descriptor for the scope containing this class</returns>
  308. public virtual ReferenceScope GetScope()
  309. {
  310. return scope;
  311. }
  312. public override MetaDataElement GetParent() { return scope; }
  313. /*----------------------------- internal functions ------------------------------*/
  314. internal void SetExternClass(ExternClass eClass) { externClass = eClass; }
  315. internal void SetScope(ReferenceScope scope)
  316. {
  317. this.scope = scope;
  318. }
  319. internal void AddField(FieldRef fld)
  320. {
  321. fields.Add(fld);
  322. fld.SetParent(this);
  323. }
  324. internal void AddMethod(MethodRef meth)
  325. {
  326. MethodRef m = (MethodRef)GetMethodDesc(meth.Name(), meth.GetParTypes());
  327. if (m == null)
  328. {
  329. methods.Add(meth);
  330. meth.SetParent(this);
  331. }
  332. }
  333. /*
  334. internal FieldRef GetExistingField(string fName, uint tyIx, PEReader buff) {
  335. FieldRef existing = (FieldRef)FindField(fName);
  336. if (existing != null) {
  337. Type fType = buff.GetBlobType(tyIx);
  338. if (!fType.SameType(existing.GetFieldType()))
  339. throw new DescriptorException("Cannot have two fields (" + fName +
  340. ") for class " + name);
  341. }
  342. return existing;
  343. }
  344. */
  345. /*
  346. internal MethodRef CheckForMethod(string mName, uint sigIx, PEReader buff) {
  347. int exIx = FindMeth(mName,0);
  348. if (exIx > -1) {
  349. MethSig mType = buff.ReadMethSig(sigIx);
  350. mType.name = mName;
  351. exIx = FindMeth(mType,0);
  352. if (exIx > -1)
  353. return (MethodRef)methods[exIx];
  354. }
  355. return null;
  356. }
  357. */
  358. internal override string ClassName()
  359. {
  360. string nameString = nameSpace + "." + name;
  361. if ((scope != null) && (scope is AssemblyRef))
  362. nameString += (", " + ((AssemblyRef)scope).AssemblyString());
  363. return nameString;
  364. }
  365. internal bool HasParent(uint tok)
  366. {
  367. return resScopeIx == tok;
  368. }
  369. internal override void BuildTables(MetaDataOut md)
  370. {
  371. if (!special)
  372. {
  373. md.AddToTable(MDTable.TypeRef, this);
  374. nameIx = md.AddToStringsHeap(name);
  375. nameSpaceIx = md.AddToStringsHeap(nameSpace);
  376. }
  377. scope.BuildMDTables(md);
  378. }
  379. internal override void BuildCILInfo(CILWriter output)
  380. {
  381. if (!special && scope != null)
  382. {
  383. output.AddRef(scope);
  384. }
  385. }
  386. internal static uint Size(MetaData md)
  387. {
  388. return md.CodedIndexSize(CIx.ResolutionScope) + 2 * md.StringsIndexSize();
  389. }
  390. internal override void Write(PEWriter output)
  391. {
  392. output.WriteCodedIndex(CIx.ResolutionScope, scope);
  393. output.StringsIndex(nameIx);
  394. output.StringsIndex(nameSpaceIx);
  395. }
  396. internal override void WriteType(CILWriter output)
  397. {
  398. if ((nameSpace == null) || (nameSpace == ""))
  399. {
  400. output.Write("[" + scope.Name() + "]" + name);
  401. }
  402. else
  403. {
  404. output.Write("[" + scope.Name() + "]" + nameSpace + "." + name);
  405. }
  406. }
  407. internal override sealed uint TypeDefOrRefToken()
  408. {
  409. uint cIx = Row;
  410. cIx = (cIx << 2) | 0x1;
  411. return cIx;
  412. }
  413. internal sealed override uint GetCodedIx(CIx code)
  414. {
  415. switch (code)
  416. {
  417. case (CIx.TypeDefOrRef): return 1;
  418. case (CIx.HasCustomAttr): return 2;
  419. case (CIx.MemberRefParent): return 1;
  420. case (CIx.ResolutionScope): return 3;
  421. }
  422. return 0;
  423. }
  424. internal override string NameString()
  425. {
  426. string nameString = "";
  427. if (scope != null) nameString = "[" + scope.NameString() + "]";
  428. if ((nameSpace != null) && (nameSpace.Length > 0)) nameString += nameSpace + ".";
  429. nameString += name;
  430. return nameString;
  431. }
  432. }
  433. /**************************************************************************/
  434. /// <summary>
  435. /// Descriptor for a reference to a Nested Class
  436. /// </summary>
  437. public class NestedClassRef : ClassRef
  438. {
  439. ClassRef parent;
  440. internal uint parentIx = 0;
  441. /*-------------------- Constructors ---------------------------------*/
  442. internal NestedClassRef(ClassRef parent, string name)
  443. : base(parent.GetScope(), "", name)
  444. {
  445. this.parent = parent;
  446. }
  447. internal NestedClassRef(uint scopeIx, string nsName, string name)
  448. : base(scopeIx, nsName, name)
  449. {
  450. }
  451. internal NestedClassRef(ReferenceScope scope, string nsName, string name)
  452. : base(scope, nsName, name)
  453. {
  454. }
  455. internal override void ResolveParent(PEReader buff, bool isExtern)
  456. {
  457. if (parent != null) return;
  458. CIx cIx = CIx.ResolutionScope;
  459. if (isExtern) cIx = CIx.Implementation;
  460. parent = (ClassRef)buff.GetCodedElement(cIx, resScopeIx);
  461. parent.ResolveParent(buff, isExtern);
  462. parent = (ClassRef)buff.GetCodedElement(cIx, resScopeIx);
  463. if (parent == null) return;
  464. NestedClassRef existing = parent.GetNestedClass(name);
  465. if (existing == null)
  466. {
  467. scope = parent.GetScope();
  468. parent.AddToClassList(this);
  469. }
  470. else if (isExtern)
  471. buff.InsertInTable(MDTable.ExportedType, Row, existing);
  472. else
  473. buff.InsertInTable(MDTable.TypeRef, Row, existing);
  474. }
  475. /// <summary>
  476. /// Get the scope of this ClassRef (either ModuleRef or AssemblyRef)
  477. /// </summary>
  478. /// <returns>Descriptor for the scope containing this class</returns>
  479. public override ReferenceScope GetScope()
  480. {
  481. if (scope == null)
  482. scope = parent.GetScope();
  483. return scope;
  484. }
  485. /// <summary>
  486. /// Get the parent (enclosing ClassRef) for this nested class
  487. /// </summary>
  488. /// <returns>Enclosing class descriptor</returns>
  489. public ClassRef GetParentClass() { return parent; }
  490. internal void SetParent(ClassRef paren) { parent = paren; }
  491. internal override string ClassName()
  492. {
  493. string nameString = name;
  494. if (parent != null) nameString = parent.TypeName() + "+" + name;
  495. if ((scope != null) && (scope is AssemblyRef))
  496. nameString += (", " + ((AssemblyRef)scope).AssemblyString());
  497. return nameString;
  498. }
  499. internal override string NameString()
  500. {
  501. if (parent == null) return name;
  502. return parent.NameString() + "+" + name;
  503. }
  504. internal sealed override void BuildTables(MetaDataOut md)
  505. {
  506. if (!special)
  507. {
  508. md.AddToTable(MDTable.TypeRef, this);
  509. nameIx = md.AddToStringsHeap(name);
  510. nameSpaceIx = md.AddToStringsHeap(nameSpace);
  511. }
  512. parent.BuildMDTables(md);
  513. }
  514. internal sealed override void Write(PEWriter output)
  515. {
  516. output.WriteCodedIndex(CIx.ResolutionScope, parent);
  517. output.StringsIndex(nameIx);
  518. output.StringsIndex(nameSpaceIx);
  519. }
  520. }
  521. /**************************************************************************/
  522. /// <summary>
  523. /// Descriptor for a class defined in System (mscorlib)
  524. /// </summary>
  525. internal class SystemClass : ClassRef
  526. {
  527. PrimitiveType elemType;
  528. internal bool added = false;
  529. internal SystemClass(AssemblyRef paren, PrimitiveType eType)
  530. : base(paren, "System", eType.GetName())
  531. {
  532. elemType = eType;
  533. }
  534. // internal override sealed void AddTypeSpec(MetaDataOut md) {
  535. // elemType.AddTypeSpec(md);
  536. // if (typeSpec == null) typeSpec = (TypeSpec)elemType.GetTypeSpec(md);
  537. // return typeSpec;
  538. // }
  539. internal sealed override void TypeSig(MemoryStream str)
  540. {
  541. str.WriteByte(elemType.GetTypeIndex());
  542. }
  543. internal override bool SameType(Type tstType)
  544. {
  545. if (tstType is SystemClass)
  546. return elemType == ((SystemClass)tstType).elemType;
  547. return elemType == tstType;
  548. }
  549. }
  550. }