Utilities.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  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. #if !READ_ONLY
  296. public static uint CompressMetadataToken (this CodedIndex self, MetadataToken token)
  297. {
  298. uint ret = 0;
  299. if (token.RID == 0)
  300. return ret;
  301. switch (self) {
  302. case CodedIndex.TypeDefOrRef:
  303. ret = token.RID << 2;
  304. switch (token.TokenType) {
  305. case TokenType.TypeDef:
  306. return ret | 0;
  307. case TokenType.TypeRef:
  308. return ret | 1;
  309. case TokenType.TypeSpec:
  310. return ret | 2;
  311. default:
  312. goto exit;
  313. }
  314. case CodedIndex.HasConstant:
  315. ret = token.RID << 2;
  316. switch (token.TokenType) {
  317. case TokenType.Field:
  318. return ret | 0;
  319. case TokenType.Param:
  320. return ret | 1;
  321. case TokenType.Property:
  322. return ret | 2;
  323. default:
  324. goto exit;
  325. }
  326. case CodedIndex.HasCustomAttribute:
  327. ret = token.RID << 5;
  328. switch (token.TokenType) {
  329. case TokenType.Method:
  330. return ret | 0;
  331. case TokenType.Field:
  332. return ret | 1;
  333. case TokenType.TypeRef:
  334. return ret | 2;
  335. case TokenType.TypeDef:
  336. return ret | 3;
  337. case TokenType.Param:
  338. return ret | 4;
  339. case TokenType.InterfaceImpl:
  340. return ret | 5;
  341. case TokenType.MemberRef:
  342. return ret | 6;
  343. case TokenType.Module:
  344. return ret | 7;
  345. case TokenType.Permission:
  346. return ret | 8;
  347. case TokenType.Property:
  348. return ret | 9;
  349. case TokenType.Event:
  350. return ret | 10;
  351. case TokenType.Signature:
  352. return ret | 11;
  353. case TokenType.ModuleRef:
  354. return ret | 12;
  355. case TokenType.TypeSpec:
  356. return ret | 13;
  357. case TokenType.Assembly:
  358. return ret | 14;
  359. case TokenType.AssemblyRef:
  360. return ret | 15;
  361. case TokenType.File:
  362. return ret | 16;
  363. case TokenType.ExportedType:
  364. return ret | 17;
  365. case TokenType.ManifestResource:
  366. return ret | 18;
  367. case TokenType.GenericParam:
  368. return ret | 19;
  369. case TokenType.GenericParamConstraint:
  370. return ret | 20;
  371. case TokenType.MethodSpec:
  372. return ret | 21;
  373. default:
  374. goto exit;
  375. }
  376. case CodedIndex.HasFieldMarshal:
  377. ret = token.RID << 1;
  378. switch (token.TokenType) {
  379. case TokenType.Field:
  380. return ret | 0;
  381. case TokenType.Param:
  382. return ret | 1;
  383. default:
  384. goto exit;
  385. }
  386. case CodedIndex.HasDeclSecurity:
  387. ret = token.RID << 2;
  388. switch (token.TokenType) {
  389. case TokenType.TypeDef:
  390. return ret | 0;
  391. case TokenType.Method:
  392. return ret | 1;
  393. case TokenType.Assembly:
  394. return ret | 2;
  395. default:
  396. goto exit;
  397. }
  398. case CodedIndex.MemberRefParent:
  399. ret = token.RID << 3;
  400. switch (token.TokenType) {
  401. case TokenType.TypeDef:
  402. return ret | 0;
  403. case TokenType.TypeRef:
  404. return ret | 1;
  405. case TokenType.ModuleRef:
  406. return ret | 2;
  407. case TokenType.Method:
  408. return ret | 3;
  409. case TokenType.TypeSpec:
  410. return ret | 4;
  411. default:
  412. goto exit;
  413. }
  414. case CodedIndex.HasSemantics:
  415. ret = token.RID << 1;
  416. switch (token.TokenType) {
  417. case TokenType.Event:
  418. return ret | 0;
  419. case TokenType.Property:
  420. return ret | 1;
  421. default:
  422. goto exit;
  423. }
  424. case CodedIndex.MethodDefOrRef:
  425. ret = token.RID << 1;
  426. switch (token.TokenType) {
  427. case TokenType.Method:
  428. return ret | 0;
  429. case TokenType.MemberRef:
  430. return ret | 1;
  431. default:
  432. goto exit;
  433. }
  434. case CodedIndex.MemberForwarded:
  435. ret = token.RID << 1;
  436. switch (token.TokenType) {
  437. case TokenType.Field:
  438. return ret | 0;
  439. case TokenType.Method:
  440. return ret | 1;
  441. default:
  442. goto exit;
  443. }
  444. case CodedIndex.Implementation:
  445. ret = token.RID << 2;
  446. switch (token.TokenType) {
  447. case TokenType.File:
  448. return ret | 0;
  449. case TokenType.AssemblyRef:
  450. return ret | 1;
  451. case TokenType.ExportedType:
  452. return ret | 2;
  453. default:
  454. goto exit;
  455. }
  456. case CodedIndex.CustomAttributeType:
  457. ret = token.RID << 3;
  458. switch (token.TokenType) {
  459. case TokenType.Method:
  460. return ret | 2;
  461. case TokenType.MemberRef:
  462. return ret | 3;
  463. default:
  464. goto exit;
  465. }
  466. case CodedIndex.ResolutionScope:
  467. ret = token.RID << 2;
  468. switch (token.TokenType) {
  469. case TokenType.Module:
  470. return ret | 0;
  471. case TokenType.ModuleRef:
  472. return ret | 1;
  473. case TokenType.AssemblyRef:
  474. return ret | 2;
  475. case TokenType.TypeRef:
  476. return ret | 3;
  477. default:
  478. goto exit;
  479. }
  480. case CodedIndex.TypeOrMethodDef:
  481. ret = token.RID << 1;
  482. switch (token.TokenType) {
  483. case TokenType.TypeDef:
  484. return ret | 0;
  485. case TokenType.Method:
  486. return ret | 1;
  487. default:
  488. goto exit;
  489. }
  490. case CodedIndex.HasCustomDebugInformation:
  491. ret = token.RID << 5;
  492. switch (token.TokenType) {
  493. case TokenType.Method:
  494. return ret | 0;
  495. case TokenType.Field:
  496. return ret | 1;
  497. case TokenType.TypeRef:
  498. return ret | 2;
  499. case TokenType.TypeDef:
  500. return ret | 3;
  501. case TokenType.Param:
  502. return ret | 4;
  503. case TokenType.InterfaceImpl:
  504. return ret | 5;
  505. case TokenType.MemberRef:
  506. return ret | 6;
  507. case TokenType.Module:
  508. return ret | 7;
  509. case TokenType.Permission:
  510. return ret | 8;
  511. case TokenType.Property:
  512. return ret | 9;
  513. case TokenType.Event:
  514. return ret | 10;
  515. case TokenType.Signature:
  516. return ret | 11;
  517. case TokenType.ModuleRef:
  518. return ret | 12;
  519. case TokenType.TypeSpec:
  520. return ret | 13;
  521. case TokenType.Assembly:
  522. return ret | 14;
  523. case TokenType.AssemblyRef:
  524. return ret | 15;
  525. case TokenType.File:
  526. return ret | 16;
  527. case TokenType.ExportedType:
  528. return ret | 17;
  529. case TokenType.ManifestResource:
  530. return ret | 18;
  531. case TokenType.GenericParam:
  532. return ret | 19;
  533. case TokenType.GenericParamConstraint:
  534. return ret | 20;
  535. case TokenType.MethodSpec:
  536. return ret | 21;
  537. case TokenType.Document:
  538. return ret | 22;
  539. case TokenType.LocalScope:
  540. return ret | 23;
  541. case TokenType.LocalVariable:
  542. return ret | 24;
  543. case TokenType.LocalConstant:
  544. return ret | 25;
  545. case TokenType.ImportScope:
  546. return ret | 26;
  547. default:
  548. goto exit;
  549. }
  550. default:
  551. goto exit;
  552. }
  553. exit:
  554. throw new ArgumentException ();
  555. }
  556. #endif
  557. public static int GetSize (this CodedIndex self, Func<Table, int> counter)
  558. {
  559. int bits;
  560. Table [] tables;
  561. switch (self) {
  562. case CodedIndex.TypeDefOrRef:
  563. bits = 2;
  564. tables = new [] { Table.TypeDef, Table.TypeRef, Table.TypeSpec };
  565. break;
  566. case CodedIndex.HasConstant:
  567. bits = 2;
  568. tables = new [] { Table.Field, Table.Param, Table.Property };
  569. break;
  570. case CodedIndex.HasCustomAttribute:
  571. bits = 5;
  572. tables = new [] {
  573. Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef,
  574. Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef,
  575. Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType,
  576. Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec,
  577. };
  578. break;
  579. case CodedIndex.HasFieldMarshal:
  580. bits = 1;
  581. tables = new [] { Table.Field, Table.Param };
  582. break;
  583. case CodedIndex.HasDeclSecurity:
  584. bits = 2;
  585. tables = new [] { Table.TypeDef, Table.Method, Table.Assembly };
  586. break;
  587. case CodedIndex.MemberRefParent:
  588. bits = 3;
  589. tables = new [] { Table.TypeDef, Table.TypeRef, Table.ModuleRef, Table.Method, Table.TypeSpec };
  590. break;
  591. case CodedIndex.HasSemantics:
  592. bits = 1;
  593. tables = new [] { Table.Event, Table.Property };
  594. break;
  595. case CodedIndex.MethodDefOrRef:
  596. bits = 1;
  597. tables = new [] { Table.Method, Table.MemberRef };
  598. break;
  599. case CodedIndex.MemberForwarded:
  600. bits = 1;
  601. tables = new [] { Table.Field, Table.Method };
  602. break;
  603. case CodedIndex.Implementation:
  604. bits = 2;
  605. tables = new [] { Table.File, Table.AssemblyRef, Table.ExportedType };
  606. break;
  607. case CodedIndex.CustomAttributeType:
  608. bits = 3;
  609. tables = new [] { Table.Method, Table.MemberRef };
  610. break;
  611. case CodedIndex.ResolutionScope:
  612. bits = 2;
  613. tables = new [] { Table.Module, Table.ModuleRef, Table.AssemblyRef, Table.TypeRef };
  614. break;
  615. case CodedIndex.TypeOrMethodDef:
  616. bits = 1;
  617. tables = new [] { Table.TypeDef, Table.Method };
  618. break;
  619. case CodedIndex.HasCustomDebugInformation:
  620. bits = 5;
  621. tables = new[] {
  622. Table.Method, Table.Field, Table.TypeRef, Table.TypeDef, Table.Param, Table.InterfaceImpl, Table.MemberRef,
  623. Table.Module, Table.DeclSecurity, Table.Property, Table.Event, Table.StandAloneSig, Table.ModuleRef,
  624. Table.TypeSpec, Table.Assembly, Table.AssemblyRef, Table.File, Table.ExportedType,
  625. Table.ManifestResource, Table.GenericParam, Table.GenericParamConstraint, Table.MethodSpec,
  626. Table.Document, Table.LocalScope, Table.LocalVariable, Table.LocalConstant, Table.ImportScope,
  627. };
  628. break;
  629. default:
  630. throw new ArgumentException ();
  631. }
  632. int max = 0;
  633. for (int i = 0; i < tables.Length; i++) {
  634. max = System.Math.Max (counter (tables [i]), max);
  635. }
  636. return max < (1 << (16 - bits)) ? 2 : 4;
  637. }
  638. }
  639. }