PageRenderTime 29ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/cecil/symbols/pdb/Microsoft.Cci.Pdb/PdbFunction.cs

#
C# | 401 lines | 329 code | 59 blank | 13 comment | 52 complexity | 1d61dde26fdd2ebbac26d2a42035b563 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //-----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  4. //
  5. //-----------------------------------------------------------------------------
  6. using System;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. #pragma warning disable 0649
  10. namespace Microsoft.Cci.Pdb {
  11. internal class PdbFunction {
  12. static internal readonly Guid msilMetaData = new Guid(0xc6ea3fc9, 0x59b3, 0x49d6, 0xbc, 0x25,
  13. 0x09, 0x02, 0xbb, 0xab, 0xb4, 0x60);
  14. static internal readonly IComparer byAddress = new PdbFunctionsByAddress();
  15. static internal readonly IComparer byToken = new PdbFunctionsByToken();
  16. internal uint token;
  17. internal uint slotToken;
  18. internal string name;
  19. internal string module;
  20. internal ushort flags;
  21. internal uint segment;
  22. internal uint address;
  23. internal uint length;
  24. //internal byte[] metadata;
  25. internal PdbScope[] scopes;
  26. internal PdbLines[] lines;
  27. internal ushort[]/*?*/ usingCounts;
  28. internal IEnumerable<INamespaceScope>/*?*/ namespaceScopes;
  29. internal string/*?*/ iteratorClass;
  30. internal List<ILocalScope>/*?*/ iteratorScopes;
  31. private static string StripNamespace(string module) {
  32. int li = module.LastIndexOf('.');
  33. if (li > 0) {
  34. return module.Substring(li + 1);
  35. }
  36. return module;
  37. }
  38. internal static PdbFunction[] LoadManagedFunctions(string module,
  39. BitAccess bits, uint limit,
  40. bool readStrings) {
  41. string mod = StripNamespace(module);
  42. int begin = bits.Position;
  43. int count = 0;
  44. while (bits.Position < limit) {
  45. ushort siz;
  46. ushort rec;
  47. bits.ReadUInt16(out siz);
  48. int star = bits.Position;
  49. int stop = bits.Position + siz;
  50. bits.Position = star;
  51. bits.ReadUInt16(out rec);
  52. switch ((SYM)rec) {
  53. case SYM.S_GMANPROC:
  54. case SYM.S_LMANPROC:
  55. ManProcSym proc;
  56. bits.ReadUInt32(out proc.parent);
  57. bits.ReadUInt32(out proc.end);
  58. bits.Position = (int)proc.end;
  59. count++;
  60. break;
  61. case SYM.S_END:
  62. bits.Position = stop;
  63. break;
  64. default:
  65. //Console.WriteLine("{0,6}: {1:x2} {2}",
  66. // bits.Position, rec, (SYM)rec);
  67. bits.Position = stop;
  68. break;
  69. }
  70. }
  71. if (count == 0) {
  72. return null;
  73. }
  74. bits.Position = begin;
  75. PdbFunction[] funcs = new PdbFunction[count];
  76. int func = 0;
  77. while (bits.Position < limit) {
  78. ushort siz;
  79. ushort rec;
  80. bits.ReadUInt16(out siz);
  81. int star = bits.Position;
  82. int stop = bits.Position + siz;
  83. bits.ReadUInt16(out rec);
  84. switch ((SYM)rec) {
  85. case SYM.S_GMANPROC:
  86. case SYM.S_LMANPROC:
  87. ManProcSym proc;
  88. int offset = bits.Position;
  89. bits.ReadUInt32(out proc.parent);
  90. bits.ReadUInt32(out proc.end);
  91. bits.ReadUInt32(out proc.next);
  92. bits.ReadUInt32(out proc.len);
  93. bits.ReadUInt32(out proc.dbgStart);
  94. bits.ReadUInt32(out proc.dbgEnd);
  95. bits.ReadUInt32(out proc.token);
  96. bits.ReadUInt32(out proc.off);
  97. bits.ReadUInt16(out proc.seg);
  98. bits.ReadUInt8(out proc.flags);
  99. bits.ReadUInt16(out proc.retReg);
  100. if (readStrings) {
  101. bits.ReadCString(out proc.name);
  102. } else {
  103. bits.SkipCString(out proc.name);
  104. }
  105. //Console.WriteLine("token={0:X8} [{1}::{2}]", proc.token, module, proc.name);
  106. bits.Position = stop;
  107. funcs[func++] = new PdbFunction(module, proc, bits);
  108. break;
  109. default: {
  110. //throw new PdbDebugException("Unknown SYMREC {0}", (SYM)rec);
  111. bits.Position = stop;
  112. break;
  113. }
  114. }
  115. }
  116. return funcs;
  117. }
  118. internal static void CountScopesAndSlots(BitAccess bits, uint limit,
  119. out int constants, out int scopes, out int slots, out int usedNamespaces) {
  120. int pos = bits.Position;
  121. BlockSym32 block;
  122. constants = 0;
  123. slots = 0;
  124. scopes = 0;
  125. usedNamespaces = 0;
  126. while (bits.Position < limit) {
  127. ushort siz;
  128. ushort rec;
  129. bits.ReadUInt16(out siz);
  130. int star = bits.Position;
  131. int stop = bits.Position + siz;
  132. bits.Position = star;
  133. bits.ReadUInt16(out rec);
  134. switch ((SYM)rec) {
  135. case SYM.S_BLOCK32: {
  136. bits.ReadUInt32(out block.parent);
  137. bits.ReadUInt32(out block.end);
  138. scopes++;
  139. bits.Position = (int)block.end;
  140. break;
  141. }
  142. case SYM.S_MANSLOT:
  143. slots++;
  144. bits.Position = stop;
  145. break;
  146. case SYM.S_UNAMESPACE:
  147. usedNamespaces++;
  148. bits.Position = stop;
  149. break;
  150. case SYM.S_MANCONSTANT:
  151. constants++;
  152. bits.Position = stop;
  153. break;
  154. default:
  155. bits.Position = stop;
  156. break;
  157. }
  158. }
  159. bits.Position = pos;
  160. }
  161. internal PdbFunction() {
  162. }
  163. internal PdbFunction(string module, ManProcSym proc, BitAccess bits) {
  164. this.token = proc.token;
  165. this.module = module;
  166. this.name = proc.name;
  167. this.flags = proc.flags;
  168. this.segment = proc.seg;
  169. this.address = proc.off;
  170. this.length = proc.len;
  171. this.slotToken = 0;
  172. if (proc.seg != 1) {
  173. throw new PdbDebugException("Segment is {0}, not 1.", proc.seg);
  174. }
  175. if (proc.parent != 0 || proc.next != 0) {
  176. throw new PdbDebugException("Warning parent={0}, next={1}",
  177. proc.parent, proc.next);
  178. }
  179. if (proc.dbgStart != 0 || proc.dbgEnd != 0) {
  180. throw new PdbDebugException("Warning DBG start={0}, end={1}",
  181. proc.dbgStart, proc.dbgEnd);
  182. }
  183. int constantCount;
  184. int scopeCount;
  185. int slotCount;
  186. int usedNamespacesCount;
  187. CountScopesAndSlots(bits, proc.end, out constantCount, out scopeCount, out slotCount, out usedNamespacesCount);
  188. scopes = new PdbScope[scopeCount];
  189. int scope = 0;
  190. while (bits.Position < proc.end) {
  191. ushort siz;
  192. ushort rec;
  193. bits.ReadUInt16(out siz);
  194. int star = bits.Position;
  195. int stop = bits.Position + siz;
  196. bits.Position = star;
  197. bits.ReadUInt16(out rec);
  198. switch ((SYM)rec) {
  199. case SYM.S_OEM: { // 0x0404
  200. OemSymbol oem;
  201. bits.ReadGuid(out oem.idOem);
  202. bits.ReadUInt32(out oem.typind);
  203. // internal byte[] rgl; // user data, force 4-byte alignment
  204. if (oem.idOem == msilMetaData) {
  205. string name = bits.ReadString();
  206. if (name == "MD2") {
  207. byte version;
  208. bits.ReadUInt8(out version);
  209. if (version == 4) {
  210. byte count;
  211. bits.ReadUInt8(out count);
  212. bits.Align(4);
  213. while (count-- > 0)
  214. this.ReadCustomMetadata(bits);
  215. }
  216. }
  217. bits.Position = stop;
  218. break;
  219. } else {
  220. throw new PdbDebugException("OEM section: guid={0} ti={1}",
  221. oem.idOem, oem.typind);
  222. // bits.Position = stop;
  223. }
  224. }
  225. case SYM.S_BLOCK32: {
  226. BlockSym32 block = new BlockSym32();
  227. bits.ReadUInt32(out block.parent);
  228. bits.ReadUInt32(out block.end);
  229. bits.ReadUInt32(out block.len);
  230. bits.ReadUInt32(out this.address);
  231. bits.ReadUInt16(out block.seg);
  232. bits.SkipCString(out block.name);
  233. bits.Position = stop;
  234. scopes[scope] = new PdbScope(block, bits, out slotToken);
  235. bits.Position = (int)block.end;
  236. break;
  237. }
  238. case SYM.S_UNAMESPACE:
  239. bits.Position = stop;
  240. break;
  241. case SYM.S_END:
  242. bits.Position = stop;
  243. break;
  244. default: {
  245. //throw new PdbDebugException("Unknown SYM: {0}", (SYM)rec);
  246. bits.Position = stop;
  247. break;
  248. }
  249. }
  250. }
  251. if (bits.Position != proc.end) {
  252. throw new PdbDebugException("Not at S_END");
  253. }
  254. ushort esiz;
  255. ushort erec;
  256. bits.ReadUInt16(out esiz);
  257. bits.ReadUInt16(out erec);
  258. if (erec != (ushort)SYM.S_END) {
  259. throw new PdbDebugException("Missing S_END");
  260. }
  261. }
  262. private void ReadCustomMetadata(BitAccess bits) {
  263. int savedPosition = bits.Position;
  264. byte version;
  265. bits.ReadUInt8(out version);
  266. if (version != 4) {
  267. throw new PdbDebugException("Unknown custom metadata item version: {0}", version);
  268. }
  269. byte kind;
  270. bits.ReadUInt8(out kind);
  271. bits.Align(4);
  272. uint numberOfBytesInItem;
  273. bits.ReadUInt32(out numberOfBytesInItem);
  274. switch (kind) {
  275. case 0: this.ReadUsingInfo(bits); break;
  276. case 1: this.ReadForwardInfo(bits); break;
  277. case 2: this.ReadForwardedToModuleInfo(bits); break;
  278. case 3: this.ReadIteratorLocals(bits); break;
  279. case 4: this.ReadForwardIterator(bits); break;
  280. default: throw new PdbDebugException("Unknown custom metadata item kind: {0}", kind);
  281. }
  282. bits.Position = savedPosition+(int)numberOfBytesInItem;
  283. }
  284. private void ReadForwardIterator(BitAccess bits) {
  285. this.iteratorClass = bits.ReadString();
  286. }
  287. private void ReadIteratorLocals(BitAccess bits) {
  288. uint numberOfLocals;
  289. bits.ReadUInt32(out numberOfLocals);
  290. this.iteratorScopes = new List<ILocalScope>((int)numberOfLocals);
  291. while (numberOfLocals-- > 0) {
  292. uint ilStartOffset;
  293. uint ilEndOffset;
  294. bits.ReadUInt32(out ilStartOffset);
  295. bits.ReadUInt32(out ilEndOffset);
  296. this.iteratorScopes.Add(new PdbIteratorScope(ilStartOffset, ilEndOffset-ilStartOffset));
  297. }
  298. }
  299. private void ReadForwardedToModuleInfo(BitAccess bits) {
  300. }
  301. private void ReadForwardInfo(BitAccess bits) {
  302. }
  303. private void ReadUsingInfo(BitAccess bits) {
  304. ushort numberOfNamespaces;
  305. bits.ReadUInt16(out numberOfNamespaces);
  306. this.usingCounts = new ushort[numberOfNamespaces];
  307. for (ushort i = 0; i < numberOfNamespaces; i++) {
  308. bits.ReadUInt16(out this.usingCounts[i]);
  309. }
  310. }
  311. internal class PdbFunctionsByAddress : IComparer {
  312. public int Compare(Object x, Object y) {
  313. PdbFunction fx = (PdbFunction)x;
  314. PdbFunction fy = (PdbFunction)y;
  315. if (fx.segment < fy.segment) {
  316. return -1;
  317. } else if (fx.segment > fy.segment) {
  318. return 1;
  319. } else if (fx.address < fy.address) {
  320. return -1;
  321. } else if (fx.address > fy.address) {
  322. return 1;
  323. } else {
  324. return 0;
  325. }
  326. }
  327. }
  328. internal class PdbFunctionsByToken : IComparer {
  329. public int Compare(Object x, Object y) {
  330. PdbFunction fx = (PdbFunction)x;
  331. PdbFunction fy = (PdbFunction)y;
  332. if (fx.token < fy.token) {
  333. return -1;
  334. } else if (fx.token > fy.token) {
  335. return 1;
  336. } else {
  337. return 0;
  338. }
  339. }
  340. }
  341. }
  342. }