Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.Cecil/0.9.5/Mono.Cecil-0.9.5/Symbols/Mono.Cecil.Pdb/Microsoft.Cci.Pdb/PdbFunction.cs @ 16048

Last change on this file since 16048 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 11.7 KB
Line 
1//-----------------------------------------------------------------------------
2//
3// Copyright (C) Microsoft Corporation.  All Rights Reserved.
4//
5//-----------------------------------------------------------------------------
6using System;
7using System.Collections;
8using System.Collections.Generic;
9
10namespace 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
17    internal uint token;
18    internal uint slotToken;
19    internal string name;
20    internal string module;
21    internal ushort flags;
22
23    internal uint segment;
24    internal uint address;
25    internal uint length;
26
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;
34
35    private static string StripNamespace(string module) {
36      int li = module.LastIndexOf('.');
37      if (li > 0) {
38        return module.Substring(li + 1);
39      }
40      return module;
41    }
42
43
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;
50
51      while (bits.Position < limit) {
52        ushort siz;
53        ushort rec;
54
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);
60
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;
70
71          case SYM.S_END:
72            bits.Position = stop;
73            break;
74
75          default:
76            //Console.WriteLine("{0,6}: {1:x2} {2}",
77            //                  bits.Position, rec, (SYM)rec);
78            bits.Position = stop;
79            break;
80        }
81      }
82      if (count == 0) {
83        return null;
84      }
85
86      bits.Position = begin;
87      PdbFunction[] funcs = new PdbFunction[count];
88      int func = 0;
89
90      while (bits.Position < limit) {
91        ushort siz;
92        ushort rec;
93
94        bits.ReadUInt16(out siz);
95        int star = bits.Position;
96        int stop = bits.Position + siz;
97        bits.ReadUInt16(out rec);
98
99        switch ((SYM)rec) {
100
101          case SYM.S_GMANPROC:
102          case SYM.S_LMANPROC:
103            ManProcSym proc;
104            int offset = bits.Position;
105
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);
121            }
122            //Console.WriteLine("token={0:X8} [{1}::{2}]", proc.token, module, proc.name);
123
124            bits.Position = stop;
125            funcs[func++] = new PdbFunction(module, proc, bits);
126            break;
127
128          default: {
129              //throw new PdbDebugException("Unknown SYMREC {0}", (SYM)rec);
130              bits.Position = stop;
131              break;
132            }
133        }
134      }
135      return funcs;
136    }
137
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;
146
147      while (bits.Position < limit) {
148        ushort siz;
149        ushort rec;
150
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);
156
157        switch ((SYM)rec) {
158          case SYM.S_BLOCK32: {
159              bits.ReadUInt32(out block.parent);
160              bits.ReadUInt32(out block.end);
161
162              scopes++;
163              bits.Position = (int)block.end;
164              break;
165            }
166
167          case SYM.S_MANSLOT:
168            slots++;
169            bits.Position = stop;
170            break;
171
172          case SYM.S_UNAMESPACE:
173            usedNamespaces++;
174            bits.Position = stop;
175            break;
176
177          case SYM.S_MANCONSTANT:
178            constants++;
179            bits.Position = stop;
180            break;
181
182          default:
183            bits.Position = stop;
184            break;
185        }
186      }
187      bits.Position = pos;
188    }
189
190    internal PdbFunction() {
191    }
192
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;
202
203      if (proc.seg != 1) {
204        throw new PdbDebugException("Segment is {0}, not 1.", proc.seg);
205      }
206      if (proc.parent != 0 || proc.next != 0) {
207        throw new PdbDebugException("Warning parent={0}, next={1}",
208                                    proc.parent, proc.next);
209      }
210      if (proc.dbgStart != 0 || proc.dbgEnd != 0) {
211        throw new PdbDebugException("Warning DBG start={0}, end={1}",
212                                    proc.dbgStart, proc.dbgEnd);
213      }
214
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;
222
223      while (bits.Position < proc.end) {
224        ushort siz;
225        ushort rec;
226
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);
232
233        switch ((SYM)rec) {
234          case SYM.S_OEM: {          // 0x0404
235              OemSymbol oem;
236
237              bits.ReadGuid(out oem.idOem);
238              bits.ReadUInt32(out oem.typind);
239              // internal byte[]   rgl;        // user data, force 4-byte alignment
240
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);
252                  }
253                }
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;
260              }
261            }
262
263          case SYM.S_BLOCK32: {
264              BlockSym32 block = new BlockSym32();
265
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;
273
274              scopes[scope] = new PdbScope(block, bits, out slotToken);
275              bits.Position = (int)block.end;
276              break;
277            }
278
279          case SYM.S_UNAMESPACE:
280            bits.Position = stop;
281            break;
282
283          case SYM.S_END:
284            bits.Position = stop;
285            break;
286
287          default: {
288              //throw new PdbDebugException("Unknown SYM: {0}", (SYM)rec);
289              bits.Position = stop;
290              break;
291            }
292        }
293      }
294
295      if (bits.Position != proc.end) {
296        throw new PdbDebugException("Not at S_END");
297      }
298
299      ushort esiz;
300      ushort erec;
301      bits.ReadUInt16(out esiz);
302      bits.ReadUInt16(out erec);
303
304      if (erec != (ushort)SYM.S_END) {
305        throw new PdbDebugException("Missing S_END");
306      }
307    }
308
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);
315      }
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);
328      }
329      bits.Position = savedPosition+(int)numberOfBytesInItem;
330    }
331
332    private void ReadForwardIterator(BitAccess bits) {
333      this.iteratorClass = bits.ReadString();
334    }
335
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));
346      }
347    }
348
349    private void ReadForwardedToModuleInfo(BitAccess bits) {
350    }
351
352    private void ReadForwardInfo(BitAccess bits) {
353    }
354
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]);
361      }
362    }
363
364    internal class PdbFunctionsByAddress : IComparer {
365      public int Compare(Object x, Object y) {
366        PdbFunction fx = (PdbFunction)x;
367        PdbFunction fy = (PdbFunction)y;
368
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;
379        }
380      }
381    }
382
383    internal class PdbFunctionsByToken : IComparer {
384      public int Compare(Object x, Object y) {
385        PdbFunction fx = (PdbFunction)x;
386        PdbFunction fy = (PdbFunction)y;
387
388        if (fx.token < fy.token) {
389          return -1;
390        } else if (fx.token > fy.token) {
391          return 1;
392        } else {
393          return 0;
394        }
395      }
396
397    }
398  }
399}
Note: See TracBrowser for help on using the repository browser.