MDMethodElems.cs 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  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. /// Base class for Method Descriptors
  26. /// </summary>
  27. public abstract class Method : Member
  28. {
  29. protected MethSig sig;
  30. protected ArrayList genericParams;
  31. /*-------------------- Constructors ---------------------------------*/
  32. internal Method(string methName, Type rType, Class paren)
  33. : base(methName, paren)
  34. {
  35. sig = new MethSig(methName);
  36. sig.retType = rType;
  37. }
  38. internal Method(string name) : base(name) { }
  39. /// <summary>
  40. /// Add calling conventions to this method descriptor
  41. /// </summary>
  42. /// <param name="cconv"></param>
  43. public void AddCallConv(CallConv cconv)
  44. {
  45. sig.callConv |= cconv;
  46. }
  47. /// <summary>
  48. /// Get the calling conventions for this method
  49. /// </summary>
  50. /// <returns></returns>
  51. public CallConv GetCallConv()
  52. {
  53. return sig.callConv;
  54. }
  55. /// <summary>
  56. /// Set the return type
  57. /// </summary>
  58. /// <param name="retT">type returned</param>
  59. internal void AddRetType(Type retT)
  60. {
  61. System.Diagnostics.Debug.Assert(retT != null);
  62. sig.retType = retT;
  63. }
  64. /// <summary>
  65. /// Get the method return type
  66. /// </summary>
  67. /// <returns>method return type</returns>
  68. public Type GetRetType()
  69. {
  70. return sig.retType;
  71. }
  72. /// <summary>
  73. /// Get the types of the method parameters
  74. /// </summary>
  75. /// <returns>list of parameter types</returns>
  76. public Type[] GetParTypes()
  77. {
  78. return sig.parTypes;
  79. }
  80. /// <summary>
  81. /// Get the optional parameter types (for varargs)
  82. /// </summary>
  83. /// <returns>list of vararg types</returns>
  84. public Type[] GetOptParTypes()
  85. {
  86. return sig.optParTypes;
  87. }
  88. public int GetGenericParamCount()
  89. {
  90. return genericParams == null ? 0 : genericParams.Count;
  91. }
  92. /// <summary>
  93. /// Add a generic type to this method
  94. /// </summary>
  95. /// <param name="name">the name of the generic type</param>
  96. /// <returns>the descriptor for the generic type</returns>
  97. public GenericParam AddGenericParam(string name)
  98. {
  99. if (genericParams == null) genericParams = new ArrayList();
  100. GenericParam gp = new GenericParam(name, this, genericParams.Count);
  101. sig.callConv |= CallConv.Generic;
  102. genericParams.Add(gp);
  103. sig.numGenPars = (uint)genericParams.Count;
  104. return gp;
  105. }
  106. /// <summary>
  107. /// Get the descriptor for a generic type
  108. /// </summary>
  109. /// <param name="name">the name of the generic type</param>
  110. /// <returns>descriptor for generic type "name"</returns>
  111. public GenericParam GetGenericParam(string name)
  112. {
  113. int pos = FindGenericParam(name);
  114. if (pos == -1) return null;
  115. return (GenericParam)genericParams[pos];
  116. }
  117. public GenericParam GetGenericParam(int ix)
  118. {
  119. if ((genericParams == null) || (ix >= genericParams.Count)) return null;
  120. return (GenericParam)genericParams[ix];
  121. }
  122. public void RemoveGenericParam(string name)
  123. {
  124. int pos = FindGenericParam(name);
  125. if (pos == -1) return;
  126. DeleteGenericParam(pos);
  127. }
  128. public void RemoveGenericParam(int ix)
  129. {
  130. if (genericParams == null) return;
  131. if (ix >= genericParams.Count) return;
  132. DeleteGenericParam(ix);
  133. }
  134. public MethodSpec Instantiate(Type[] genTypes)
  135. {
  136. if (genTypes == null) return null;
  137. if ((genericParams == null) || (genericParams.Count == 0))
  138. throw new Exception("Cannot instantiate non-generic method");
  139. if (genTypes.Length != genericParams.Count)
  140. throw new Exception("Wrong number of type parameters for instantiation\nNeeded "
  141. + genericParams.Count + " but got " + genTypes.Length);
  142. return new MethodSpec(this, genTypes);
  143. }
  144. public GenericParam[] GetGenericParams()
  145. { // KJG June 2005
  146. if (genericParams == null) return null;
  147. return (GenericParam[])genericParams.ToArray(typeof(GenericParam));
  148. }
  149. /*------------------------- internal functions --------------------------*/
  150. internal abstract void TypeSig(MemoryStream sig);
  151. internal bool HasNameAndSig(string name, Type[] sigTypes)
  152. {
  153. if (this.name != name) return false;
  154. return sig.HasSig(sigTypes);
  155. }
  156. internal bool HasNameAndSig(string name, Type[] sigTypes, Type[] optPars)
  157. {
  158. if (this.name != name) return false;
  159. return sig.HasSig(sigTypes, optPars);
  160. }
  161. internal MethSig GetSig() { return sig; }
  162. internal MethSig GetSig(PEReader buff) {
  163. if (sig == null)
  164. sig = buff.ReadMethSig(this, this.sigIx);
  165. return sig;
  166. }
  167. internal void SetSig(MethSig sig)
  168. {
  169. this.sig = sig;
  170. this.sig.name = name;
  171. }
  172. internal override string NameString()
  173. {
  174. return parent.NameString() + sig.NameString();
  175. }
  176. private int FindGenericParam(string name)
  177. {
  178. if (genericParams == null) return -1;
  179. for (int i = 0; i < genericParams.Count; i++)
  180. {
  181. GenericParam gp = (GenericParam)genericParams[i];
  182. if (gp.GetName() == name) return i;
  183. }
  184. return -1;
  185. }
  186. private void DeleteGenericParam(int pos)
  187. {
  188. genericParams.RemoveAt(pos);
  189. for (int i = pos; i < genericParams.Count; i++)
  190. {
  191. GenericParam gp = (GenericParam)genericParams[i];
  192. gp.Index = (uint)i;
  193. }
  194. }
  195. internal void AddGenericParam(GenericParam par)
  196. {
  197. if (genericParams == null) genericParams = new ArrayList();
  198. genericParams.Add(par);
  199. //sig.callConv |= CallConv.Generic;
  200. //sig.numGenPars = (uint)genericParams.Count;
  201. }
  202. internal ArrayList GenericParams
  203. {
  204. get { return genericParams; }
  205. set { genericParams = value; }
  206. }
  207. internal void SetGenericParams(GenericParam[] pars)
  208. {
  209. genericParams = new ArrayList(pars);
  210. sig.callConv |= CallConv.Generic;
  211. sig.numGenPars = (uint)genericParams.Count;
  212. }
  213. internal override void WriteType(CILWriter output)
  214. {
  215. sig.WriteCallConv(output);
  216. sig.retType.WriteType(output);
  217. output.Write(" ");
  218. parent.WriteName(output);
  219. output.Write("::" + name);
  220. sig.WriteParTypes(output);
  221. }
  222. }
  223. /**************************************************************************/
  224. /// <summary>
  225. /// Descriptor for an Instantiation of a generic method
  226. /// </summary>
  227. public class MethodSpec : Method
  228. {
  229. Method methParent;
  230. uint instIx;
  231. Type[] instTypes;
  232. internal static byte GENERICINST = 0x0A;
  233. /*-------------------- Constructors ---------------------------------*/
  234. public MethodSpec(Method mParent, Type[] instTypes)
  235. : base(null)
  236. {
  237. this.methParent = mParent;
  238. this.instTypes = instTypes;
  239. tabIx = MDTable.MethodSpec;
  240. }
  241. internal MethodSpec(PEReader buff)
  242. : base(null)
  243. {
  244. parentIx = buff.GetCodedIndex(CIx.MethodDefOrRef);
  245. instIx = buff.GetBlobIx();
  246. tabIx = MDTable.MethodSpec;
  247. this.unresolved = true;
  248. }
  249. internal static void Read(PEReader buff, TableRow[] specs)
  250. {
  251. for (int i = 0; i < specs.Length; i++)
  252. specs[i] = new MethodSpec(buff);
  253. }
  254. internal override void Resolve(PEReader buff) {
  255. methParent = (Method)buff.GetCodedElement(CIx.MethodDefOrRef, parentIx);
  256. buff.currentMethodScope = methParent; // set scopes - Fix by CK
  257. buff.currentClassScope = (Class)methParent.GetParent();
  258. //
  259. // EXPERIMENTAL: The signature of the methParent must be
  260. // visible as the signature of this MethodSpec. The type-actuals
  261. // are held in the instTypes array.
  262. this.sig = this.methParent.GetSig(buff);
  263. instTypes = buff.ReadMethSpecSig(instIx);
  264. this.unresolved = false;
  265. //
  266. buff.currentMethodScope = null;
  267. buff.currentClassScope = null;
  268. }
  269. internal override void TypeSig(MemoryStream str)
  270. {
  271. str.WriteByte(GENERICINST);
  272. MetaDataOut.CompressNum(BlobUtil.CompressUInt((uint)instTypes.Length), str);
  273. for (int i = 0; i < instTypes.Length; i++)
  274. {
  275. instTypes[i].TypeSig(str);
  276. }
  277. }
  278. internal static uint Size(MetaData md)
  279. {
  280. return md.CodedIndexSize(CIx.MethodDefOrRef) + md.BlobIndexSize();
  281. }
  282. internal override void BuildTables(MetaDataOut md)
  283. {
  284. md.AddToTable(MDTable.MethodSpec, this);
  285. if (!(methParent is MethodDef)) // Never build a method def
  286. methParent.BuildMDTables(md);
  287. for (int i = 0; i < instTypes.Length; i++)
  288. {
  289. instTypes[i].BuildMDTables(md);
  290. }
  291. }
  292. internal override void BuildSignatures(MetaDataOut md)
  293. {
  294. MemoryStream outSig = new MemoryStream();
  295. TypeSig(outSig);
  296. instIx = md.AddToBlobHeap(outSig.ToArray());
  297. }
  298. internal override void Write(PEWriter output)
  299. {
  300. output.WriteCodedIndex(CIx.MethodDefOrRef, methParent);
  301. output.BlobIndex(instIx);
  302. }
  303. /*-------------------- Public Methods ------------------------------*/
  304. public Type[] GetGenericParamTypes()
  305. { // KJG 15 July 2005
  306. return instTypes;
  307. }
  308. public Method GetMethParent()
  309. { // KJG 15 July 2005
  310. return methParent;
  311. }
  312. }
  313. /**************************************************************************/
  314. /// <summary>
  315. /// Descriptor for a method defined in another assembly/module
  316. /// </summary>
  317. public class MethodRef : Method
  318. {
  319. internal MethodDef defOf;
  320. MethodDef varArgParent = null;
  321. /*-------------------- Constructors ---------------------------------*/
  322. internal MethodRef(Class paren, string name, Type retType, Type[] pars)
  323. : base(name, retType, paren)
  324. {
  325. sig.parTypes = pars;
  326. if (pars != null) sig.numPars = (uint)pars.Length;
  327. }
  328. internal MethodRef(uint parIx, string name, uint sigIx)
  329. : base(name)
  330. {
  331. this.parentIx = parIx;
  332. this.sigIx = sigIx;
  333. }
  334. internal MethodRef(MethSig sig)
  335. : base(sig.name)
  336. {
  337. this.sig = sig;
  338. }
  339. internal override void Resolve(PEReader buff)
  340. {
  341. if (sig == null)
  342. {
  343. buff.currentMethodScope = this;
  344. buff.currentClassScope = parent;
  345. sig = buff.ReadMethSig(this, name, sigIx);
  346. buff.currentMethodScope = null;
  347. buff.currentClassScope = null;
  348. }
  349. }
  350. internal override Member ResolveParent(PEReader buff)
  351. {
  352. if (parent != null) return this;
  353. buff.currentMethodScope = this;
  354. MetaDataElement paren = buff.GetCodedElement(CIx.MemberRefParent, parentIx);
  355. buff.currentMethodScope = null;
  356. if (paren is MethodDef)
  357. {
  358. parent = null;
  359. varArgParent = (MethodDef)paren;
  360. //this.sig = buff.ReadMethSig(this,name,sigIx);
  361. ((MethodDef)paren).AddVarArgSig(this);
  362. return this;
  363. }
  364. else if (paren is ClassSpec)
  365. {
  366. ((ClassSpec)paren).AddMethod(this);
  367. return this;
  368. }
  369. else if (paren is PrimitiveType)
  370. {
  371. paren = MSCorLib.mscorlib.GetDefaultClass();
  372. }
  373. else if (paren is ClassDef)
  374. {
  375. this.sig = buff.ReadMethSig(this, name, sigIx);
  376. return ((ClassDef)paren).GetMethod(this.sig);
  377. }
  378. else if (paren is TypeSpec)
  379. {
  380. paren = new ConstructedTypeSpec((TypeSpec)paren);
  381. //Console.WriteLine("Got TypeSpec as parent of Member");
  382. //return this;
  383. //throw new Exception("Got TypeSpec as parent of Member");
  384. //((TypeSpec)paren).AddMethod(buff,this);
  385. }
  386. if (paren is ReferenceScope)
  387. parent = ((ReferenceScope)paren).GetDefaultClass();
  388. parent = (Class)paren;
  389. //if ((MethodRef)parent.GetMethodDesc(name) != null) throw new PEFileException("Existing method!!");
  390. //sig = buff.ReadMethSig(this,name,sigIx);
  391. //MethodRef existing = (MethodRef)parent.GetMethod(sig);
  392. //if (existing != null)
  393. // return existing;
  394. parent.AddToMethodList(this);
  395. return this;
  396. }
  397. public void MakeVarArgMethod(MethodDef paren, Type[] optPars)
  398. {
  399. if (paren != null)
  400. {
  401. parent = null;
  402. varArgParent = paren;
  403. }
  404. sig.optParTypes = optPars;
  405. if (sig.optParTypes != null) sig.numOptPars = (uint)sig.optParTypes.Length;
  406. sig.callConv = CallConv.Vararg;
  407. }
  408. internal void MakeGenericPars(uint num)
  409. {
  410. // Experimental (kjg) 2007-09-03
  411. // It appears that for some system dll the MethodRef may not
  412. // have any generic params defined, but the methodSig does.
  413. if (genericParams == null)
  414. if (genericParams == null) genericParams = new ArrayList();
  415. for (int i = genericParams.Count; i < num; i++)
  416. {
  417. genericParams.Add(new GenericParam("GPar" + i, this, i));
  418. }
  419. // Previous code ...
  420. //if (genericParams != null) {
  421. // for (int i=genericParams.Count; i < num; i++) {
  422. // genericParams.Add(new GenericParam("GPar"+i,this,i));
  423. // }
  424. //}
  425. //sig.numGenPars = (uint)genericParams.Count;
  426. }
  427. /*------------------------- public set and get methods --------------------------*/
  428. /// <summary>
  429. /// Set the parameter types for this method
  430. /// </summary>
  431. /// <param name="pars">List of types of method parameters</param>
  432. public void SetParTypes(Type[] pars)
  433. {
  434. if (pars == null)
  435. {
  436. sig.numPars = 0;
  437. return;
  438. }
  439. sig.parTypes = pars;
  440. sig.numPars = (uint)pars.Length;
  441. }
  442. /// <summary>
  443. /// Set the list of optional parameter types for this method
  444. /// </summary>
  445. /// <param name="pars">list of optional parameter types</param>
  446. public void SetOptParTypes(Type[] pars)
  447. {
  448. if (pars == null)
  449. {
  450. sig.numOptPars = 0;
  451. return;
  452. }
  453. sig.optParTypes = pars;
  454. sig.numOptPars = (uint)sig.optParTypes.Length;
  455. }
  456. /*------------------------- internal functions --------------------------*/
  457. internal sealed override void TypeSig(MemoryStream sigStream)
  458. {
  459. sig.TypeSig(sigStream);
  460. }
  461. internal sealed override void BuildTables(MetaDataOut md)
  462. {
  463. md.AddToTable(MDTable.MemberRef, this);
  464. nameIx = md.AddToStringsHeap(name);
  465. if (parent != null)
  466. {
  467. if (parent is ClassSpec) md.ConditionalAddToTable(MDTable.TypeSpec, parent);
  468. if (parent is ConstructedTypeSpec)
  469. md.AddToTable(MDTable.TypeSpec, ((ConstructedTypeSpec)parent).Spec);
  470. parent.BuildMDTables(md);
  471. }
  472. sig.BuildTables(md);
  473. }
  474. internal sealed override void BuildSignatures(MetaDataOut md)
  475. {
  476. sig.BuildSignatures(md);
  477. MemoryStream sigStream = new MemoryStream();
  478. TypeSig(sigStream);
  479. sigIx = md.AddToBlobHeap(sigStream.ToArray());
  480. done = false;
  481. }
  482. internal override void BuildCILInfo(CILWriter output)
  483. {
  484. parent.BuildCILInfo(output);
  485. }
  486. internal static uint Size(MetaData md)
  487. {
  488. return md.CodedIndexSize(CIx.MemberRefParent) + md.StringsIndexSize() + md.BlobIndexSize();
  489. }
  490. internal sealed override void Write(PEWriter output)
  491. {
  492. if (varArgParent != null)
  493. output.WriteCodedIndex(CIx.MemberRefParent, varArgParent);
  494. else if (parent is ConstructedTypeSpec)
  495. output.WriteCodedIndex(CIx.MemberRefParent, ((ConstructedTypeSpec)parent).Spec);
  496. else
  497. output.WriteCodedIndex(CIx.MemberRefParent, parent);
  498. output.StringsIndex(nameIx);
  499. output.BlobIndex(sigIx);
  500. }
  501. internal sealed override uint GetCodedIx(CIx code)
  502. {
  503. switch (code)
  504. {
  505. case (CIx.HasCustomAttr): return 6;
  506. case (CIx.MethodDefOrRef): return 1;
  507. case (CIx.CustomAttributeType): return 3;
  508. }
  509. return 0;
  510. }
  511. }
  512. /**************************************************************************/
  513. /// <summary>
  514. /// Descriptor for a method defined in THIS assembly/module
  515. /// IL .method
  516. /// </summary>
  517. public class MethodDef : Method
  518. {
  519. private static readonly ushort PInvokeImpl = 0x2000;
  520. private static readonly ushort NotPInvoke = 0xDFFF;
  521. private static readonly ushort HasSecurity = 0x4000;
  522. private static readonly ushort NoSecurity = 0xBFFF;
  523. //private static readonly uint UnmanagedExport = 0x0008;
  524. uint parIx = 0, textOffset = 0;
  525. internal MethodRef refOf;
  526. // The default max stack depth to be assigned when the depth can not be calculated.
  527. private static readonly int DefaultMaxStackDepth = 8;
  528. CILInstructions code;
  529. uint rva;
  530. Param[] parList;
  531. Local[] locals;
  532. bool initLocals;
  533. ushort methFlags = 0, implFlags = 0;
  534. int maxStack = 0, numLocals = 0;
  535. uint numPars = 0;
  536. bool entryPoint = false;
  537. internal LocalSig localSig;
  538. MethodRef varArgSig;
  539. ImplMap pinvokeImpl;
  540. ArrayList security = null;
  541. internal uint locToken = 0;
  542. /*-------------------- Constructors ---------------------------------*/
  543. internal MethodDef(string name, Type retType, Param[] pars, ClassDef paren)
  544. : base(name, retType, paren)
  545. {
  546. sig.SetParTypes(pars);
  547. parList = pars;
  548. parent = paren;
  549. tabIx = MDTable.Method;
  550. }
  551. internal MethodDef(ClassDef paren, MethSig mSig, Param[] pars)
  552. : base(mSig.name)
  553. {
  554. sig = mSig;
  555. parList = pars;
  556. parent = paren;
  557. tabIx = MDTable.Method;
  558. }
  559. internal MethodDef(ClassSpec paren, MethSig mSig, Param[] pars)
  560. : base(mSig.name)
  561. {
  562. parent = paren;
  563. parList = pars;
  564. sig = mSig;
  565. tabIx = MDTable.Method;
  566. }
  567. internal MethodDef(PEReader buff)
  568. : base(null)
  569. {
  570. rva = buff.ReadUInt32();
  571. implFlags = buff.ReadUInt16();
  572. methFlags = buff.ReadUInt16();
  573. name = buff.GetString();
  574. sigIx = buff.GetBlobIx();
  575. parIx = buff.GetIndex(MDTable.Param);
  576. tabIx = MDTable.Method;
  577. }
  578. internal static void Read(PEReader buff, TableRow[] methDefs)
  579. {
  580. MethodDef prevDef = null;
  581. prevDef = new MethodDef(buff);
  582. methDefs[0] = prevDef;
  583. for (int i = 1; i < methDefs.Length; i++)
  584. {
  585. prevDef.Row = (uint)i;
  586. MethodDef methDef = new MethodDef(buff);
  587. prevDef.numPars = methDef.parIx - prevDef.parIx;
  588. prevDef = methDef;
  589. methDefs[i] = methDef;
  590. }
  591. prevDef.Row = (uint)methDefs.Length;
  592. prevDef.numPars = (buff.GetTableSize(MDTable.Param) + 1) - prevDef.parIx;
  593. }
  594. internal static void GetMethodRefs(PEReader buff, uint num, ClassRef parent)
  595. {
  596. for (int i = 0; i < num; i++)
  597. {
  598. uint rva = buff.ReadUInt32();
  599. ushort implFlags = buff.ReadUInt16();
  600. ushort methFlags = buff.ReadUInt16();
  601. string name = buff.GetString();
  602. uint sigIx = buff.GetBlobIx();
  603. uint parIx = buff.GetIndex(MDTable.Param);
  604. if (IsPublicOrProtected(methFlags))
  605. {
  606. MethodRef mRef = new MethodRef(parIx, name, sigIx); // changed
  607. mRef.SetParent(parent);
  608. //Console.WriteLine(parent.NameString());
  609. MethSig mSig = buff.ReadMethSig(mRef, name, sigIx);
  610. //mSig.name = name;
  611. mRef.SetSig(mSig); // changed
  612. parent.AddToMethodList(mRef);
  613. }
  614. }
  615. }
  616. private void DoPars(PEReader buff, bool resolvePars)
  617. {
  618. if (sig == null) sig = buff.ReadMethSig(this, sigIx);
  619. sig.name = name;
  620. parList = new Param[sig.numPars];
  621. if (parIx > buff.GetTableSize(MDTable.Param))
  622. {
  623. // EXPERIMENTAL kjg 19 November 2007
  624. // It is actually allowed that a method def does not
  625. // have corresponding Param metadata, provided the
  626. // parameter types may be constructed from the sig.
  627. for (uint i = 0; i < sig.numPars; i++)
  628. {
  629. parList[i] = Param.DefaultParam();
  630. parList[i].SetParType(sig.parTypes[i]);
  631. }
  632. }
  633. else
  634. {
  635. for (uint i = 0; i < sig.numPars; i++)
  636. {
  637. parList[i] = (Param)buff.GetElement(MDTable.Param, i + parIx);
  638. if (resolvePars) parList[i].Resolve(buff, i + parIx, sig.parTypes[i]);
  639. else parList[i].SetParType(sig.parTypes[i]);
  640. }
  641. }
  642. }
  643. private void DoCode(PEReader buff)
  644. {
  645. if (rva != 0)
  646. {
  647. if (Diag.DiagOn) Console.WriteLine("Reading byte codes for method " + name);
  648. buff.ReadByteCodes(this, rva);
  649. }
  650. }
  651. internal sealed override void Resolve(PEReader buff)
  652. {
  653. buff.currentMethodScope = this;
  654. buff.currentClassScope = parent;
  655. DoPars(buff, true);
  656. if (!buff.skipBody)
  657. {
  658. DoCode(buff);
  659. }
  660. buff.currentMethodScope = null;
  661. buff.currentClassScope = null;
  662. }
  663. /*------------------------- public set and get methods --------------------------*/
  664. /// <summary>
  665. /// Get the parameters of this method
  666. /// </summary>
  667. /// <returns>Array of params of this method</returns>
  668. public Param[] GetParams()
  669. {
  670. return parList;
  671. }
  672. /// <summary>
  673. /// Set the parameters for this method
  674. /// </summary>
  675. /// <param name="pars">Descriptors of the parameters for this method</param>
  676. public void SetParams(Param[] pars)
  677. {
  678. parList = pars;
  679. sig.SetParTypes(pars);
  680. }
  681. /// <summary>
  682. /// Add some attributes to this method descriptor
  683. /// </summary>
  684. /// <param name="ma">the attributes to be added</param>
  685. public void AddMethAttribute(MethAttr ma) { methFlags |= (ushort)ma; }
  686. /// <summary>
  687. /// Property to get and set the attributes for this method
  688. /// </summary>
  689. public MethAttr GetMethAttributes() { return (MethAttr)methFlags; }
  690. public void SetMethAttributes(MethAttr ma) { methFlags = (ushort)ma; }
  691. /// <summary>
  692. /// Add some implementation attributes to this method descriptor
  693. /// </summary>
  694. /// <param name="ia">the attributes to be added</param>
  695. public void AddImplAttribute(ImplAttr ia)
  696. {
  697. implFlags |= (ushort)ia;
  698. }
  699. /// <summary>
  700. /// Property to get and set the implementation attributes for this method
  701. /// </summary>
  702. public ImplAttr GetImplAttributes() { return (ImplAttr)implFlags; }
  703. public void SetImplAttributes(ImplAttr ia) { implFlags = (ushort)ia; }
  704. public void AddPInvokeInfo(ModuleRef scope, string methName,
  705. PInvokeAttr callAttr)
  706. {
  707. pinvokeImpl = new ImplMap((ushort)callAttr, this, methName, scope);
  708. methFlags |= PInvokeImpl;
  709. }
  710. public void RemovePInvokeInfo()
  711. {
  712. pinvokeImpl = null;
  713. methFlags &= NotPInvoke;
  714. }
  715. public void AddSecurity(SecurityAction act, byte[] permissionSet)
  716. {
  717. methFlags |= HasSecurity;
  718. if (security == null) security = new ArrayList();
  719. security.Add(new DeclSecurity(this, act, permissionSet));
  720. }
  721. public void AddSecurity(DeclSecurity sec)
  722. {
  723. methFlags |= HasSecurity;
  724. if (security == null) security = new ArrayList();
  725. security.Add(sec);
  726. }
  727. public DeclSecurity[] GetSecurity()
  728. {
  729. if (security == null) return null;
  730. return (DeclSecurity[])security.ToArray(typeof(DeclSecurity));
  731. }
  732. public void RemoveSecurity()
  733. {
  734. security = null;
  735. methFlags &= NoSecurity;
  736. }
  737. /// <summary>
  738. /// Set the maximum stack height for this method
  739. /// </summary>
  740. /// <param name="maxStack">the maximum height of the stack</param>
  741. public void SetMaxStack(int maxStack)
  742. {
  743. this.maxStack = maxStack;
  744. }
  745. /// <summary>
  746. /// Retrieve the maximum size of the stack for the code
  747. /// of this method
  748. /// </summary>
  749. /// <returns>max stack height for CIL codes</returns>
  750. public int GetMaxStack()
  751. {
  752. return maxStack;
  753. }
  754. /// <summary>
  755. /// Add local variables to this method
  756. /// </summary>
  757. /// <param name="locals">the locals to be added</param>
  758. /// <param name="initLocals">are locals initialised to default values</param>
  759. public void AddLocals(Local[] locals, bool initLocals)
  760. {
  761. if (locals == null) return;
  762. this.locals = locals;
  763. this.initLocals = initLocals;
  764. numLocals = locals.Length;
  765. for (int i = 0; i < numLocals; i++)
  766. {
  767. this.locals[i].SetIndex(i);
  768. }
  769. }
  770. /// <summary>
  771. /// Retrieve the locals for this method
  772. /// </summary>
  773. /// <returns>list of locals declared in this method</returns>
  774. public Local[] GetLocals() { return locals; }
  775. /// <summary>
  776. /// Remove all the locals from this method
  777. /// </summary>
  778. public void RemoveLocals()
  779. {
  780. locals = null;
  781. numLocals = 0;
  782. initLocals = false;
  783. }
  784. /// <summary>
  785. /// Mark this method as having an entry point
  786. /// </summary>
  787. public void DeclareEntryPoint() { entryPoint = true; }
  788. /// <summary>
  789. /// Does this method have an entrypoint?
  790. /// </summary>
  791. public bool HasEntryPoint() { return entryPoint; }
  792. /// <summary>
  793. /// Remove the entry point from this method
  794. /// </summary>
  795. public void RemoveEntryPoint() { entryPoint = false; }
  796. /// <summary>
  797. /// Create a code buffer for this method to add the IL instructions to
  798. /// </summary>
  799. /// <returns>a buffer for this method's IL instructions</returns>
  800. public CILInstructions CreateCodeBuffer()
  801. {
  802. code = new CILInstructions(this);
  803. return code;
  804. }
  805. /// <summary>
  806. /// Get the CIL code buffer for this method
  807. /// </summary>
  808. /// <returns>Code buffer for this method</returns>
  809. public CILInstructions GetCodeBuffer() { return code; }
  810. /// <summary>
  811. /// Make a method reference descriptor for this method to be used
  812. /// as a callsite signature for this vararg method
  813. /// </summary>
  814. /// <param name="optPars">the optional pars for the vararg method call</param>
  815. /// <returns></returns>
  816. public MethodRef MakeVarArgSignature(Type[] optPars)
  817. {
  818. MethSig mSig = new MethSig(name);
  819. mSig.parTypes = sig.parTypes;
  820. mSig.retType = sig.retType;
  821. varArgSig = new MethodRef(sig);
  822. varArgSig.MakeVarArgMethod(this, optPars);
  823. return varArgSig;
  824. }
  825. public MethodRef GetVarArgSignature()
  826. {
  827. return varArgSig;
  828. }
  829. /// <summary>
  830. /// Get the MethodRef equivalent to this MethodDef. Assumes
  831. /// that one has been created.
  832. /// </summary>
  833. /// <returns>MethodRef for this MethodDef</returns>
  834. public MethodRef RefOf() { return refOf; }
  835. /// <summary>
  836. /// Get the MethodRef equivalent to this MethodDef. If one
  837. /// does not exist, then create it.
  838. /// </summary>
  839. /// <returns>MethodRef for this MethodDef</returns>
  840. public MethodRef MakeRefOf()
  841. {
  842. if (refOf != null) return refOf;
  843. ClassRef parRef = ((ClassDef)parent).MakeRefOf();
  844. refOf = parRef.GetMethod(name, sig.parTypes);
  845. if (refOf == null)
  846. {
  847. Type rType = sig.MakeRefRetType();
  848. Type[] pTypes = sig.MakeRefParTypes();
  849. refOf = new MethodRef(parRef, name, rType, pTypes);
  850. refOf.defOf = this;
  851. refOf.AddCallConv(this.GetCallConv());
  852. }
  853. return refOf;
  854. }
  855. /*------------------------- internal functions --------------------------*/
  856. private static bool IsPublicOrProtected(ushort methFlags)
  857. {
  858. return (methFlags & (ushort)MethAttr.Public) == (ushort)MethAttr.Public ||
  859. (methFlags & (ushort)MethAttr.Family) == (ushort)MethAttr.Family;
  860. }
  861. internal void InsertGenericParam(GenericParam genPar)
  862. {
  863. if (genericParams == null) genericParams = new ArrayList();
  864. for (int i = 0; i < genericParams.Count - genPar.Index; i++)
  865. {
  866. genericParams.Add(null);
  867. }
  868. genericParams.Insert((int)genPar.Index, genPar);
  869. }
  870. internal override bool isDef() { return true; }
  871. internal PEFile GetScope()
  872. {
  873. return ((ClassDef)parent).GetScope();
  874. }
  875. internal void ChangeRefsToDefs(ClassDef newPar, ClassDef[] oldTypes)
  876. {
  877. parent = newPar;
  878. sig.ChangeParTypes(newPar, oldTypes);
  879. if (code != null)
  880. code.ChangeRefsToDefs(newPar, oldTypes);
  881. }
  882. internal void AddPInvokeInfo(ImplMap impl)
  883. {
  884. pinvokeImpl = impl;
  885. methFlags |= PInvokeImpl;
  886. }
  887. internal void AddVarArgSig(MethodRef meth)
  888. {
  889. varArgSig = meth;
  890. //meth.MakeVarArgMethod(this,null);
  891. }
  892. internal sealed override void TypeSig(MemoryStream sigStream)
  893. {
  894. sig.TypeSig(sigStream);
  895. }
  896. // fix for Whidbey bug
  897. internal void AddGenericsToTable(MetaDataOut md)
  898. {
  899. if (genericParams != null)
  900. {
  901. for (int i = 0; i < genericParams.Count; i++)
  902. {
  903. md.AddToTable(MDTable.GenericParam, (GenericParam)genericParams[i]);
  904. }
  905. }
  906. }
  907. internal sealed override void BuildTables(MetaDataOut md)
  908. {
  909. md.AddToTable(MDTable.Method, this);
  910. nameIx = md.AddToStringsHeap(name);
  911. if (genericParams != null)
  912. {
  913. for (int i = 0; i < genericParams.Count; i++)
  914. {
  915. ((GenericParam)genericParams[i]).BuildMDTables(md);
  916. }
  917. }
  918. if (security != null)
  919. {
  920. for (int i = 0; i < security.Count; i++)
  921. {
  922. ((DeclSecurity)security[i]).BuildMDTables(md);
  923. }
  924. }
  925. if (pinvokeImpl != null) pinvokeImpl.BuildMDTables(md);
  926. if (entryPoint) md.SetEntryPoint(this);
  927. if (locals != null)
  928. {
  929. localSig = new LocalSig(locals);
  930. localSig.BuildMDTables(md);
  931. }
  932. try
  933. {
  934. if (code != null)
  935. {
  936. if (code.IsEmpty())
  937. {
  938. code = null;
  939. }
  940. else
  941. {
  942. code.BuildTables(md);
  943. }
  944. }
  945. }
  946. catch (InstructionException ex)
  947. {
  948. throw new Exception(ex.AddMethodName(name));
  949. }
  950. parIx = md.TableIndex(MDTable.Param);
  951. for (int i = 0; i < sig.numPars; i++)
  952. {
  953. parList[i].seqNo = (ushort)(i + 1);
  954. parList[i].BuildMDTables(md);
  955. }
  956. sig.BuildTables(md);
  957. }
  958. internal sealed override void BuildCILInfo(CILWriter output)
  959. {
  960. if (genericParams != null)
  961. {
  962. for (int i = 0; i < genericParams.Count; i++)
  963. {
  964. ((GenericParam)genericParams[i]).BuildCILInfo(output);
  965. }
  966. }
  967. if (security != null)
  968. {
  969. for (int i = 0; i < security.Count; i++)
  970. {
  971. ((DeclSecurity)security[i]).BuildCILInfo(output);
  972. }
  973. }
  974. if (pinvokeImpl != null) pinvokeImpl.BuildCILInfo(output);
  975. if (locals != null)
  976. {
  977. for (int i = 0; i < locals.Length; i++)
  978. {
  979. locals[i].BuildCILInfo(output);
  980. }
  981. }
  982. try
  983. {
  984. if (code != null) code.BuildCILInfo(output);
  985. }
  986. catch (InstructionException ex)
  987. {
  988. throw new Exception(ex.AddMethodName(name));
  989. }
  990. sig.BuildCILInfo(output);
  991. }
  992. internal sealed override void BuildSignatures(MetaDataOut md)
  993. {
  994. if (locals != null)
  995. {
  996. localSig.BuildSignatures(md);
  997. locToken = localSig.Token();
  998. }
  999. if (code != null)
  1000. {
  1001. // If the stack depth has not been explicity set, try to work out what is needed.
  1002. if (maxStack == 0)
  1003. {
  1004. try
  1005. {
  1006. // Set the flag to show if the return type is void or other.
  1007. code.ReturnsVoid = GetRetType().SameType(PrimitiveType.Void);
  1008. // Calculate the max stack depth
  1009. maxStack = code.GetMaxStackDepthRequired();
  1010. }
  1011. catch (CouldNotFindMaxStackDepth)
  1012. {
  1013. // Could not find the depth, assign the default
  1014. maxStack = DefaultMaxStackDepth;
  1015. }
  1016. }
  1017. code.CheckCode(locToken, initLocals, maxStack, md);
  1018. textOffset = md.AddCode(code);
  1019. if (Diag.DiagOn) Console.WriteLine("code offset = " + textOffset);
  1020. }
  1021. sig.BuildSignatures(md);
  1022. MemoryStream outSig = new MemoryStream();
  1023. TypeSig(outSig);
  1024. sigIx = md.AddToBlobHeap(outSig.ToArray());
  1025. done = false;
  1026. }
  1027. internal static uint Size(MetaData md)
  1028. {
  1029. return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
  1030. }
  1031. internal sealed override void Write(PEWriter output)
  1032. {
  1033. if (code == null) output.Write(0);
  1034. else output.WriteCodeRVA(textOffset);
  1035. output.Write(implFlags);
  1036. output.Write(methFlags);
  1037. output.StringsIndex(nameIx);
  1038. output.BlobIndex(sigIx);
  1039. output.WriteIndex(MDTable.Param, parIx);
  1040. }
  1041. internal override void Write(CILWriter output)
  1042. {
  1043. output.Write(" .method ");
  1044. WriteFlags(output, methFlags);
  1045. sig.Write(output);
  1046. output.Write(" " + name + "(");
  1047. if (parList != null)
  1048. {
  1049. for (int i = 0; i < parList.Length; i++)
  1050. {
  1051. parList[i].Write(output);
  1052. if (i < parList.Length - 1)
  1053. {
  1054. output.Write(", ");
  1055. }
  1056. }
  1057. }
  1058. output.Write(") ");
  1059. uint codeType = implFlags & (uint)0x11;
  1060. if (codeType == 0)
  1061. {
  1062. output.Write("cil ");
  1063. }
  1064. else if (codeType == 1)
  1065. {
  1066. output.Write("native ");
  1067. }
  1068. else if (codeType == 3)
  1069. {
  1070. output.Write("runtime ");
  1071. }
  1072. if ((implFlags & (uint)ImplAttr.Unmanaged) == 0)
  1073. {
  1074. output.Write("managed ");
  1075. }
  1076. else
  1077. {
  1078. output.Write("unmanaged ");
  1079. }
  1080. if ((implFlags & (uint)ImplAttr.ForwardRef) != 0)
  1081. {
  1082. output.Write("forwardref ");
  1083. }
  1084. if ((implFlags & (uint)ImplAttr.InternalCall) != 0)
  1085. {
  1086. output.Write("internalcall ");
  1087. }
  1088. if ((implFlags & (uint)ImplAttr.Synchronized) != 0)
  1089. {
  1090. output.Write("synchronized ");
  1091. }
  1092. if ((implFlags & (uint)ImplAttr.NoInLining) != 0)
  1093. {
  1094. output.Write("noinlining ");
  1095. }
  1096. output.WriteLine(" {");
  1097. if ((locals != null) && (locals.Length > 0))
  1098. {
  1099. output.Write(" .locals (");
  1100. for (int i = 0; i < locals.Length; i++)
  1101. {
  1102. if (i > 0)
  1103. {
  1104. output.Write(" ");
  1105. }
  1106. locals[i].Write(output);
  1107. if (i < locals.Length - 1)
  1108. {
  1109. output.WriteLine(",");
  1110. }
  1111. }
  1112. output.WriteLine(" )");
  1113. }
  1114. if (entryPoint)
  1115. {
  1116. output.WriteLine(" .entrypoint");
  1117. }
  1118. if (code != null) code.Write(output);
  1119. output.WriteLine(" }");
  1120. }
  1121. internal sealed override uint GetCodedIx(CIx code)
  1122. {
  1123. switch (code)
  1124. {
  1125. case (CIx.HasCustomAttr): return 0;
  1126. case (CIx.HasDeclSecurity): return 1;
  1127. case (CIx.MemberRefParent): return 3;
  1128. case (CIx.MethodDefOrRef): return 0;
  1129. case (CIx.MemberForwarded): return 1;
  1130. case (CIx.CustomAttributeType): return 2;
  1131. case (CIx.TypeOrMethodDef): return 1;
  1132. }
  1133. return 0;
  1134. }
  1135. }
  1136. }