MDMethodElems.cs 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292
  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.ConditionalAddTypeSpec(parent);
  468. if (parent is ConstructedTypeSpec)
  469. md.ConditionalAddTypeSpec(((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. // The following code is done out of line in method
  933. // TraverseCode *after* all the method indices have
  934. // been allocated in the metadata.
  935. // (kjg, March 2010)
  936. //try {
  937. // if (code != null) {
  938. // if (code.IsEmpty()) {
  939. // code = null;
  940. // }
  941. // else {
  942. // code.BuildTables(md);
  943. // }
  944. // }
  945. //}
  946. //catch (InstructionException ex) {
  947. // throw new Exception(ex.AddMethodName(name));
  948. //}
  949. parIx = md.TableIndex(MDTable.Param);
  950. for (int i = 0; i < sig.numPars; i++)
  951. {
  952. parList[i].seqNo = (ushort)(i + 1);
  953. parList[i].BuildMDTables(md);
  954. }
  955. sig.BuildTables(md);
  956. }
  957. internal void TraverseCode(MetaDataOut md) {
  958. try {
  959. if (code != null) {
  960. if (code.IsEmpty()) {
  961. code = null;
  962. }
  963. else {
  964. code.BuildTables(md);
  965. }
  966. }
  967. }
  968. catch (InstructionException ex) {
  969. throw new Exception(ex.AddMethodName(name));
  970. }
  971. }
  972. internal sealed override void BuildCILInfo(CILWriter output)
  973. {
  974. if (genericParams != null)
  975. {
  976. for (int i = 0; i < genericParams.Count; i++)
  977. {
  978. ((GenericParam)genericParams[i]).BuildCILInfo(output);
  979. }
  980. }
  981. if (security != null)
  982. {
  983. for (int i = 0; i < security.Count; i++)
  984. {
  985. ((DeclSecurity)security[i]).BuildCILInfo(output);
  986. }
  987. }
  988. if (pinvokeImpl != null) pinvokeImpl.BuildCILInfo(output);
  989. if (locals != null)
  990. {
  991. for (int i = 0; i < locals.Length; i++)
  992. {
  993. locals[i].BuildCILInfo(output);
  994. }
  995. }
  996. try
  997. {
  998. if (code != null) code.BuildCILInfo(output);
  999. }
  1000. catch (InstructionException ex)
  1001. {
  1002. throw new Exception(ex.AddMethodName(name));
  1003. }
  1004. sig.BuildCILInfo(output);
  1005. }
  1006. internal sealed override void BuildSignatures(MetaDataOut md)
  1007. {
  1008. if (locals != null)
  1009. {
  1010. localSig.BuildSignatures(md);
  1011. locToken = localSig.Token();
  1012. }
  1013. if (code != null)
  1014. {
  1015. // If the stack depth has not been explicity set, try to work out what is needed.
  1016. if (maxStack == 0)
  1017. {
  1018. try
  1019. {
  1020. // Set the flag to show if the return type is void or other.
  1021. code.ReturnsVoid = GetRetType().SameType(PrimitiveType.Void);
  1022. // Calculate the max stack depth
  1023. maxStack = code.GetMaxStackDepthRequired();
  1024. }
  1025. catch (CouldNotFindMaxStackDepth)
  1026. {
  1027. // Could not find the depth, assign the default
  1028. maxStack = DefaultMaxStackDepth;
  1029. }
  1030. }
  1031. code.CheckCode(locToken, initLocals, maxStack, md);
  1032. textOffset = md.AddCode(code);
  1033. if (Diag.DiagOn) Console.WriteLine("code offset = " + textOffset);
  1034. }
  1035. sig.BuildSignatures(md);
  1036. MemoryStream outSig = new MemoryStream();
  1037. TypeSig(outSig);
  1038. sigIx = md.AddToBlobHeap(outSig.ToArray());
  1039. done = false;
  1040. }
  1041. internal static uint Size(MetaData md)
  1042. {
  1043. return 8 + md.StringsIndexSize() + md.BlobIndexSize() + md.TableIndexSize(MDTable.Param);
  1044. }
  1045. internal sealed override void Write(PEWriter output)
  1046. {
  1047. if (code == null) output.Write(0);
  1048. else output.WriteCodeRVA(textOffset);
  1049. output.Write(implFlags);
  1050. output.Write(methFlags);
  1051. output.StringsIndex(nameIx);
  1052. output.BlobIndex(sigIx);
  1053. output.WriteIndex(MDTable.Param, parIx);
  1054. }
  1055. internal override void Write(CILWriter output)
  1056. {
  1057. output.Write(" .method ");
  1058. WriteFlags(output, methFlags);
  1059. sig.Write(output);
  1060. output.Write(" " + name + "(");
  1061. if (parList != null)
  1062. {
  1063. for (int i = 0; i < parList.Length; i++)
  1064. {
  1065. parList[i].Write(output);
  1066. if (i < parList.Length - 1)
  1067. {
  1068. output.Write(", ");
  1069. }
  1070. }
  1071. }
  1072. output.Write(") ");
  1073. uint codeType = implFlags & (uint)0x11;
  1074. if (codeType == 0)
  1075. {
  1076. output.Write("cil ");
  1077. }
  1078. else if (codeType == 1)
  1079. {
  1080. output.Write("native ");
  1081. }
  1082. else if (codeType == 3)
  1083. {
  1084. output.Write("runtime ");
  1085. }
  1086. if ((implFlags & (uint)ImplAttr.Unmanaged) == 0)
  1087. {
  1088. output.Write("managed ");
  1089. }
  1090. else
  1091. {
  1092. output.Write("unmanaged ");
  1093. }
  1094. if ((implFlags & (uint)ImplAttr.ForwardRef) != 0)
  1095. {
  1096. output.Write("forwardref ");
  1097. }
  1098. if ((implFlags & (uint)ImplAttr.InternalCall) != 0)
  1099. {
  1100. output.Write("internalcall ");
  1101. }
  1102. if ((implFlags & (uint)ImplAttr.Synchronized) != 0)
  1103. {
  1104. output.Write("synchronized ");
  1105. }
  1106. if ((implFlags & (uint)ImplAttr.NoInLining) != 0)
  1107. {
  1108. output.Write("noinlining ");
  1109. }
  1110. output.WriteLine(" {");
  1111. if ((locals != null) && (locals.Length > 0))
  1112. {
  1113. output.Write(" .locals (");
  1114. for (int i = 0; i < locals.Length; i++)
  1115. {
  1116. if (i > 0)
  1117. {
  1118. output.Write(" ");
  1119. }
  1120. locals[i].Write(output);
  1121. if (i < locals.Length - 1)
  1122. {
  1123. output.WriteLine(",");
  1124. }
  1125. }
  1126. output.WriteLine(" )");
  1127. }
  1128. if (entryPoint)
  1129. {
  1130. output.WriteLine(" .entrypoint");
  1131. }
  1132. if (code != null) code.Write(output);
  1133. output.WriteLine(" }");
  1134. }
  1135. internal sealed override uint GetCodedIx(CIx code)
  1136. {
  1137. switch (code)
  1138. {
  1139. case (CIx.HasCustomAttr): return 0;
  1140. case (CIx.HasDeclSecurity): return 1;
  1141. case (CIx.MemberRefParent): return 3;
  1142. case (CIx.MethodDefOrRef): return 0;
  1143. case (CIx.MemberForwarded): return 1;
  1144. case (CIx.CustomAttributeType): return 2;
  1145. case (CIx.TypeOrMethodDef): return 1;
  1146. }
  1147. return 0;
  1148. }
  1149. }
  1150. }