* Parameters.cs (ParseArguments): If no project file is specified,
[mcs.git] / tools / pdb2mdb / PdbFunction.cs
blobbe284204dcf0a209c5fdcfa8aa2bdfb28c2c3c35
1 //-----------------------------------------------------------------------------
2 //
3 // Copyright (C) Microsoft Corporation. All Rights Reserved.
4 //
5 //-----------------------------------------------------------------------------
6 using System;
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();
17 internal uint token;
18 internal uint slotToken;
19 internal string name;
20 internal string module;
21 internal ushort flags;
23 internal uint segment;
24 internal uint address;
25 internal uint length;
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('.');
37 if (li > 0) {
38 return module.Substring(li + 1);
40 return module;
44 internal static PdbFunction[] LoadManagedFunctions(string module,
45 BitAccess bits, uint limit,
46 bool readStrings) {
47 string mod = StripNamespace(module);
48 int begin = bits.Position;
49 int count = 0;
51 while (bits.Position < limit) {
52 ushort siz;
53 ushort rec;
55 bits.ReadUInt16(out siz);
56 int star = bits.Position;
57 int stop = bits.Position + siz;
58 bits.Position = star;
59 bits.ReadUInt16(out rec);
61 switch ((SYM)rec) {
62 case SYM.S_GMANPROC:
63 case SYM.S_LMANPROC:
64 ManProcSym proc;
65 bits.ReadUInt32(out proc.parent);
66 bits.ReadUInt32(out proc.end);
67 bits.Position = (int)proc.end;
68 count++;
69 break;
71 case SYM.S_END:
72 bits.Position = stop;
73 break;
75 default:
76 //Console.WriteLine("{0,6}: {1:x2} {2}",
77 // bits.Position, rec, (SYM)rec);
78 bits.Position = stop;
79 break;
82 if (count == 0) {
83 return null;
86 bits.Position = begin;
87 PdbFunction[] funcs = new PdbFunction[count];
88 int func = 0;
90 while (bits.Position < limit) {
91 ushort siz;
92 ushort rec;
94 bits.ReadUInt16(out siz);
95 int star = bits.Position;
96 int stop = bits.Position + siz;
97 bits.ReadUInt16(out rec);
99 switch ((SYM)rec) {
101 case SYM.S_GMANPROC:
102 case SYM.S_LMANPROC:
103 ManProcSym proc;
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);
117 if (readStrings) {
118 bits.ReadCString(out proc.name);
119 } else {
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);
126 break;
128 default: {
129 //throw new PdbDebugException("Unknown SYMREC {0}", (SYM)rec);
130 bits.Position = stop;
131 break;
135 return funcs;
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;
141 BlockSym32 block;
142 constants = 0;
143 slots = 0;
144 scopes = 0;
145 usedNamespaces = 0;
147 while (bits.Position < limit) {
148 ushort siz;
149 ushort rec;
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);
157 switch ((SYM)rec) {
158 case SYM.S_BLOCK32: {
159 bits.ReadUInt32(out block.parent);
160 bits.ReadUInt32(out block.end);
162 scopes++;
163 bits.Position = (int)block.end;
164 break;
167 case SYM.S_MANSLOT:
168 slots++;
169 bits.Position = stop;
170 break;
172 case SYM.S_UNAMESPACE:
173 usedNamespaces++;
174 bits.Position = stop;
175 break;
177 case SYM.S_MANCONSTANT:
178 constants++;
179 bits.Position = stop;
180 break;
182 default:
183 bits.Position = stop;
184 break;
187 bits.Position = pos;
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;
201 this.slotToken = 0;
203 if (proc.seg != 1) {
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);
215 int constantCount;
216 int scopeCount;
217 int slotCount;
218 int usedNamespacesCount;
219 CountScopesAndSlots(bits, proc.end, out constantCount, out scopeCount, out slotCount, out usedNamespacesCount);
220 scopes = new PdbScope[scopeCount];
221 int scope = 0;
223 while (bits.Position < proc.end) {
224 ushort siz;
225 ushort rec;
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);
233 switch ((SYM)rec) {
234 case SYM.S_OEM: { // 0x0404
235 OemSymbol oem;
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();
243 if (name == "MD2") {
244 byte version;
245 bits.ReadUInt8(out version);
246 if (version == 4) {
247 byte count;
248 bits.ReadUInt8(out count);
249 bits.Align(4);
250 while (count-- > 0)
251 this.ReadCustomMetadata(bits);
254 bits.Position = stop;
255 break;
256 } else {
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;
276 break;
279 case SYM.S_UNAMESPACE:
280 bits.Position = stop;
281 break;
283 case SYM.S_END:
284 bits.Position = stop;
285 break;
287 default: {
288 //throw new PdbDebugException("Unknown SYM: {0}", (SYM)rec);
289 bits.Position = stop;
290 break;
295 if (bits.Position != proc.end) {
296 throw new PdbDebugException("Not at S_END");
299 ushort esiz;
300 ushort erec;
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;
311 byte version;
312 bits.ReadUInt8(out version);
313 if (version != 4) {
314 throw new PdbDebugException("Unknown custom metadata item version: {0}", version);
316 byte kind;
317 bits.ReadUInt8(out kind);
318 bits.Align(4);
319 uint numberOfBytesInItem;
320 bits.ReadUInt32(out numberOfBytesInItem);
321 switch (kind) {
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) {
337 uint numberOfLocals;
338 bits.ReadUInt32(out numberOfLocals);
339 this.iteratorScopes = new List<ILocalScope>((int)numberOfLocals);
340 while (numberOfLocals-- > 0) {
341 uint ilStartOffset;
342 uint ilEndOffset;
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) {
370 return -1;
371 } else if (fx.segment > fy.segment) {
372 return 1;
373 } else if (fx.address < fy.address) {
374 return -1;
375 } else if (fx.address > fy.address) {
376 return 1;
377 } else {
378 return 0;
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) {
389 return -1;
390 } else if (fx.token > fy.token) {
391 return 1;
392 } else {
393 return 0;