/Debugger/Debugger.Core/Mono.Cecil/Mono.Cecil.Signatures/SignatureReader.cs

http://github.com/icsharpcode/ILSpy · C# · 991 lines · 454 code · 63 blank · 474 comment · 97 complexity · 42ab2afe5f40cd946f689309eb8cc2ed MD5 · raw file

  1. //
  2. // SignatureReader.cs
  3. //
  4. // Author:
  5. // Jb Evain (jbevain@gmail.com)
  6. //
  7. // (C) 2005 - 2007 Jb Evain
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. namespace Mono.Cecil.Signatures {
  29. using System;
  30. using System.Collections;
  31. using System.IO;
  32. using System.Text;
  33. using Mono.Cecil;
  34. using Mono.Cecil.Metadata;
  35. internal sealed class SignatureReader : BaseSignatureVisitor {
  36. byte [] m_blobData;
  37. IDictionary m_signatures;
  38. public byte[] Blob {
  39. get {
  40. return m_blobData;
  41. }
  42. }
  43. public SignatureReader (byte [] blobData)
  44. {
  45. m_blobData = blobData;
  46. m_signatures = new Hashtable ();
  47. }
  48. /*
  49. MetadataRoot m_root;
  50. ReflectionReader m_reflectReader;
  51. byte [] m_blobData;
  52. IDictionary m_signatures;
  53. IAssemblyResolver AssemblyResolver {
  54. get { return m_reflectReader.Module.Assembly.Resolver; }
  55. }
  56. public SignatureReader (MetadataRoot root, ReflectionReader reflectReader)
  57. {
  58. m_root = root;
  59. m_reflectReader = reflectReader;
  60. m_blobData = m_root.Streams.BlobHeap != null ? m_root.Streams.BlobHeap.Data : new byte [0];
  61. m_signatures = new Hashtable ();
  62. }
  63. */
  64. public FieldSig GetFieldSig (uint index)
  65. {
  66. FieldSig f = m_signatures [index] as FieldSig;
  67. if (f == null) {
  68. f = new FieldSig (index);
  69. f.Accept (this);
  70. m_signatures [index] = f;
  71. }
  72. return f;
  73. }
  74. public PropertySig GetPropSig (uint index)
  75. {
  76. PropertySig p = m_signatures [index] as PropertySig;
  77. if (p == null) {
  78. p = new PropertySig (index);
  79. p.Accept (this);
  80. m_signatures [index] = p;
  81. }
  82. return p;
  83. }
  84. public MethodDefSig GetMethodDefSig (uint index)
  85. {
  86. MethodDefSig m = m_signatures [index] as MethodDefSig;
  87. if (m == null) {
  88. m = new MethodDefSig (index);
  89. m.Accept (this);
  90. m_signatures [index] = m;
  91. }
  92. return m;
  93. }
  94. public MethodRefSig GetMethodRefSig (uint index)
  95. {
  96. MethodRefSig m = m_signatures [index] as MethodRefSig;
  97. if (m == null) {
  98. m = new MethodRefSig (index);
  99. m.Accept (this);
  100. m_signatures [index] = m;
  101. }
  102. return m;
  103. }
  104. public TypeSpec GetTypeSpec (uint index)
  105. {
  106. TypeSpec ts = m_signatures [index] as TypeSpec;
  107. if (ts == null) {
  108. ts = ReadTypeSpec (m_blobData, (int) index);
  109. m_signatures [index] = ts;
  110. }
  111. return ts;
  112. }
  113. public MethodSpec GetMethodSpec (uint index)
  114. {
  115. MethodSpec ms = m_signatures [index] as MethodSpec;
  116. if (ms == null) {
  117. ms = ReadMethodSpec (m_blobData, (int) index);
  118. m_signatures [index] = ms;
  119. }
  120. return ms;
  121. }
  122. public LocalVarSig GetLocalVarSig (uint index)
  123. {
  124. LocalVarSig lv = m_signatures [index] as LocalVarSig;
  125. if (lv == null) {
  126. lv = new LocalVarSig (index);
  127. lv.Accept (this);
  128. m_signatures [index] = lv;
  129. }
  130. return lv;
  131. }
  132. /*
  133. public CustomAttrib GetCustomAttrib (uint index, MethodReference ctor)
  134. {
  135. return GetCustomAttrib (index, ctor, false);
  136. }
  137. public CustomAttrib GetCustomAttrib (uint index, MethodReference ctor, bool resolve)
  138. {
  139. return ReadCustomAttrib ((int) index, ctor, resolve);
  140. }
  141. public CustomAttrib GetCustomAttrib (byte [] data, MethodReference ctor)
  142. {
  143. return GetCustomAttrib (data, ctor, false);
  144. }
  145. public CustomAttrib GetCustomAttrib (byte [] data, MethodReference ctor, bool resolve)
  146. {
  147. BinaryReader br = new BinaryReader (new MemoryStream (data));
  148. return ReadCustomAttrib (br, data, ctor, resolve);
  149. }
  150. */
  151. public Signature GetMemberRefSig (TokenType tt, uint index)
  152. {
  153. int start, callconv;
  154. Utilities.ReadCompressedInteger (m_blobData, (int) index, out start);
  155. callconv = m_blobData [start];
  156. if ((callconv & 0x5) == 0x5 || (callconv & 0x10) == 0x10) // vararg || generic?
  157. return GetMethodDefSig (index);
  158. if ((callconv & 0x6) != 0) // field ?
  159. return GetFieldSig (index);
  160. switch (tt) {
  161. case TokenType.TypeDef :
  162. case TokenType.TypeRef :
  163. case TokenType.TypeSpec :
  164. return GetMethodRefSig (index);
  165. case TokenType.ModuleRef :
  166. case TokenType.Method :
  167. return GetMethodDefSig (index);
  168. }
  169. return null;
  170. }
  171. /*
  172. public MarshalSig GetMarshalSig (uint index)
  173. {
  174. MarshalSig ms = m_signatures [index] as MarshalSig;
  175. if (ms == null) {
  176. byte [] data = m_root.Streams.BlobHeap.Read (index);
  177. ms = ReadMarshalSig (data);
  178. m_signatures [index] = ms;
  179. }
  180. return ms;
  181. }
  182. */
  183. public MethodSig GetStandAloneMethodSig (uint index)
  184. {
  185. int start;
  186. if ((m_blobData [index] & 0x5) > 0) {
  187. MethodRefSig mrs = new MethodRefSig (index);
  188. ReadMethodRefSig (mrs, m_blobData, (int)index, out start);
  189. return mrs;
  190. } else {
  191. MethodDefSig mds = new MethodDefSig (index);
  192. ReadMethodDefSig (mds, m_blobData, (int)index, out start);
  193. return mds;
  194. }
  195. }
  196. public override void VisitMethodDefSig (MethodDefSig methodDef)
  197. {
  198. int start;
  199. ReadMethodDefSig (methodDef, m_blobData, (int)methodDef.BlobIndex, out start);
  200. }
  201. public override void VisitMethodRefSig (MethodRefSig methodRef)
  202. {
  203. int start;
  204. ReadMethodRefSig (methodRef, m_blobData, (int)methodRef.BlobIndex, out start);
  205. }
  206. public override void VisitFieldSig (FieldSig field)
  207. {
  208. int start = 0;
  209. //Utilities.ReadCompressedInteger (m_blobData, (int) field.BlobIndex, out start);
  210. //field.CallingConvention = m_blobData [start];
  211. field.Field = (field.CallingConvention & 0x6) != 0;
  212. field.CustomMods = ReadCustomMods (m_blobData, start + 1, out start);
  213. field.Type = ReadType (m_blobData, start, out start);
  214. }
  215. public override void VisitPropertySig (PropertySig property)
  216. {
  217. int start;
  218. Utilities.ReadCompressedInteger (m_blobData, (int) property.BlobIndex, out start);
  219. property.CallingConvention = m_blobData [start];
  220. property.Property = (property.CallingConvention & 0x8) != 0;
  221. property.ParamCount = Utilities.ReadCompressedInteger (m_blobData, start + 1, out start);
  222. property.CustomMods = ReadCustomMods (m_blobData, start, out start);
  223. property.Type = ReadType (m_blobData, start, out start);
  224. property.Parameters = ReadParameters (property.ParamCount, m_blobData, start);
  225. }
  226. public override void VisitLocalVarSig (LocalVarSig localvar)
  227. {
  228. int start;
  229. Utilities.ReadCompressedInteger (m_blobData, (int) localvar.BlobIndex, out start);
  230. localvar.CallingConvention = m_blobData [start];
  231. localvar.Local = (localvar.CallingConvention & 0x7) != 0;
  232. localvar.Count = Utilities.ReadCompressedInteger (m_blobData, start + 1, out start);
  233. localvar.LocalVariables = ReadLocalVariables (localvar.Count, m_blobData, start);
  234. }
  235. void ReadMethodDefSig (MethodDefSig methodDef, byte [] data, int pos, out int start)
  236. {
  237. methodDef.CallingConvention = data [pos];
  238. start = pos + 1;
  239. methodDef.HasThis = (methodDef.CallingConvention & 0x20) != 0;
  240. methodDef.ExplicitThis = (methodDef.CallingConvention & 0x40) != 0;
  241. if ((methodDef.CallingConvention & 0x5) != 0)
  242. methodDef.MethCallConv |= MethodCallingConvention.VarArg;
  243. else if ((methodDef.CallingConvention & 0x10) != 0) {
  244. methodDef.MethCallConv |= MethodCallingConvention.Generic;
  245. methodDef.GenericParameterCount = Utilities.ReadCompressedInteger (data, start, out start);
  246. } else
  247. methodDef.MethCallConv |= MethodCallingConvention.Default;
  248. methodDef.ParamCount = Utilities.ReadCompressedInteger (data, start, out start);
  249. methodDef.RetType = ReadRetType (data, start, out start);
  250. int sentpos;
  251. methodDef.Parameters = ReadParameters (methodDef.ParamCount, data, start, out sentpos);
  252. methodDef.Sentinel = sentpos;
  253. }
  254. void ReadMethodRefSig (MethodRefSig methodRef, byte [] data, int pos, out int start)
  255. {
  256. methodRef.CallingConvention = data [pos];
  257. start = pos + 1;
  258. methodRef.HasThis = (methodRef.CallingConvention & 0x20) != 0;
  259. methodRef.ExplicitThis = (methodRef.CallingConvention & 0x40) != 0;
  260. if ((methodRef.CallingConvention & 0x1) != 0)
  261. methodRef.MethCallConv |= MethodCallingConvention.C;
  262. else if ((methodRef.CallingConvention & 0x2) != 0)
  263. methodRef.MethCallConv |= MethodCallingConvention.StdCall;
  264. else if ((methodRef.CallingConvention & 0x3) != 0)
  265. methodRef.MethCallConv |= MethodCallingConvention.ThisCall;
  266. else if ((methodRef.CallingConvention & 0x4) != 0)
  267. methodRef.MethCallConv |= MethodCallingConvention.FastCall;
  268. else if ((methodRef.CallingConvention & 0x5) != 0)
  269. methodRef.MethCallConv |= MethodCallingConvention.VarArg;
  270. else
  271. methodRef.MethCallConv |= MethodCallingConvention.Default;
  272. methodRef.ParamCount = Utilities.ReadCompressedInteger (data, start, out start);
  273. methodRef.RetType = ReadRetType (data, start, out start);
  274. int sentpos;
  275. methodRef.Parameters = ReadParameters (methodRef.ParamCount, data, start, out sentpos);
  276. methodRef.Sentinel = sentpos;
  277. }
  278. LocalVarSig.LocalVariable [] ReadLocalVariables (int length, byte [] data, int pos)
  279. {
  280. int start = pos;
  281. LocalVarSig.LocalVariable [] types = new LocalVarSig.LocalVariable [length];
  282. for (int i = 0; i < length; i++)
  283. types [i] = ReadLocalVariable (data, start, out start);
  284. return types;
  285. }
  286. public LocalVarSig.LocalVariable ReadLocalVariable (byte [] data, int pos, out int start)
  287. {
  288. start = pos;
  289. LocalVarSig.LocalVariable lv = new LocalVarSig.LocalVariable ();
  290. lv.ByRef = false;
  291. int cursor;
  292. while (true) {
  293. lv.CustomMods = ReadCustomMods (data, start, out start);
  294. cursor = start;
  295. int current = Utilities.ReadCompressedInteger (data, start, out start);
  296. if (current == (int) ElementType.Pinned) // the only possible constraint
  297. lv.Constraint |= Constraint.Pinned;
  298. else if (current == (int) ElementType.ByRef) {
  299. lv.ByRef = true;
  300. if (lv.CustomMods == null || lv.CustomMods.Length == 0)
  301. lv.CustomMods = ReadCustomMods (data, start, out start);
  302. } else {
  303. lv.Type = ReadType (data, cursor, out start);
  304. break;
  305. }
  306. }
  307. return lv;
  308. }
  309. TypeSpec ReadTypeSpec (byte [] data, int pos)
  310. {
  311. int start = pos;
  312. Utilities.ReadCompressedInteger (data, start, out start);
  313. TypeSpec ts = new TypeSpec ();
  314. ts.CustomMods = ReadCustomMods (data, start, out start);
  315. ts.Type = ReadType (data, start, out start);
  316. return ts;
  317. }
  318. MethodSpec ReadMethodSpec (byte [] data, int pos)
  319. {
  320. int start = pos;
  321. Utilities.ReadCompressedInteger (data, start, out start);
  322. if (Utilities.ReadCompressedInteger (data, start, out start) != 0x0a)
  323. throw new ReflectionException ("Invalid MethodSpec signature");
  324. return new MethodSpec (ReadGenericInstSignature (data, start, out start));
  325. }
  326. RetType ReadRetType (byte [] data, int pos, out int start)
  327. {
  328. RetType rt = new RetType ();
  329. start = pos;
  330. rt.CustomMods = ReadCustomMods (data, start, out start);
  331. int curs = start;
  332. ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
  333. switch (flag) {
  334. case ElementType.Void :
  335. rt.ByRef = rt.TypedByRef = false;
  336. rt.Void = true;
  337. break;
  338. case ElementType.TypedByRef :
  339. rt.ByRef = rt.Void = false;
  340. rt.TypedByRef = true;
  341. break;
  342. case ElementType.ByRef :
  343. rt.TypedByRef = rt.Void = false;
  344. rt.ByRef = true;
  345. if (rt.CustomMods == null || rt.CustomMods.Length == 0)
  346. rt.CustomMods = ReadCustomMods (data, start, out start);
  347. rt.Type = ReadType (data, start, out start);
  348. break;
  349. default :
  350. rt.TypedByRef = rt.Void = rt.ByRef = false;
  351. rt.Type = ReadType (data, curs, out start);
  352. break;
  353. }
  354. return rt;
  355. }
  356. Param [] ReadParameters (int length, byte [] data, int pos)
  357. {
  358. Param [] ret = new Param [length];
  359. int start = pos;
  360. for (int i = 0; i < length; i++)
  361. ret [i] = ReadParameter (data, start, out start);
  362. return ret;
  363. }
  364. Param [] ReadParameters (int length, byte [] data, int pos, out int sentinelpos)
  365. {
  366. Param [] ret = new Param [length];
  367. int start = pos;
  368. sentinelpos = -1;
  369. for (int i = 0; i < length; i++) {
  370. int curs = start;
  371. int flag = Utilities.ReadCompressedInteger (data, start, out start);
  372. if (flag == (int) ElementType.Sentinel) {
  373. sentinelpos = i;
  374. curs = start;
  375. }
  376. ret [i] = ReadParameter (data, curs, out start);
  377. }
  378. return ret;
  379. }
  380. Param ReadParameter (byte [] data, int pos, out int start)
  381. {
  382. Param p = new Param ();
  383. start = pos;
  384. p.CustomMods = ReadCustomMods (data, start, out start);
  385. int curs = start;
  386. ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
  387. switch (flag) {
  388. case ElementType.TypedByRef :
  389. p.TypedByRef = true;
  390. p.ByRef = false;
  391. break;
  392. case ElementType.ByRef :
  393. p.TypedByRef = false;
  394. p.ByRef = true;
  395. if (p.CustomMods == null || p.CustomMods.Length == 0)
  396. p.CustomMods = ReadCustomMods (data, start, out start);
  397. p.Type = ReadType (data, start, out start);
  398. break;
  399. default :
  400. p.TypedByRef = false;
  401. p.ByRef = false;
  402. p.Type = ReadType (data, curs, out start);
  403. break;
  404. }
  405. return p;
  406. }
  407. public SigType ReadType (byte [] data, int pos, out int start)
  408. {
  409. start = pos;
  410. ElementType element = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
  411. switch (element) {
  412. case ElementType.ValueType :
  413. VALUETYPE vt = new VALUETYPE ();
  414. vt.Type = Utilities.GetMetadataToken(CodedIndex.TypeDefOrRef,
  415. (uint) Utilities.ReadCompressedInteger (data, start, out start));
  416. return vt;
  417. case ElementType.Class :
  418. CLASS c = new CLASS ();
  419. c.Type = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
  420. (uint) Utilities.ReadCompressedInteger (data, start, out start));
  421. return c;
  422. case ElementType.Ptr :
  423. PTR p = new PTR ();
  424. int buf = start;
  425. int flag = Utilities.ReadCompressedInteger (data, start, out start);
  426. p.Void = flag == (int) ElementType.Void;
  427. if (p.Void)
  428. return p;
  429. start = buf;
  430. p.CustomMods = ReadCustomMods (data, start, out start);
  431. p.PtrType = ReadType (data, start, out start);
  432. return p;
  433. case ElementType.FnPtr :
  434. FNPTR fp = new FNPTR ();
  435. if ((data [start] & 0x5) != 0) {
  436. MethodRefSig mr = new MethodRefSig ((uint) start);
  437. ReadMethodRefSig (mr, data, start, out start);
  438. fp.Method = mr;
  439. } else {
  440. MethodDefSig md = new MethodDefSig ((uint) start);
  441. ReadMethodDefSig (md, data, start, out start);
  442. fp.Method = md;
  443. }
  444. return fp;
  445. case ElementType.Array :
  446. ARRAY ary = new ARRAY ();
  447. ary.CustomMods = ReadCustomMods (data, start, out start);
  448. ArrayShape shape = new ArrayShape ();
  449. ary.Type = ReadType (data, start, out start);
  450. shape.Rank = Utilities.ReadCompressedInteger (data, start, out start);
  451. shape.NumSizes = Utilities.ReadCompressedInteger (data, start, out start);
  452. shape.Sizes = new int [shape.NumSizes];
  453. for (int i = 0; i < shape.NumSizes; i++)
  454. shape.Sizes [i] = Utilities.ReadCompressedInteger (data, start, out start);
  455. shape.NumLoBounds = Utilities.ReadCompressedInteger (data, start, out start);
  456. shape.LoBounds = new int [shape.NumLoBounds];
  457. for (int i = 0; i < shape.NumLoBounds; i++)
  458. shape.LoBounds [i] = Utilities.ReadCompressedInteger (data, start, out start);
  459. ary.Shape = shape;
  460. return ary;
  461. case ElementType.SzArray :
  462. SZARRAY sa = new SZARRAY ();
  463. sa.CustomMods = ReadCustomMods (data, start, out start);
  464. sa.Type = ReadType (data, start, out start);
  465. return sa;
  466. case ElementType.Var:
  467. return new VAR (Utilities.ReadCompressedInteger (data, start, out start));
  468. case ElementType.MVar:
  469. return new MVAR (Utilities.ReadCompressedInteger (data, start, out start));
  470. case ElementType.GenericInst:
  471. GENERICINST ginst = new GENERICINST ();
  472. ginst.ValueType = ((ElementType) Utilities.ReadCompressedInteger (
  473. data, start, out start)) == ElementType.ValueType;
  474. ginst.Type = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
  475. (uint) Utilities.ReadCompressedInteger (data, start, out start));
  476. ginst.Signature = ReadGenericInstSignature (data, start, out start);
  477. return ginst;
  478. default :
  479. return new SigType (element);
  480. }
  481. }
  482. GenericInstSignature ReadGenericInstSignature (byte [] data, int pos, out int start)
  483. {
  484. start = pos;
  485. GenericInstSignature gis = new GenericInstSignature ();
  486. gis.Arity = Utilities.ReadCompressedInteger (data, start, out start);
  487. gis.Types = new GenericArg [gis.Arity];
  488. for (int i = 0; i < gis.Arity; i++)
  489. gis.Types [i] = ReadGenericArg (data, start, out start);
  490. return gis;
  491. }
  492. GenericArg ReadGenericArg (byte[] data, int pos, out int start)
  493. {
  494. start = pos;
  495. CustomMod [] mods = ReadCustomMods (data, start, out start);
  496. GenericArg arg = new GenericArg (ReadType (data, start, out start));
  497. arg.CustomMods = mods;
  498. return arg;
  499. }
  500. CustomMod [] ReadCustomMods (byte [] data, int pos, out int start)
  501. {
  502. ArrayList cmods = new ArrayList ();
  503. start = pos;
  504. while (true) {
  505. int buf = start;
  506. ElementType flag = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
  507. start = buf;
  508. if (!((flag == ElementType.CModOpt) || (flag == ElementType.CModReqD)))
  509. break;
  510. cmods.Add (ReadCustomMod (data, start, out start));
  511. }
  512. return cmods.ToArray (typeof (CustomMod)) as CustomMod [];
  513. }
  514. CustomMod ReadCustomMod (byte [] data, int pos, out int start)
  515. {
  516. CustomMod cm = new CustomMod ();
  517. start = pos;
  518. ElementType cmod = (ElementType) Utilities.ReadCompressedInteger (data, start, out start);
  519. if (cmod == ElementType.CModOpt)
  520. cm.CMOD = CustomMod.CMODType.OPT;
  521. else if (cmod == ElementType.CModReqD)
  522. cm.CMOD = CustomMod.CMODType.REQD;
  523. else
  524. cm.CMOD = CustomMod.CMODType.None;
  525. cm.TypeDefOrRef = Utilities.GetMetadataToken (CodedIndex.TypeDefOrRef,
  526. (uint) Utilities.ReadCompressedInteger (data, start, out start));
  527. return cm;
  528. }
  529. /*
  530. CustomAttrib ReadCustomAttrib (int pos, MethodReference ctor, bool resolve)
  531. {
  532. int start, length = Utilities.ReadCompressedInteger (m_blobData, pos, out start);
  533. byte [] data = new byte [length];
  534. Buffer.BlockCopy (m_blobData, start, data, 0, length);
  535. try {
  536. return ReadCustomAttrib (new BinaryReader (
  537. new MemoryStream (data)), data, ctor, resolve);
  538. } catch {
  539. CustomAttrib ca = new CustomAttrib (ctor);
  540. ca.Read = false;
  541. return ca;
  542. }
  543. }
  544. CustomAttrib ReadCustomAttrib (BinaryReader br, byte [] data, MethodReference ctor, bool resolve)
  545. {
  546. CustomAttrib ca = new CustomAttrib (ctor);
  547. if (data.Length == 0) {
  548. ca.FixedArgs = new CustomAttrib.FixedArg [0];
  549. ca.NamedArgs = new CustomAttrib.NamedArg [0];
  550. return ca;
  551. }
  552. bool read = true;
  553. ca.Prolog = br.ReadUInt16 ();
  554. if (ca.Prolog != CustomAttrib.StdProlog)
  555. throw new MetadataFormatException ("Non standard prolog for custom attribute");
  556. ca.FixedArgs = new CustomAttrib.FixedArg [ctor.Parameters.Count];
  557. for (int i = 0; i < ca.FixedArgs.Length && read; i++)
  558. ca.FixedArgs [i] = ReadFixedArg (data, br,
  559. ctor.Parameters [i].ParameterType, ref read, resolve);
  560. if (br.BaseStream.Position == br.BaseStream.Length)
  561. read = false;
  562. if (!read) {
  563. ca.Read = read;
  564. return ca;
  565. }
  566. ca.NumNamed = br.ReadUInt16 ();
  567. ca.NamedArgs = new CustomAttrib.NamedArg [ca.NumNamed];
  568. for (int i = 0; i < ca.NumNamed && read; i++)
  569. ca.NamedArgs [i] = ReadNamedArg (data, br, ref read, resolve);
  570. ca.Read = read;
  571. return ca;
  572. }
  573. CustomAttrib.FixedArg ReadFixedArg (byte [] data, BinaryReader br,
  574. TypeReference param, ref bool read, bool resolve)
  575. {
  576. CustomAttrib.FixedArg fa = new CustomAttrib.FixedArg ();
  577. if (param is ArrayType) {
  578. param = ((ArrayType) param).ElementType;
  579. fa.SzArray = true;
  580. fa.NumElem = br.ReadUInt32 ();
  581. if (fa.NumElem == 0 || fa.NumElem == 0xffffffff) {
  582. fa.Elems = new CustomAttrib.Elem [0];
  583. fa.NumElem = 0;
  584. return fa;
  585. }
  586. fa.Elems = new CustomAttrib.Elem [fa.NumElem];
  587. for (int i = 0; i < fa.NumElem; i++)
  588. fa.Elems [i] = ReadElem (data, br, param, ref read, resolve);
  589. } else
  590. fa.Elems = new CustomAttrib.Elem [] { ReadElem (data, br, param, ref read, resolve) };
  591. return fa;
  592. }
  593. TypeReference CreateEnumTypeReference (string enumName)
  594. {
  595. string asmName = null;
  596. int asmStart = enumName.IndexOf (',');
  597. if (asmStart != -1) {
  598. asmName = enumName.Substring (asmStart + 1);
  599. enumName = enumName.Substring (0, asmStart);
  600. }
  601. // Inner class style is reflection style.
  602. enumName = enumName.Replace ('+', '/');
  603. AssemblyNameReference asm;
  604. if (asmName == null) {
  605. // If no assembly is given then the ECMA standard says the
  606. // assembly is either the current one or mscorlib.
  607. if (m_reflectReader.Module.Types.Contains (enumName))
  608. return m_reflectReader.Module.Types [enumName];
  609. asm = m_reflectReader.Corlib;
  610. } else
  611. asm = AssemblyNameReference.Parse (asmName);
  612. string [] outers = enumName.Split ('/');
  613. string outerfullname = outers [0];
  614. string ns = null;
  615. int nsIndex = outerfullname.LastIndexOf ('.');
  616. if (nsIndex != -1)
  617. ns = outerfullname.Substring (0, nsIndex);
  618. string name = outerfullname.Substring (nsIndex + 1);
  619. TypeReference decType = new TypeReference (name, ns, asm);
  620. for (int i = 1; i < outers.Length; i++) {
  621. TypeReference t = new TypeReference (outers [i], null, asm);
  622. t.DeclaringType = decType;
  623. decType = t;
  624. }
  625. decType.IsValueType = true;
  626. return decType;
  627. }
  628. TypeReference ReadTypeReference (byte [] data, BinaryReader br, out ElementType elemType)
  629. {
  630. bool array = false;
  631. elemType = (ElementType) br.ReadByte ();
  632. if (elemType == ElementType.SzArray) {
  633. elemType = (ElementType) br.ReadByte ();
  634. array = true;
  635. }
  636. TypeReference res;
  637. if (elemType == ElementType.Enum)
  638. res = CreateEnumTypeReference (ReadUTF8String (data, br));
  639. else
  640. res = TypeReferenceFromElemType (elemType);
  641. if (array)
  642. res = new ArrayType (res);
  643. return res;
  644. }
  645. TypeReference TypeReferenceFromElemType (ElementType elemType)
  646. {
  647. switch (elemType) {
  648. case ElementType.Boxed :
  649. return m_reflectReader.SearchCoreType (Constants.Object);
  650. case ElementType.String :
  651. return m_reflectReader.SearchCoreType (Constants.String);
  652. case ElementType.Type :
  653. return m_reflectReader.SearchCoreType (Constants.Type);
  654. case ElementType.Boolean :
  655. return m_reflectReader.SearchCoreType (Constants.Boolean);
  656. case ElementType.Char :
  657. return m_reflectReader.SearchCoreType (Constants.Char);
  658. case ElementType.R4 :
  659. return m_reflectReader.SearchCoreType (Constants.Single);
  660. case ElementType.R8 :
  661. return m_reflectReader.SearchCoreType (Constants.Double);
  662. case ElementType.I1 :
  663. return m_reflectReader.SearchCoreType (Constants.SByte);
  664. case ElementType.I2 :
  665. return m_reflectReader.SearchCoreType (Constants.Int16);
  666. case ElementType.I4 :
  667. return m_reflectReader.SearchCoreType (Constants.Int32);
  668. case ElementType.I8 :
  669. return m_reflectReader.SearchCoreType (Constants.Int64);
  670. case ElementType.U1 :
  671. return m_reflectReader.SearchCoreType (Constants.Byte);
  672. case ElementType.U2 :
  673. return m_reflectReader.SearchCoreType (Constants.UInt16);
  674. case ElementType.U4 :
  675. return m_reflectReader.SearchCoreType (Constants.UInt32);
  676. case ElementType.U8 :
  677. return m_reflectReader.SearchCoreType (Constants.UInt64);
  678. default :
  679. throw new MetadataFormatException ("Non valid type in CustomAttrib.Elem: 0x{0}",
  680. ((byte) elemType).ToString("x2"));
  681. }
  682. }
  683. internal CustomAttrib.NamedArg ReadNamedArg (byte [] data, BinaryReader br, ref bool read, bool resolve)
  684. {
  685. CustomAttrib.NamedArg na = new CustomAttrib.NamedArg ();
  686. byte kind = br.ReadByte ();
  687. if (kind == 0x53) { // field
  688. na.Field = true;
  689. na.Property = false;
  690. } else if (kind == 0x54) { // property
  691. na.Field = false;
  692. na.Property = true;
  693. } else
  694. throw new MetadataFormatException ("Wrong kind of namedarg found: 0x" + kind.ToString("x2"));
  695. TypeReference elemType = ReadTypeReference (data, br, out na.FieldOrPropType);
  696. na.FieldOrPropName = ReadUTF8String (data, br);
  697. na.FixedArg = ReadFixedArg (data, br, elemType, ref read, resolve);
  698. return na;
  699. }
  700. CustomAttrib.Elem ReadElem (byte [] data, BinaryReader br, TypeReference elemType, ref bool read, bool resolve)
  701. {
  702. CustomAttrib.Elem elem = new CustomAttrib.Elem ();
  703. string elemName = elemType.FullName;
  704. if (elemName == Constants.Object) {
  705. elemType = ReadTypeReference (data, br, out elem.FieldOrPropType);
  706. if (elemType is ArrayType) {
  707. read = false; // Don't know how to represent arrays as an object value.
  708. return elem;
  709. } else if (elemType.FullName == Constants.Object)
  710. throw new MetadataFormatException ("Non valid type in CustomAttrib.Elem after boxed prefix: 0x{0}",
  711. ((byte) elem.FieldOrPropType).ToString("x2"));
  712. elem = ReadElem (data, br, elemType, ref read, resolve);
  713. elem.String = elem.Simple = elem.Type = false;
  714. elem.BoxedValueType = true;
  715. return elem;
  716. }
  717. elem.ElemType = elemType;
  718. if (elemName == Constants.Type || elemName == Constants.String) {
  719. switch (elemType.FullName) {
  720. case Constants.String:
  721. elem.String = true;
  722. elem.BoxedValueType = elem.Simple = elem.Type = false;
  723. break;
  724. case Constants.Type:
  725. elem.Type = true;
  726. elem.BoxedValueType = elem.Simple = elem.String = false;
  727. break;
  728. }
  729. if (data [br.BaseStream.Position] == 0xff) { // null
  730. elem.Value = null;
  731. br.BaseStream.Position++;
  732. } else {
  733. elem.Value = ReadUTF8String (data, br);
  734. }
  735. return elem;
  736. }
  737. elem.String = elem.Type = elem.BoxedValueType = false;
  738. if (!ReadSimpleValue (br, ref elem, elem.ElemType)) {
  739. if (!resolve) { // until enums writing is implemented
  740. read = false;
  741. return elem;
  742. }
  743. TypeReference typeRef = GetEnumUnderlyingType (elem.ElemType, resolve);
  744. if (typeRef == null || !ReadSimpleValue (br, ref elem, typeRef))
  745. read = false;
  746. }
  747. return elem;
  748. }
  749. TypeReference GetEnumUnderlyingType (TypeReference enumType, bool resolve)
  750. {
  751. TypeDefinition type = enumType as TypeDefinition;
  752. if (type == null && resolve && AssemblyResolver != null) {
  753. if (enumType.Scope is ModuleDefinition)
  754. throw new NotSupportedException ();
  755. AssemblyDefinition asm = AssemblyResolver.Resolve (
  756. ((AssemblyNameReference) enumType.Scope).FullName);
  757. type = asm.MainModule.Types [enumType.FullName];
  758. }
  759. if (type != null && type.IsEnum)
  760. return type.Fields.GetField ("value__").FieldType;
  761. return null;
  762. }
  763. bool ReadSimpleValue (BinaryReader br, ref CustomAttrib.Elem elem, TypeReference type)
  764. {
  765. switch (type.FullName) {
  766. case Constants.Boolean :
  767. elem.Value = br.ReadByte () == 1;
  768. break;
  769. case Constants.Char :
  770. elem.Value = (char) br.ReadUInt16 ();
  771. break;
  772. case Constants.Single :
  773. elem.Value = br.ReadSingle ();
  774. break;
  775. case Constants.Double :
  776. elem.Value = br.ReadDouble ();
  777. break;
  778. case Constants.Byte :
  779. elem.Value = br.ReadByte ();
  780. break;
  781. case Constants.Int16 :
  782. elem.Value = br.ReadInt16 ();
  783. break;
  784. case Constants.Int32 :
  785. elem.Value = br.ReadInt32 ();
  786. break;
  787. case Constants.Int64 :
  788. elem.Value = br.ReadInt64 ();
  789. break;
  790. case Constants.SByte :
  791. elem.Value = br.ReadSByte ();
  792. break;
  793. case Constants.UInt16 :
  794. elem.Value = br.ReadUInt16 ();
  795. break;
  796. case Constants.UInt32 :
  797. elem.Value = br.ReadUInt32 ();
  798. break;
  799. case Constants.UInt64 :
  800. elem.Value = br.ReadUInt64 ();
  801. break;
  802. default : // enum
  803. return false;
  804. }
  805. elem.Simple = true;
  806. return true;
  807. }
  808. MarshalSig ReadMarshalSig (byte [] data)
  809. {
  810. int start;
  811. MarshalSig ms = new MarshalSig ((NativeType) Utilities.ReadCompressedInteger (data, 0, out start));
  812. switch (ms.NativeInstrinsic) {
  813. case NativeType.ARRAY:
  814. MarshalSig.Array ar = new MarshalSig.Array ();
  815. ar.ArrayElemType = (NativeType) Utilities.ReadCompressedInteger (data, start, out start);
  816. if (start < data.Length)
  817. ar.ParamNum = Utilities.ReadCompressedInteger (data, start, out start);
  818. if (start < data.Length)
  819. ar.NumElem = Utilities.ReadCompressedInteger (data, start, out start);
  820. if (start < data.Length)
  821. ar.ElemMult = Utilities.ReadCompressedInteger (data, start, out start);
  822. ms.Spec = ar;
  823. break;
  824. case NativeType.CUSTOMMARSHALER:
  825. MarshalSig.CustomMarshaler cm = new MarshalSig.CustomMarshaler ();
  826. cm.Guid = ReadUTF8String (data, start, out start);
  827. cm.UnmanagedType = ReadUTF8String (data, start, out start);
  828. cm.ManagedType = ReadUTF8String (data, start, out start);
  829. cm.Cookie = ReadUTF8String (data, start, out start);
  830. ms.Spec = cm;
  831. break;
  832. case NativeType.FIXEDARRAY:
  833. MarshalSig.FixedArray fa = new MarshalSig.FixedArray ();
  834. fa.NumElem = Utilities.ReadCompressedInteger (data, start, out start);
  835. if (start < data.Length)
  836. fa.ArrayElemType = (NativeType) Utilities.ReadCompressedInteger (data, start, out start);
  837. ms.Spec = fa;
  838. break;
  839. case NativeType.SAFEARRAY:
  840. MarshalSig.SafeArray sa = new MarshalSig.SafeArray ();
  841. if (start < data.Length)
  842. sa.ArrayElemType = (VariantType) Utilities.ReadCompressedInteger (data, start, out start);
  843. ms.Spec = sa;
  844. break;
  845. case NativeType.FIXEDSYSSTRING:
  846. MarshalSig.FixedSysString fss = new MarshalSig.FixedSysString ();
  847. if (start < data.Length)
  848. fss.Size = Utilities.ReadCompressedInteger (data, start, out start);
  849. ms.Spec = fss;
  850. break;
  851. }
  852. return ms;
  853. }
  854. static internal string ReadUTF8String (byte [] data, BinaryReader br)
  855. {
  856. int start = (int)br.BaseStream.Position;
  857. string val = ReadUTF8String (data, start, out start);
  858. br.BaseStream.Position = start;
  859. return val;
  860. }
  861. static internal string ReadUTF8String (byte [] data, int pos, out int start)
  862. {
  863. int length = Utilities.ReadCompressedInteger (data, pos, out start);
  864. pos = start;
  865. start += length;
  866. // COMPACT FRAMEWORK NOTE: Encoding.GetString (byte[]) is not supported.
  867. return Encoding.UTF8.GetString (data, pos, length);
  868. }
  869. */
  870. }
  871. }