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
) {