~ubuntu-branches/ubuntu/oneiric/cecil/oneiric

« back to all changes in this revision

Viewing changes to symbols/mdb/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane, Iain Lane, Jo Shields
  • Date: 2011-08-07 22:38:20 UTC
  • mfrom: (1.1.7 upstream) (6.1.6 experimental)
  • Revision ID: james.westby@ubuntu.com-20110807223820-nfdm4q0pk2smjm11
Tags: 0.9.5+dfsg-1
[ Iain Lane ]
* [411dc78] Update to use my d.o email address
* [74bedaf] Disable clilibs; this is an unstable library
  apps grow unnecessary depends otherwise
* [5288c1f] Mangle debian version in watch file to take care of repacking.
  Also update watch file to look at new github location for tarballs
* [8f7110f] Relax version restriction on cli-common-dev; anything from 0.8
  will do

[ Jo Shields ]
* [e846eb8] Imported Upstream version 0.9.5+dfsg
* [3017d96] Bump build dependencies, as we're building for Mono 2.10 now.
* [27c2cff] Set to DebSrc 3.0, so we can apply patches via Quilt.
* [d0447b3] Update build to use XBuild, not manual compiler invocation.
* [08d2b92] Patch to avoid building tests (which rely on NUnit 2.4)
* [fa5a033] Update install file to include all new assemblies and locations.
* [43bd1e2] Since upstream no longer ships a pcfile, add our own.
* [942ead4] Don't try to ship a Changelog when none exists.
* [ba8232d] Erase obj/ folders in clean rule.
* [090af34] Exclude modulerefs on Windowsy libraries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// Mono.CSharp.Debugger/MonoSymbolFile.cs
 
3
//
 
4
// Author:
 
5
//   Martin Baulig (martin@ximian.com)
 
6
//
 
7
// (C) 2003 Ximian, Inc.  http://www.ximian.com
 
8
//
 
9
 
 
10
//
 
11
// Permission is hereby granted, free of charge, to any person obtaining
 
12
// a copy of this software and associated documentation files (the
 
13
// "Software"), to deal in the Software without restriction, including
 
14
// without limitation the rights to use, copy, modify, merge, publish,
 
15
// distribute, sublicense, and/or sell copies of the Software, and to
 
16
// permit persons to whom the Software is furnished to do so, subject to
 
17
// the following conditions:
 
18
//
 
19
// The above copyright notice and this permission notice shall be
 
20
// included in all copies or substantial portions of the Software.
 
21
//
 
22
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
23
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
24
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
25
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 
26
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
27
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
28
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
29
//
 
30
 
 
31
using System;
 
32
using System.Reflection;
 
33
using SRE = System.Reflection.Emit;
 
34
using System.Collections.Generic;
 
35
using System.Text;
 
36
using System.Threading;
 
37
using System.IO;
 
38
 
 
39
namespace Mono.CompilerServices.SymbolWriter
 
40
{
 
41
        public class MonoSymbolFileException : Exception
 
42
        {
 
43
                public MonoSymbolFileException ()
 
44
                        : base ()
 
45
                { }
 
46
 
 
47
                public MonoSymbolFileException (string message, params object[] args)
 
48
                        : base (String.Format (message, args))
 
49
                { }
 
50
        }
 
51
 
 
52
        internal class MyBinaryWriter : BinaryWriter
 
53
        {
 
54
                public MyBinaryWriter (Stream stream)
 
55
                        : base (stream)
 
56
                { }
 
57
 
 
58
                public void WriteLeb128 (int value)
 
59
                {
 
60
                        base.Write7BitEncodedInt (value);
 
61
                }
 
62
        }
 
63
 
 
64
        internal class MyBinaryReader : BinaryReader
 
65
        {
 
66
                public MyBinaryReader (Stream stream)
 
67
                        : base (stream)
 
68
                { }
 
69
 
 
70
                public int ReadLeb128 ()
 
71
                {
 
72
                        return base.Read7BitEncodedInt ();
 
73
                }
 
74
 
 
75
                public string ReadString (int offset)
 
76
                {
 
77
                        long old_pos = BaseStream.Position;
 
78
                        BaseStream.Position = offset;
 
79
 
 
80
                        string text = ReadString ();
 
81
 
 
82
                        BaseStream.Position = old_pos;
 
83
                        return text;
 
84
                }
 
85
        }
 
86
 
 
87
        public interface ISourceFile
 
88
        {
 
89
                SourceFileEntry Entry {
 
90
                        get;
 
91
                }
 
92
        }
 
93
 
 
94
        public interface ICompileUnit
 
95
        {
 
96
                CompileUnitEntry Entry {
 
97
                        get;
 
98
                }
 
99
        }
 
100
 
 
101
        public interface IMethodDef
 
102
        {
 
103
                string Name {
 
104
                        get;
 
105
                }
 
106
 
 
107
                int Token {
 
108
                        get;
 
109
                }
 
110
        }
 
111
 
 
112
#if !CECIL
 
113
        internal class MonoDebuggerSupport
 
114
        {
 
115
                static GetMethodTokenFunc get_method_token;
 
116
                static GetGuidFunc get_guid;
 
117
                static GetLocalIndexFunc get_local_index;
 
118
 
 
119
                delegate int GetMethodTokenFunc (MethodBase method);
 
120
                delegate Guid GetGuidFunc (Module module);
 
121
                delegate int GetLocalIndexFunc (SRE.LocalBuilder local);
 
122
 
 
123
                static Delegate create_delegate (Type type, Type delegate_type, string name)
 
124
                {
 
125
                        MethodInfo mi = type.GetMethod (name, BindingFlags.Static |
 
126
                                                        BindingFlags.NonPublic);
 
127
                        if (mi == null)
 
128
                                throw new Exception ("Can't find " + name);
 
129
 
 
130
                        return Delegate.CreateDelegate (delegate_type, mi);
 
131
                }
 
132
 
 
133
                static MonoDebuggerSupport ()
 
134
                {
 
135
                        get_method_token = (GetMethodTokenFunc) create_delegate (
 
136
                                typeof (Assembly), typeof (GetMethodTokenFunc),
 
137
                                "MonoDebugger_GetMethodToken");
 
138
 
 
139
                        get_guid = (GetGuidFunc) create_delegate (
 
140
                                typeof (Module), typeof (GetGuidFunc), "Mono_GetGuid");
 
141
 
 
142
                        get_local_index = (GetLocalIndexFunc) create_delegate (
 
143
                                typeof (SRE.LocalBuilder), typeof (GetLocalIndexFunc),
 
144
                                "Mono_GetLocalIndex");
 
145
                }
 
146
 
 
147
                public static int GetMethodToken (MethodBase method)
 
148
                {
 
149
                        return get_method_token (method);
 
150
                }
 
151
 
 
152
                public static Guid GetGuid (Module module)
 
153
                {
 
154
                        return get_guid (module);
 
155
                }
 
156
 
 
157
                public static int GetLocalIndex (SRE.LocalBuilder local)
 
158
                {
 
159
                        return get_local_index (local);
 
160
                }
 
161
        }
 
162
#endif
 
163
 
 
164
        public class MonoSymbolFile : IDisposable
 
165
        {
 
166
                List<MethodEntry> methods = new List<MethodEntry> ();
 
167
                List<SourceFileEntry> sources = new List<SourceFileEntry> ();
 
168
                List<CompileUnitEntry> comp_units = new List<CompileUnitEntry> ();
 
169
                Dictionary<Type, int> type_hash = new Dictionary<Type, int> ();
 
170
                Dictionary<int, AnonymousScopeEntry> anonymous_scopes;
 
171
 
 
172
                OffsetTable ot;
 
173
                int last_type_index;
 
174
                int last_method_index;
 
175
                int last_namespace_index;
 
176
 
 
177
                public readonly string FileName = "<dynamic>";
 
178
                public readonly int MajorVersion = OffsetTable.MajorVersion;
 
179
                public readonly int MinorVersion = OffsetTable.MinorVersion;
 
180
 
 
181
                public int NumLineNumbers;
 
182
 
 
183
                internal MonoSymbolFile ()
 
184
                {
 
185
                        ot = new OffsetTable ();
 
186
                }
 
187
 
 
188
                internal int AddSource (SourceFileEntry source)
 
189
                {
 
190
                        sources.Add (source);
 
191
                        return sources.Count;
 
192
                }
 
193
 
 
194
                internal int AddCompileUnit (CompileUnitEntry entry)
 
195
                {
 
196
                        comp_units.Add (entry);
 
197
                        return comp_units.Count;
 
198
                }
 
199
 
 
200
                internal int DefineType (Type type)
 
201
                {
 
202
                        int index;
 
203
                        if (type_hash.TryGetValue (type, out index))
 
204
                                return index;
 
205
 
 
206
                        index = ++last_type_index;
 
207
                        type_hash.Add (type, index);
 
208
                        return index;
 
209
                }
 
210
 
 
211
                internal void AddMethod (MethodEntry entry)
 
212
                {
 
213
                        methods.Add (entry);
 
214
                }
 
215
 
 
216
                public MethodEntry DefineMethod (CompileUnitEntry comp_unit, int token,
 
217
                                                 ScopeVariable[] scope_vars, LocalVariableEntry[] locals,
 
218
                                                 LineNumberEntry[] lines, CodeBlockEntry[] code_blocks,
 
219
                                                 string real_name, MethodEntry.Flags flags,
 
220
                                                 int namespace_id)
 
221
                {
 
222
                        if (reader != null)
 
223
                                throw new InvalidOperationException ();
 
224
 
 
225
                        MethodEntry method = new MethodEntry (
 
226
                                this, comp_unit, token, scope_vars, locals, lines, code_blocks,
 
227
                                real_name, flags, namespace_id);
 
228
                        AddMethod (method);
 
229
                        return method;
 
230
                }
 
231
 
 
232
                internal void DefineAnonymousScope (int id)
 
233
                {
 
234
                        if (reader != null)
 
235
                                throw new InvalidOperationException ();
 
236
 
 
237
                        if (anonymous_scopes == null)
 
238
                                anonymous_scopes = new Dictionary<int, AnonymousScopeEntry>  ();
 
239
 
 
240
                        anonymous_scopes.Add (id, new AnonymousScopeEntry (id));
 
241
                }
 
242
 
 
243
                internal void DefineCapturedVariable (int scope_id, string name, string captured_name,
 
244
                                                      CapturedVariable.CapturedKind kind)
 
245
                {
 
246
                        if (reader != null)
 
247
                                throw new InvalidOperationException ();
 
248
 
 
249
                        AnonymousScopeEntry scope = anonymous_scopes [scope_id];
 
250
                        scope.AddCapturedVariable (name, captured_name, kind);
 
251
                }
 
252
 
 
253
                internal void DefineCapturedScope (int scope_id, int id, string captured_name)
 
254
                {
 
255
                        if (reader != null)
 
256
                                throw new InvalidOperationException ();
 
257
 
 
258
                        AnonymousScopeEntry scope = anonymous_scopes [scope_id];
 
259
                        scope.AddCapturedScope (id, captured_name);
 
260
                }
 
261
 
 
262
                internal int GetNextTypeIndex ()
 
263
                {
 
264
                        return ++last_type_index;
 
265
                }
 
266
 
 
267
                internal int GetNextMethodIndex ()
 
268
                {
 
269
                        return ++last_method_index;
 
270
                }
 
271
 
 
272
                internal int GetNextNamespaceIndex ()
 
273
                {
 
274
                        return ++last_namespace_index;
 
275
                }
 
276
 
 
277
                void Write (MyBinaryWriter bw, Guid guid)
 
278
                {
 
279
                        // Magic number and file version.
 
280
                        bw.Write (OffsetTable.Magic);
 
281
                        bw.Write (MajorVersion);
 
282
                        bw.Write (MinorVersion);
 
283
 
 
284
                        bw.Write (guid.ToByteArray ());
 
285
 
 
286
                        //
 
287
                        // Offsets of file sections; we must write this after we're done
 
288
                        // writing the whole file, so we just reserve the space for it here.
 
289
                        //
 
290
                        long offset_table_offset = bw.BaseStream.Position;
 
291
                        ot.Write (bw, MajorVersion, MinorVersion);
 
292
 
 
293
                        //
 
294
                        // Sort the methods according to their tokens and update their index.
 
295
                        //
 
296
                        methods.Sort ();
 
297
                        for (int i = 0; i < methods.Count; i++)
 
298
                                ((MethodEntry) methods [i]).Index = i + 1;
 
299
 
 
300
                        //
 
301
                        // Write data sections.
 
302
                        //
 
303
                        ot.DataSectionOffset = (int) bw.BaseStream.Position;
 
304
                        foreach (SourceFileEntry source in sources)
 
305
                                source.WriteData (bw);
 
306
                        foreach (CompileUnitEntry comp_unit in comp_units)
 
307
                                comp_unit.WriteData (bw);
 
308
                        foreach (MethodEntry method in methods)
 
309
                                method.WriteData (this, bw);
 
310
                        ot.DataSectionSize = (int) bw.BaseStream.Position - ot.DataSectionOffset;
 
311
 
 
312
                        //
 
313
                        // Write the method index table.
 
314
                        //
 
315
                        ot.MethodTableOffset = (int) bw.BaseStream.Position;
 
316
                        for (int i = 0; i < methods.Count; i++) {
 
317
                                MethodEntry entry = (MethodEntry) methods [i];
 
318
                                entry.Write (bw);
 
319
                        }
 
320
                        ot.MethodTableSize = (int) bw.BaseStream.Position - ot.MethodTableOffset;
 
321
 
 
322
                        //
 
323
                        // Write source table.
 
324
                        //
 
325
                        ot.SourceTableOffset = (int) bw.BaseStream.Position;
 
326
                        for (int i = 0; i < sources.Count; i++) {
 
327
                                SourceFileEntry source = (SourceFileEntry) sources [i];
 
328
                                source.Write (bw);
 
329
                        }
 
330
                        ot.SourceTableSize = (int) bw.BaseStream.Position - ot.SourceTableOffset;
 
331
 
 
332
                        //
 
333
                        // Write compilation unit table.
 
334
                        //
 
335
                        ot.CompileUnitTableOffset = (int) bw.BaseStream.Position;
 
336
                        for (int i = 0; i < comp_units.Count; i++) {
 
337
                                CompileUnitEntry unit = (CompileUnitEntry) comp_units [i];
 
338
                                unit.Write (bw);
 
339
                        }
 
340
                        ot.CompileUnitTableSize = (int) bw.BaseStream.Position - ot.CompileUnitTableOffset;
 
341
 
 
342
                        //
 
343
                        // Write anonymous scope table.
 
344
                        //
 
345
                        ot.AnonymousScopeCount = anonymous_scopes != null ? anonymous_scopes.Count : 0;
 
346
                        ot.AnonymousScopeTableOffset = (int) bw.BaseStream.Position;
 
347
                        if (anonymous_scopes != null) {
 
348
                                foreach (AnonymousScopeEntry scope in anonymous_scopes.Values)
 
349
                                        scope.Write (bw);
 
350
                        }
 
351
                        ot.AnonymousScopeTableSize = (int) bw.BaseStream.Position - ot.AnonymousScopeTableOffset;
 
352
 
 
353
                        //
 
354
                        // Fixup offset table.
 
355
                        //
 
356
                        ot.TypeCount = last_type_index;
 
357
                        ot.MethodCount = methods.Count;
 
358
                        ot.SourceCount = sources.Count;
 
359
                        ot.CompileUnitCount = comp_units.Count;
 
360
 
 
361
                        //
 
362
                        // Write offset table.
 
363
                        //
 
364
                        ot.TotalFileSize = (int) bw.BaseStream.Position;
 
365
                        bw.Seek ((int) offset_table_offset, SeekOrigin.Begin);
 
366
                        ot.Write (bw, MajorVersion, MinorVersion);
 
367
                        bw.Seek (0, SeekOrigin.End);
 
368
 
 
369
#if false
 
370
                        Console.WriteLine ("TOTAL: {0} line numbes, {1} bytes, extended {2} bytes, " +
 
371
                                           "{3} methods.", NumLineNumbers, LineNumberSize,
 
372
                                           ExtendedLineNumberSize, methods.Count);
 
373
#endif
 
374
                }
 
375
 
 
376
                public void CreateSymbolFile (Guid guid, FileStream fs)
 
377
                {
 
378
                        if (reader != null)
 
379
                                throw new InvalidOperationException ();
 
380
 
 
381
                        Write (new MyBinaryWriter (fs), guid);
 
382
                }
 
383
 
 
384
                MyBinaryReader reader;
 
385
                Dictionary<int, SourceFileEntry> source_file_hash;
 
386
                Dictionary<int, CompileUnitEntry> compile_unit_hash;
 
387
 
 
388
                List<MethodEntry> method_list;
 
389
                Dictionary<int, MethodEntry> method_token_hash;
 
390
                Dictionary<string, int> source_name_hash;
 
391
 
 
392
                Guid guid;
 
393
 
 
394
                MonoSymbolFile (string filename)
 
395
                {
 
396
                        this.FileName = filename;
 
397
                        FileStream stream = new FileStream (filename, FileMode.Open, FileAccess.Read);
 
398
                        reader = new MyBinaryReader (stream);
 
399
 
 
400
                        try {
 
401
                                long magic = reader.ReadInt64 ();
 
402
                                int major_version = reader.ReadInt32 ();
 
403
                                int minor_version = reader.ReadInt32 ();
 
404
 
 
405
                                if (magic != OffsetTable.Magic)
 
406
                                        throw new MonoSymbolFileException (
 
407
                                                "Symbol file `{0}' is not a valid " +
 
408
                                                "Mono symbol file", filename);
 
409
                                if (major_version != OffsetTable.MajorVersion)
 
410
                                        throw new MonoSymbolFileException (
 
411
                                                "Symbol file `{0}' has version {1}, " +
 
412
                                                "but expected {2}", filename, major_version,
 
413
                                                OffsetTable.MajorVersion);
 
414
                                if (minor_version != OffsetTable.MinorVersion)
 
415
                                        throw new MonoSymbolFileException (
 
416
                                                "Symbol file `{0}' has version {1}.{2}, " +
 
417
                                                "but expected {3}.{4}", filename, major_version,
 
418
                                                minor_version, OffsetTable.MajorVersion,
 
419
                                                OffsetTable.MinorVersion);
 
420
 
 
421
                                MajorVersion = major_version;
 
422
                                MinorVersion = minor_version;
 
423
                                guid = new Guid (reader.ReadBytes (16));
 
424
 
 
425
                                ot = new OffsetTable (reader, major_version, minor_version);
 
426
                        } catch {
 
427
                                throw new MonoSymbolFileException (
 
428
                                        "Cannot read symbol file `{0}'", filename);
 
429
                        }
 
430
 
 
431
                        source_file_hash = new Dictionary<int, SourceFileEntry> ();
 
432
                        compile_unit_hash = new Dictionary<int, CompileUnitEntry> ();
 
433
                }
 
434
 
 
435
                void CheckGuidMatch (Guid other, string filename, string assembly)
 
436
                {
 
437
                        if (other == guid)
 
438
                                return;
 
439
 
 
440
                        throw new MonoSymbolFileException (
 
441
                                "Symbol file `{0}' does not match assembly `{1}'",
 
442
                                filename, assembly);
 
443
                }
 
444
 
 
445
#if CECIL
 
446
                protected MonoSymbolFile (string filename, Mono.Cecil.ModuleDefinition module)
 
447
                        : this (filename)
 
448
                {
 
449
                        CheckGuidMatch (module.Mvid, filename, module.FullyQualifiedName);
 
450
                }
 
451
 
 
452
                public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module)
 
453
                {
 
454
                        return ReadSymbolFile (module, module.FullyQualifiedName);
 
455
                }
 
456
 
 
457
                public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module, string filename)
 
458
                {
 
459
                        string name = filename + ".mdb";
 
460
 
 
461
                        return new MonoSymbolFile (name, module);
 
462
                }
 
463
#else
 
464
                protected MonoSymbolFile (string filename, Assembly assembly) : this (filename)
 
465
                {
 
466
                        // Check that the MDB file matches the assembly, if we have been
 
467
                        // passed an assembly.
 
468
                        if (assembly == null)
 
469
                                return;
 
470
 
 
471
                        Module[] modules = assembly.GetModules ();
 
472
                        Guid assembly_guid = MonoDebuggerSupport.GetGuid (modules [0]);
 
473
 
 
474
                        CheckGuidMatch (assembly_guid, filename, assembly.Location);
 
475
                }
 
476
 
 
477
                public static MonoSymbolFile ReadSymbolFile (Assembly assembly)
 
478
                {
 
479
                        string filename = assembly.Location;
 
480
                        string name = filename + ".mdb";
 
481
 
 
482
                        return new MonoSymbolFile (name, assembly);
 
483
                }
 
484
#endif
 
485
 
 
486
                public static MonoSymbolFile ReadSymbolFile (string mdbFilename)
 
487
                {
 
488
                        return new MonoSymbolFile (mdbFilename, null);
 
489
                }
 
490
 
 
491
                public int CompileUnitCount {
 
492
                        get { return ot.CompileUnitCount; }
 
493
                }
 
494
 
 
495
                public int SourceCount {
 
496
                        get { return ot.SourceCount; }
 
497
                }
 
498
 
 
499
                public int MethodCount {
 
500
                        get { return ot.MethodCount; }
 
501
                }
 
502
 
 
503
                public int TypeCount {
 
504
                        get { return ot.TypeCount; }
 
505
                }
 
506
 
 
507
                public int AnonymousScopeCount {
 
508
                        get { return ot.AnonymousScopeCount; }
 
509
                }
 
510
 
 
511
                public int NamespaceCount {
 
512
                        get { return last_namespace_index; }
 
513
                }
 
514
 
 
515
                public Guid Guid {
 
516
                        get { return guid; }
 
517
                }
 
518
 
 
519
                public OffsetTable OffsetTable {
 
520
                        get { return ot; }
 
521
                }
 
522
 
 
523
                internal int LineNumberCount = 0;
 
524
                internal int LocalCount = 0;
 
525
                internal int StringSize = 0;
 
526
 
 
527
                internal int LineNumberSize = 0;
 
528
                internal int ExtendedLineNumberSize = 0;
 
529
 
 
530
                public SourceFileEntry GetSourceFile (int index)
 
531
                {
 
532
                        if ((index < 1) || (index > ot.SourceCount))
 
533
                                throw new ArgumentException ();
 
534
                        if (reader == null)
 
535
                                throw new InvalidOperationException ();
 
536
 
 
537
                        lock (this) {
 
538
                                SourceFileEntry source;
 
539
                                if (source_file_hash.TryGetValue (index, out source))
 
540
                                        return source;
 
541
 
 
542
                                long old_pos = reader.BaseStream.Position;
 
543
 
 
544
                                reader.BaseStream.Position = ot.SourceTableOffset +
 
545
                                        SourceFileEntry.Size * (index - 1);
 
546
                                source = new SourceFileEntry (this, reader);
 
547
                                source_file_hash.Add (index, source);
 
548
 
 
549
                                reader.BaseStream.Position = old_pos;
 
550
                                return source;
 
551
                        }
 
552
                }
 
553
 
 
554
                public SourceFileEntry[] Sources {
 
555
                        get {
 
556
                                if (reader == null)
 
557
                                        throw new InvalidOperationException ();
 
558
 
 
559
                                SourceFileEntry[] retval = new SourceFileEntry [SourceCount];
 
560
                                for (int i = 0; i < SourceCount; i++)
 
561
                                        retval [i] = GetSourceFile (i + 1);
 
562
                                return retval;
 
563
                        }
 
564
                }
 
565
 
 
566
                public CompileUnitEntry GetCompileUnit (int index)
 
567
                {
 
568
                        if ((index < 1) || (index > ot.CompileUnitCount))
 
569
                                throw new ArgumentException ();
 
570
                        if (reader == null)
 
571
                                throw new InvalidOperationException ();
 
572
 
 
573
                        lock (this) {
 
574
                                CompileUnitEntry unit;
 
575
                                if (compile_unit_hash.TryGetValue (index, out unit))
 
576
                                        return unit;
 
577
 
 
578
                                long old_pos = reader.BaseStream.Position;
 
579
 
 
580
                                reader.BaseStream.Position = ot.CompileUnitTableOffset +
 
581
                                        CompileUnitEntry.Size * (index - 1);
 
582
                                unit = new CompileUnitEntry (this, reader);
 
583
                                compile_unit_hash.Add (index, unit);
 
584
 
 
585
                                reader.BaseStream.Position = old_pos;
 
586
                                return unit;
 
587
                        }
 
588
                }
 
589
 
 
590
                public CompileUnitEntry[] CompileUnits {
 
591
                        get {
 
592
                                if (reader == null)
 
593
                                        throw new InvalidOperationException ();
 
594
 
 
595
                                CompileUnitEntry[] retval = new CompileUnitEntry [CompileUnitCount];
 
596
                                for (int i = 0; i < CompileUnitCount; i++)
 
597
                                        retval [i] = GetCompileUnit (i + 1);
 
598
                                return retval;
 
599
                        }
 
600
                }
 
601
 
 
602
                void read_methods ()
 
603
                {
 
604
                        lock (this) {
 
605
                                if (method_token_hash != null)
 
606
                                        return;
 
607
 
 
608
                                method_token_hash = new Dictionary<int, MethodEntry> ();
 
609
                                method_list = new List<MethodEntry> ();
 
610
 
 
611
                                long old_pos = reader.BaseStream.Position;
 
612
                                reader.BaseStream.Position = ot.MethodTableOffset;
 
613
 
 
614
                                for (int i = 0; i < MethodCount; i++) {
 
615
                                        MethodEntry entry = new MethodEntry (this, reader, i + 1);
 
616
                                        method_token_hash.Add (entry.Token, entry);
 
617
                                        method_list.Add (entry);
 
618
                                }
 
619
 
 
620
                                reader.BaseStream.Position = old_pos;
 
621
                        }
 
622
                }
 
623
 
 
624
                public MethodEntry GetMethodByToken (int token)
 
625
                {
 
626
                        if (reader == null)
 
627
                                throw new InvalidOperationException ();
 
628
 
 
629
                        lock (this) {
 
630
                                read_methods ();
 
631
                                MethodEntry me;
 
632
                                method_token_hash.TryGetValue (token, out me);
 
633
                                return me;
 
634
                        }
 
635
                }
 
636
 
 
637
                public MethodEntry GetMethod (int index)
 
638
                {
 
639
                        if ((index < 1) || (index > ot.MethodCount))
 
640
                                throw new ArgumentException ();
 
641
                        if (reader == null)
 
642
                                throw new InvalidOperationException ();
 
643
 
 
644
                        lock (this) {
 
645
                                read_methods ();
 
646
                                return (MethodEntry) method_list [index - 1];
 
647
                        }
 
648
                }
 
649
 
 
650
                public MethodEntry[] Methods {
 
651
                        get {
 
652
                                if (reader == null)
 
653
                                        throw new InvalidOperationException ();
 
654
 
 
655
                                lock (this) {
 
656
                                        read_methods ();
 
657
                                        MethodEntry[] retval = new MethodEntry [MethodCount];
 
658
                                        method_list.CopyTo (retval, 0);
 
659
                                        return retval;
 
660
                                }
 
661
                        }
 
662
                }
 
663
 
 
664
                public int FindSource (string file_name)
 
665
                {
 
666
                        if (reader == null)
 
667
                                throw new InvalidOperationException ();
 
668
 
 
669
                        lock (this) {
 
670
                                if (source_name_hash == null) {
 
671
                                        source_name_hash = new Dictionary<string, int> ();
 
672
 
 
673
                                        for (int i = 0; i < ot.SourceCount; i++) {
 
674
                                                SourceFileEntry source = GetSourceFile (i + 1);
 
675
                                                source_name_hash.Add (source.FileName, i);
 
676
                                        }
 
677
                                }
 
678
 
 
679
                                int value;
 
680
                                if (!source_name_hash.TryGetValue (file_name, out value))
 
681
                                        return -1;
 
682
                                return value;
 
683
                        }
 
684
                }
 
685
 
 
686
                public AnonymousScopeEntry GetAnonymousScope (int id)
 
687
                {
 
688
                        if (reader == null)
 
689
                                throw new InvalidOperationException ();
 
690
 
 
691
                        AnonymousScopeEntry scope;
 
692
                        lock (this) {
 
693
                                if (anonymous_scopes != null) {
 
694
                                        anonymous_scopes.TryGetValue (id, out scope);
 
695
                                        return scope;
 
696
                                }
 
697
 
 
698
                                anonymous_scopes = new Dictionary<int, AnonymousScopeEntry> ();
 
699
                                reader.BaseStream.Position = ot.AnonymousScopeTableOffset;
 
700
                                for (int i = 0; i < ot.AnonymousScopeCount; i++) {
 
701
                                        scope = new AnonymousScopeEntry (reader);
 
702
                                        anonymous_scopes.Add (scope.ID, scope);
 
703
                                }
 
704
 
 
705
                                return anonymous_scopes [id];
 
706
                        }
 
707
                }
 
708
 
 
709
                internal MyBinaryReader BinaryReader {
 
710
                        get {
 
711
                                if (reader == null)
 
712
                                        throw new InvalidOperationException ();
 
713
 
 
714
                                return reader;
 
715
                        }
 
716
                }
 
717
 
 
718
                public void Dispose ()
 
719
                {
 
720
                        Dispose (true);
 
721
                }
 
722
 
 
723
                protected virtual void Dispose (bool disposing)
 
724
                {
 
725
                        if (disposing) {
 
726
                                if (reader != null) {
 
727
                                        reader.Close ();
 
728
                                        reader = null;
 
729
                                }
 
730
                        }
 
731
                }
 
732
        }
 
733
}