/Mono.Cecil.Metadata/Utilities.cs

http://github.com/jbevain/cecil · C# · 650 lines · 628 code · 13 blank · 9 comment · 40 complexity · fe42e400a6fca96be9ee2674b5f4c5fa MD5 · raw file

  1. //
  2. // Author:
  3. // Jb Evain (jbevain@gmail.com)
  4. //
  5. // Copyright (c) 2008 - 2015 Jb Evain
  6. // Copyright (c) 2008 - 2011 Novell, Inc.
  7. //
  8. // Licensed under the MIT/X11 license.
  9. //
  10. using System;
  11. using Mono.Cecil.Metadata;
  12. namespace Mono.Cecil {
  13. static partial class Mixin {
  14. public const int TableCount = 58;
  15. public const int CodedIndexCount = 14;
  16. public static uint ReadCompressedUInt32 (this byte [] data, ref int position)
  17. {
  18. uint integer;
  19. if ((data [position] & 0x80) == 0) {
  20. integer = data [position];
  21. position++;
  22. } else if ((data [position] & 0x40) == 0) {
  23. integer = (uint) (data [position] & ~0x80) << 8;
  24. integer |= data [position + 1];
  25. position += 2;
  26. } else {
  27. integer = (uint) (data [position] & ~0xc0) << 24;
  28. integer |= (uint) data [position + 1] << 16;
  29. integer |= (uint) data [position + 2] << 8;
  30. integer |= (uint) data [position + 3];
  31. position += 4;
  32. }
  33. return integer;
  34. }
  35. public static MetadataToken GetMetadataToken (this CodedIndex self, uint data)
  36. {
  37. uint rid;
  38. TokenType token_type;
  39. switch (self) {
  40. case CodedIndex.TypeDefOrRef:
  41. rid = data >> 2;
  42. switch (data & 3) {
  43. case 0:
  44. token_type = TokenType.TypeDef; goto ret;
  45. case 1:
  46. token_type = TokenType.TypeRef; goto ret;
  47. case 2:
  48. token_type = TokenType.TypeSpec; goto ret;
  49. default:
  50. goto exit;
  51. }
  52. case CodedIndex.HasConstant:
  53. rid = data >> 2;
  54. switch (data & 3) {
  55. case 0:
  56. token_type = TokenType.Field; goto ret;
  57. case 1:
  58. token_type = TokenType.Param; goto ret;
  59. case 2:
  60. token_type = TokenType.Property; goto ret;
  61. default:
  62. goto exit;
  63. }
  64. case CodedIndex.HasCustomAttribute:
  65. rid = data >> 5;
  66. switch (data & 31) {
  67. case 0:
  68. token_type = TokenType.Method; goto ret;
  69. case 1:
  70. token_type = TokenType.Field; goto ret;
  71. case 2:
  72. token_type = TokenType.TypeRef; goto ret;
  73. case 3:
  74. token_type = TokenType.TypeDef; goto ret;
  75. case 4:
  76. token_type = TokenType.Param; goto ret;
  77. case 5:
  78. token_type = TokenType.InterfaceImpl; goto ret;
  79. case 6:
  80. token_type = TokenType.MemberRef; goto ret;
  81. case 7:
  82. token_type = TokenType.Module; goto ret;
  83. case 8:
  84. token_type = TokenType.Permission; goto ret;
  85. case 9:
  86. token_type = TokenType.Property; goto ret;
  87. case 10:
  88. token_type = TokenType.Event; goto ret;
  89. case 11:
  90. token_type = TokenType.Signature; goto ret;
  91. case 12:
  92. token_type = TokenType.ModuleRef; goto ret;
  93. case 13:
  94. token_type = TokenType.TypeSpec; goto ret;
  95. case 14:
  96. token_type = TokenType.Assembly; goto ret;
  97. case 15:
  98. token_type = TokenType.AssemblyRef; goto ret;
  99. case 16:
  100. token_type = TokenType.File; goto ret;
  101. case 17:
  102. token_type = TokenType.ExportedType; goto ret;
  103. case 18:
  104. token_type = TokenType.ManifestResource; goto ret;
  105. case 19:
  106. token_type = TokenType.GenericParam; goto ret;
  107. case 20:
  108. token_type = TokenType.GenericParamConstraint; goto ret;
  109. case 21:
  110. token_type = TokenType.MethodSpec; goto ret;
  111. default:
  112. goto exit;
  113. }
  114. case CodedIndex.HasFieldMarshal:
  115. rid = data >> 1;
  116. switch (data & 1) {
  117. case 0:
  118. token_type = TokenType.Field; goto ret;
  119. case 1:
  120. token_type = TokenType.Param; goto ret;
  121. default:
  122. goto exit;
  123. }
  124. case CodedIndex.HasDeclSecurity:
  125. rid = data >> 2;
  126. switch (data & 3) {
  127. case 0:
  128. token_type = TokenType.TypeDef; goto ret;
  129. case 1:
  130. token_type = TokenType.Method; goto ret;
  131. case 2:
  132. token_type = TokenType.Assembly; goto ret;
  133. default:
  134. goto exit;
  135. }
  136. case CodedIndex.MemberRefParent:
  137. rid = data >> 3;
  138. switch (data & 7) {
  139. case 0:
  140. token_type = TokenType.TypeDef; goto ret;
  141. case 1:
  142. token_type = TokenType.TypeRef; goto ret;
  143. case 2:
  144. token_type = TokenType.ModuleRef; goto ret;
  145. case 3:
  146. token_type = TokenType.Method; goto ret;
  147. case 4:
  148. token_type = TokenType.TypeSpec; goto ret;
  149. default:
  150. goto exit;
  151. }
  152. case CodedIndex.HasSemantics:
  153. rid = data >> 1;
  154. switch (data & 1) {
  155. case 0:
  156. token_type = TokenType.Event; goto ret;
  157. case 1:
  158. token_type = TokenType.Property; goto ret;
  159. default:
  160. goto exit;
  161. }
  162. case CodedIndex.MethodDefOrRef:
  163. rid = data >> 1;
  164. switch (data & 1) {
  165. case 0:
  166. token_type = TokenType.Method; goto ret;
  167. case 1:
  168. token_type = TokenType.MemberRef; goto ret;
  169. default:
  170. goto exit;
  171. }
  172. case CodedIndex.MemberForwarded:
  173. rid = data >> 1;
  174. switch (data & 1) {
  175. case 0:
  176. token_type = TokenType.Field; goto ret;
  177. case 1:
  178. token_type = TokenType.Method; goto ret;
  179. default:
  180. goto exit;
  181. }
  182. case CodedIndex.Implementation:
  183. rid = data >> 2;
  184. switch (data & 3) {
  185. case 0:
  186. token_type = TokenType.File; goto ret;
  187. case 1:
  188. token_type = TokenType.AssemblyRef; goto ret;
  189. case 2:
  190. token_type = TokenType.ExportedType; goto ret;
  191. default:
  192. goto exit;
  193. }
  194. case CodedIndex.CustomAttributeType:
  195. rid = data >> 3;
  196. switch (data & 7) {
  197. case 2:
  198. token_type = TokenType.Method; goto ret;
  199. case 3:
  200. token_type = TokenType.MemberRef; goto ret;
  201. default:
  202. goto exit;
  203. }
  204. case CodedIndex.ResolutionScope:
  205. rid = data >> 2;
  206. switch (data & 3) {
  207. case 0:
  208. token_type = TokenType.Module; goto ret;
  209. case 1:
  210. token_type = TokenType.ModuleRef; goto ret;
  211. case 2:
  212. token_type = TokenType.AssemblyRef; goto ret;
  213. case 3:
  214. token_type = TokenType.TypeRef; goto ret;
  215. default:
  216. goto exit;
  217. }
  218. case CodedIndex.TypeOrMethodDef:
  219. rid = data >> 1;
  220. switch (data & 1) {
  221. case 0:
  222. token_type = TokenType.TypeDef; goto ret;
  223. case 1:
  224. token_type = TokenType.Method; goto ret;
  225. default: goto exit;
  226. }
  227. case CodedIndex.HasCustomDebugInformation:
  228. rid = data >> 5;
  229. switch (data & 31) {
  230. case 0:
  231. token_type = TokenType.Method; goto ret;
  232. case 1:
  233. token_type = TokenType.Field; goto ret;
  234. case 2:
  235. token_type = TokenType.TypeRef; goto ret;
  236. case 3:
  237. token_type = TokenType.TypeDef; goto ret;
  238. case 4:
  239. token_type = TokenType.Param; goto ret;
  240. case 5:
  241. token_type = TokenType.InterfaceImpl; goto ret;
  242. case 6:
  243. token_type = TokenType.MemberRef; goto ret;
  244. case 7:
  245. token_type = TokenType.Module; goto ret;
  246. case 8:
  247. token_type = TokenType.Permission; goto ret;
  248. case 9:
  249. token_type = TokenType.Property; goto ret;
  250. case 10:
  251. token_type = TokenType.Event; goto ret;
  252. case 11:
  253. token_type = TokenType.Signature; goto ret;
  254. case 12:
  255. token_type = TokenType.ModuleRef; goto ret;
  256. case 13:
  257. token_type = TokenType.TypeSpec; goto ret;
  258. case 14:
  259. token_type = TokenType.Assembly; goto ret;
  260. case 15:
  261. token_type = TokenType.AssemblyRef; goto ret;
  262. case 16:
  263. token_type = TokenType.File; goto ret;
  264. case 17:
  265. token_type = TokenType.ExportedType; goto ret;
  266. case 18:
  267. token_type = TokenType.ManifestResource; goto ret;
  268. case 19:
  269. token_type = TokenType.GenericParam; goto ret;
  270. case 20:
  271. token_type = TokenType.GenericParamConstraint; goto ret;
  272. case 21:
  273. token_type = TokenType.MethodSpec; goto ret;
  274. case 22:
  275. token_type = TokenType.Document; goto ret;
  276. case 23:
  277. token_type = TokenType.LocalScope; goto ret;
  278. case 24:
  279. token_type = TokenType.LocalVariable; goto ret;
  280. case 25:
  281. token_type = TokenType.LocalConstant; goto ret;
  282. case 26:
  283. token_type = TokenType.ImportScope; goto ret;
  284. default:
  285. goto exit;
  286. }
  287. default:
  288. goto exit;
  289. }
  290. ret:
  291. return new MetadataToken (token_type, rid);
  292. exit:
  293. return MetadataToken.Zero;
  294. }
  295. public static uint CompressMetadataToken (this CodedIndex self, MetadataToken token)
  296. {
  297. uint ret = 0;
  298. if (token.RID == 0)
  299. return ret;
  300. switch (self) {
  301. case CodedIndex.TypeDefOrRef:
  302. ret = token.RID << 2;
  303. switch (token.TokenType) {
  304. case TokenType.TypeDef:
  305. return ret | 0;
  306. case TokenType.TypeRef:
  307. return ret | 1;
  308. case TokenType.TypeSpec:
  309. return ret | 2;
  310. default:
  311. goto exit;
  312. }
  313. case CodedIndex.HasConstant:
  314. ret = token.RID << 2;
  315. switch (token.TokenType) {
  316. case TokenType.Field:
  317. return ret | 0;
  318. case TokenType.Param:
  319. return ret | 1;
  320. case TokenType.Property:
  321. return ret | 2;
  322. default:
  323. goto exit;
  324. }
  325. case CodedIndex.HasCustomAttribute:
  326. ret = token.RID << 5;
  327. switch (token.TokenType) {
  328. case TokenType.Method:
  329. return ret | 0;
  330. case TokenType.Field:
  331. return ret | 1;
  332. case TokenType.TypeRef:
  333. return ret | 2;
  334. case TokenType.TypeDef:
  335. return ret | 3;
  336. case TokenType.Param:
  337. return ret | 4;
  338. case TokenType.InterfaceImpl:
  339. return ret | 5;
  340. case TokenType.MemberRef:
  341. return ret | 6;
  342. case TokenType.Module:
  343. return ret | 7;
  344. case TokenType.Permission:
  345. return ret | 8;
  346. case TokenType.Property:
  347. return ret | 9;
  348. case TokenType.Event:
  349. return ret | 10;
  350. case TokenType.Signature:
  351. return ret | 11;
  352. case TokenType.ModuleRef:
  353. return ret | 12;
  354. case TokenType.TypeSpec:
  355. return ret | 13;
  356. case TokenType.Assembly:
  357. return ret | 14;
  358. case TokenType.AssemblyRef:
  359. return ret | 15;
  360. case TokenType.File:
  361. return ret | 16;
  362. case TokenType.ExportedType:
  363. return ret | 17;
  364. case TokenType.ManifestResource:
  365. return ret | 18;
  366. case TokenType.GenericParam:
  367. return ret | 19;
  368. case TokenType.GenericParamConstraint:
  369. return ret | 20;
  370. case TokenType.MethodSpec:
  371. return ret | 21;
  372. default:
  373. goto exit;
  374. }
  375. case CodedIndex.HasFieldMarshal:
  376. ret = token.RID << 1;
  377. switch (token.TokenType) {
  378. case TokenType.Field:
  379. return ret | 0;
  380. case TokenType.Param:
  381. return ret | 1;
  382. default:
  383. goto exit;
  384. }
  385. case CodedIndex.HasDeclSecurity:
  386. ret = token.RID << 2;
  387. switch (token.TokenType) {
  388. case TokenType.TypeDef:
  389. return ret | 0;
  390. case TokenType.Method:
  391. return ret | 1;
  392. case TokenType.Assembly:
  393. return ret | 2;
  394. default:
  395. goto exit;
  396. }
  397. case CodedIndex.MemberRefParent:
  398. ret = token.RID << 3;
  399. switch (token.TokenType) {
  400. case TokenType.TypeDef:
  401. return ret | 0;
  402. case TokenType.TypeRef:
  403. return ret | 1;
  404. case TokenType.ModuleRef:
  405. return ret | 2;
  406. case TokenType.Method:
  407. return ret | 3;
  408. case TokenType.TypeSpec:
  409. return ret | 4;
  410. default:
  411. goto exit;
  412. }
  413. case CodedIndex.HasSemantics:
  414. ret = token.RID << 1;
  415. switch (token.TokenType) {
  416. case TokenType.Event:
  417. return ret | 0;
  418. case TokenType.Property:
  419. return ret | 1;
  420. default:
  421. goto exit;
  422. }
  423. case CodedIndex.MethodDefOrRef:
  424. ret = token.RID << 1;
  425. switch (token.TokenType) {
  426. case TokenType.Method:
  427. return ret | 0;
  428. case TokenType.MemberRef:
  429. return ret | 1;
  430. default:
  431. goto exit;
  432. }
  433. case CodedIndex.MemberForwarded:
  434. ret = token.RID << 1;
  435. switch (token.TokenType) {
  436. case TokenType.Field:
  437. return ret | 0;
  438. case TokenType.Method:
  439. return ret | 1;
  440. default:
  441. goto exit;
  442. }
  443. case CodedIndex.Implementation:
  444. ret = token.RID << 2;
  445. switch (token.TokenType) {
  446. case TokenType.File:
  447. return ret | 0;
  448. case TokenType.AssemblyRef:
  449. return ret | 1;
  450. case TokenType.ExportedType:
  451. return ret | 2;
  452. default:
  453. goto exit;
  454. }
  455. case CodedIndex.CustomAttributeType:
  456. ret = token.RID << 3;
  457. switch (token.TokenType) {
  458. case TokenType.Method:
  459. return ret | 2;
  460. case TokenType.MemberRef:
  461. return ret | 3;
  462. default:
  463. goto exit;
  464. }
  465. case CodedIndex.ResolutionScope:
  466. ret = token.RID << 2;
  467. switch (token.TokenType) {
  468. case TokenType.Module:
  469. return ret | 0;
  470. case TokenType.ModuleRef:
  471. return ret | 1;
  472. case TokenType.AssemblyRef:
  473. return ret | 2;
  474. case TokenType.TypeRef:
  475. return ret | 3;
  476. default:
  477. goto exit;
  478. }
  479. case CodedIndex.TypeOrMethodDef:
  480. ret = token.RID << 1;
  481. switch (token.TokenType) {
  482. case TokenType.TypeDef:
  483. return ret | 0;
  484. case TokenType.Method:
  485. return ret | 1;
  486. default:
  487. goto exit;
  488. }
  489. case CodedIndex.HasCustomDebugInformation:
  490. ret = token.RID << 5;
  491. switch (token.TokenType) {
  492. case TokenType.Method:
  493. return ret | 0;
  494. case TokenType.Field:
  495. return ret | 1;
  496. case TokenType.TypeRef:
  497. return ret | 2;
  498. case TokenType.TypeDef:
  499. return ret | 3;
  500. case TokenType.Param:
  501. return ret | 4;
  502. case TokenType.InterfaceImpl:
  503. return ret | 5;
  504. case TokenType.MemberRef:
  505. return ret | 6;
  506. case TokenType.Module:
  507. return ret | 7;
  508. case TokenType.Permission:
  509. return ret | 8;
  510. case TokenType.Property:
  511. return ret | 9;
  512. case TokenType.Event:
  513. return ret | 10;
  514. case TokenType.Signature:
  515. return ret | 11;
  516. case TokenType.ModuleRef:
  517. return ret | 12;
  518. case TokenType.TypeSpec:
  519. return ret | 13;
  520. case TokenType.Assembly:
  521. return ret | 14;
  522. case TokenType.AssemblyRef:
  523. return ret | 15;
  524. case TokenType.File:
  525. return ret | 16;
  526. case TokenType.ExportedType:
  527. return ret | 17;
  528. case TokenType.ManifestResource:
  529. return ret | 18;
  530. case TokenType.GenericParam:
  531. return ret | 19;
  532. case TokenType.GenericParamConstraint:
  533. return ret | 20;
  534. case TokenType.MethodSpec:
  535. return ret | 21;
  536. case TokenType.Document:
  537. return ret | 22;
  538. case TokenType.LocalScope:
  539. return ret | 23;
  540. case TokenType.LocalVariable:
  541. return ret | 24;
  542. case TokenType.LocalConstant:
  543. return ret | 25;
  544. case TokenType.ImportScope:
  545. return ret | 26;
  546. default:
  547. goto exit;
  548. }
  549. default:
  550. goto exit;
  551. }
  552. exit:
  553. throw new ArgumentException ();
  554. }
  555. public static int GetSize (this CodedIndex self, Func<Table, int> counter)
  556. {
  557. int bits;
  558. Table [] tables;
  559. switch (self) {
  560. case CodedIndex.TypeDefOrRef:
  561. bits = 2;
  562. tables = new [] { Table.TypeDef, Table.TypeRef, Table.TypeSpec };
  563. break;
  564. case CodedIndex.HasConstant:
  565. bits = 2;
  566. tables = new [] { Table.Field, Table.Param, Table.Property };
  567. break;
  568. case CodedIndex.HasCustomAttribute:
  569. bits = 5;
  570. tables = new [] {
  571. Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef,
  572. Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef,
  573. Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType,
  574. Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec,
  575. };
  576. break;
  577. case CodedIndex.HasFieldMarshal:
  578. bits = 1;
  579. tables = new [] { Table.Field, Table.Param };
  580. break;
  581. case CodedIndex.HasDeclSecurity:
  582. bits = 2;
  583. tables = new [] { Table.TypeDef, Table.Method, Table.Assembly };
  584. break;
  585. case CodedIndex.MemberRefParent:
  586. bits = 3;
  587. tables = new [] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec };
  588. break;
  589. case CodedIndex.HasSemantics:
  590. bits = 1;
  591. tables = new [] { Table.Event, Table.Property };
  592. break;
  593. case CodedIndex.MethodDefOrRef:
  594. bits = 1;
  595. tables = new [] { Table.Method, Table.MemberRef };
  596. break;
  597. case CodedIndex.MemberForwarded:
  598. bits = 1;
  599. tables = new [] { Table.Field, Table.Method };
  600. break;
  601. case CodedIndex.Implementation:
  602. bits = 2;
  603. tables = new [] { Table.File, Table.AssemblyRef, Table.ExportedType };
  604. break;
  605. case CodedIndex.CustomAttributeType:
  606. bits = 3;
  607. tables = new [] { Table.Method, Table.MemberRef };
  608. break;
  609. case CodedIndex.ResolutionScope:
  610. bits = 2;
  611. tables = new [] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef };
  612. break;
  613. case CodedIndex.TypeOrMethodDef:
  614. bits = 1;
  615. tables = new [] { Table.TypeDef, Table.Method };
  616. break;
  617. case CodedIndex.HasCustomDebugInformation:
  618. bits = 5;
  619. tables = new[] {
  620. Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef,
  621. Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef,
  622. Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType,
  623. Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec,
  624. Table.Document, Table.LocalScope, Table.LocalVariable, Table.LocalConstant, Table.ImportScope,
  625. };
  626. break;
  627. default:
  628. throw new ArgumentException ();
  629. }
  630. int max = 0;
  631. for (int i = 0; i < tables.Length; i++) {
  632. max = System.Math.Max (counter (tables [i]), max);
  633. }
  634. return max < (1 << (16 - bits)) ? 2 : 4;
  635. }
  636. }
  637. }