1 //-----------------------------------------------------------------------------
3 // Copyright (C) Microsoft Corporation. All Rights Reserved.
5 //-----------------------------------------------------------------------------
7 using System.Collections;
8 using System.Collections.Generic;
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();
18 internal uint slotToken;
20 internal string module;
21 internal ushort flags;
23 internal uint segment;
24 internal uint address;
27 //internal byte[] metadata;
28 internal PdbScope[] scopes;
29 internal PdbLines[] lines;
30 internal ushort[]/*?*/ usingCounts;
31 internal IEnumerable<INamespaceScope>/*?*/ namespaceScopes;
32 internal string/*?*/ iteratorClass;
33 internal List<ILocalScope>/*?*/ iteratorScopes;
35 private static string StripNamespace(string module) {
36 int li = module.LastIndexOf('.');
38 return module.Substring(li + 1);
44 internal static PdbFunction[] LoadManagedFunctions(string module,
45 BitAccess bits, uint limit,
47 string mod = StripNamespace(module);
48 int begin = bits.Position;
51 while (bits.Position < limit) {
55 bits.ReadUInt16(out siz);
56 int star = bits.Position;
57 int stop = bits.Position + siz;
59 bits.ReadUInt16(out rec);
65 bits.ReadUInt32(out proc.parent);
66 bits.ReadUInt32(out proc.end);
67 bits.Position = (int)proc.end;
76 //Console.WriteLine("{0,6}: {1:x2} {2}",
77 // bits.Position, rec, (SYM)rec);
86 bits.Position = begin;
87 PdbFunction[] funcs = new PdbFunction[count];
90 while (bits.Position < limit) {
94 bits.ReadUInt16(out siz);
95 int star = bits.Position;
96 int stop = bits.Position + siz;
97 bits.ReadUInt16(out rec);
104 int offset = bits.Position;
106 bits.ReadUInt32(out proc.parent);
107 bits.ReadUInt32(out proc.end);
108 bits.ReadUInt32(out proc.next);
109 bits.ReadUInt32(out proc.len);
110 bits.ReadUInt32(out proc.dbgStart);
111 bits.ReadUInt32(out proc.dbgEnd);
112 bits.ReadUInt32(out proc.token);
113 bits.ReadUInt32(out proc.off);
114 bits.ReadUInt16(out proc.seg);
115 bits.ReadUInt8(out proc.flags);
116 bits.ReadUInt16(out proc.retReg);
118 bits.ReadCString(out proc.name);
120 bits.SkipCString(out proc.name);
122 //Console.WriteLine("token={0:X8} [{1}::{2}]", proc.token, module, proc.name);
124 bits.Position = stop;
125 funcs[func++] = new PdbFunction(module, proc, bits);
129 //throw new PdbDebugException("Unknown SYMREC {0}", (SYM)rec);
130 bits.Position = stop;
138 internal static void CountScopesAndSlots(BitAccess bits, uint limit,
139 out int constants, out int scopes, out int slots, out int usedNamespaces) {
140 int pos = bits.Position;
147 while (bits.Position < limit) {
151 bits.ReadUInt16(out siz);
152 int star = bits.Position;
153 int stop = bits.Position + siz;
154 bits.Position = star;
155 bits.ReadUInt16(out rec);
158 case SYM.S_BLOCK32: {
159 bits.ReadUInt32(out block.parent);
160 bits.ReadUInt32(out block.end);
163 bits.Position = (int)block.end;
169 bits.Position = stop;
172 case SYM.S_UNAMESPACE:
174 bits.Position = stop;
177 case SYM.S_MANCONSTANT:
179 bits.Position = stop;
183 bits.Position = stop;
190 internal PdbFunction() {
193 internal PdbFunction(string module, ManProcSym proc, BitAccess bits) {
194 this.token = proc.token;
195 this.module = module;
196 this.name = proc.name;
197 this.flags = proc.flags;
198 this.segment = proc.seg;
199 this.address = proc.off;
200 this.length = proc.len;
204 throw new PdbDebugException("Segment is {0}, not 1.", proc.seg);
206 if (proc.parent != 0 || proc.next != 0) {
207 throw new PdbDebugException("Warning parent={0}, next={1}",
208 proc.parent, proc.next);
210 if (proc.dbgStart != 0 || proc.dbgEnd != 0) {
211 throw new PdbDebugException("Warning DBG start={0}, end={1}",
212 proc.dbgStart, proc.dbgEnd);
218 int usedNamespacesCount;
219 CountScopesAndSlots(bits, proc.end, out constantCount, out scopeCount, out slotCount, out usedNamespacesCount);
220 scopes = new PdbScope[scopeCount];
223 while (bits.Position < proc.end) {
227 bits.ReadUInt16(out siz);
228 int star = bits.Position;
229 int stop = bits.Position + siz;
230 bits.Position = star;
231 bits.ReadUInt16(out rec);
234 case SYM.S_OEM: { // 0x0404
237 bits.ReadGuid(out oem.idOem);
238 bits.ReadUInt32(out oem.typind);
239 // internal byte[] rgl; // user data, force 4-byte alignment
241 if (oem.idOem == msilMetaData) {
242 string name = bits.ReadString();
245 bits.ReadUInt8(out version);
248 bits.ReadUInt8(out count);
251 this.ReadCustomMetadata(bits);
254 bits.Position = stop;
257 throw new PdbDebugException("OEM section: guid={0} ti={1}",
258 oem.idOem, oem.typind);
259 // bits.Position = stop;
263 case SYM.S_BLOCK32: {
264 BlockSym32 block = new BlockSym32();
266 bits.ReadUInt32(out block.parent);
267 bits.ReadUInt32(out block.end);
268 bits.ReadUInt32(out block.len);
269 bits.ReadUInt32(out this.address);
270 bits.ReadUInt16(out block.seg);
271 bits.SkipCString(out block.name);
272 bits.Position = stop;
274 scopes[scope] = new PdbScope(block, bits, out slotToken);
275 bits.Position = (int)block.end;
279 case SYM.S_UNAMESPACE:
280 bits.Position = stop;
284 bits.Position = stop;
288 //throw new PdbDebugException("Unknown SYM: {0}", (SYM)rec);
289 bits.Position = stop;
295 if (bits.Position != proc.end) {
296 throw new PdbDebugException("Not at S_END");
301 bits.ReadUInt16(out esiz);
302 bits.ReadUInt16(out erec);
304 if (erec != (ushort)SYM.S_END) {
305 throw new PdbDebugException("Missing S_END");
309 private void ReadCustomMetadata(BitAccess bits) {
310 int savedPosition = bits.Position;
312 bits.ReadUInt8(out version);
314 throw new PdbDebugException("Unknown custom metadata item version: {0}", version);
317 bits.ReadUInt8(out kind);
319 uint numberOfBytesInItem;
320 bits.ReadUInt32(out numberOfBytesInItem);
322 case 0: this.ReadUsingInfo(bits); break;
323 case 1: this.ReadForwardInfo(bits); break;
324 case 2: this.ReadForwardedToModuleInfo(bits); break;
325 case 3: this.ReadIteratorLocals(bits); break;
326 case 4: this.ReadForwardIterator(bits); break;
327 default: throw new PdbDebugException("Unknown custom metadata item kind: {0}", kind);
329 bits.Position = savedPosition+(int)numberOfBytesInItem;
332 private void ReadForwardIterator(BitAccess bits) {
333 this.iteratorClass = bits.ReadString();
336 private void ReadIteratorLocals(BitAccess bits) {
338 bits.ReadUInt32(out numberOfLocals);
339 this.iteratorScopes = new List<ILocalScope>((int)numberOfLocals);
340 while (numberOfLocals-- > 0) {
343 bits.ReadUInt32(out ilStartOffset);
344 bits.ReadUInt32(out ilEndOffset);
345 this.iteratorScopes.Add(new PdbIteratorScope(ilStartOffset, ilEndOffset-ilStartOffset));
349 private void ReadForwardedToModuleInfo(BitAccess bits) {
352 private void ReadForwardInfo(BitAccess bits) {
355 private void ReadUsingInfo(BitAccess bits) {
356 ushort numberOfNamespaces;
357 bits.ReadUInt16(out numberOfNamespaces);
358 this.usingCounts = new ushort[numberOfNamespaces];
359 for (ushort i = 0; i < numberOfNamespaces; i++) {
360 bits.ReadUInt16(out this.usingCounts[i]);
364 internal class PdbFunctionsByAddress : IComparer {
365 public int Compare(Object x, Object y) {
366 PdbFunction fx = (PdbFunction)x;
367 PdbFunction fy = (PdbFunction)y;
369 if (fx.segment < fy.segment) {
371 } else if (fx.segment > fy.segment) {
373 } else if (fx.address < fy.address) {
375 } else if (fx.address > fy.address) {
383 internal class PdbFunctionsByToken : IComparer {
384 public int Compare(Object x, Object y) {
385 PdbFunction fx = (PdbFunction)x;
386 PdbFunction fy = (PdbFunction)y;
388 if (fx.token < fy.token) {
390 } else if (fx.token > fy.token) {