2
// Mono.CSharp.Debugger/MonoSymbolFile.cs
5
// Martin Baulig (martin@ximian.com)
7
// (C) 2003 Ximian, Inc. http://www.ximian.com
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:
19
// The above copyright notice and this permission notice shall be
20
// included in all copies or substantial portions of the Software.
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.
32
using System.Reflection;
33
using SRE = System.Reflection.Emit;
34
using System.Collections;
36
using System.Threading;
39
namespace Mono.CompilerServices.SymbolWriterOld
41
public class MonoSymbolFileException : Exception
43
public MonoSymbolFileException ()
47
public MonoSymbolFileException (string message, params object[] args)
48
: base (String.Format (message, args))
52
internal class MyBinaryWriter : BinaryWriter
54
public MyBinaryWriter (Stream stream)
58
public void WriteLeb128 (int value)
60
base.Write7BitEncodedInt (value);
64
internal class MyBinaryReader : BinaryReader
66
public MyBinaryReader (Stream stream)
70
public int ReadLeb128 ()
72
return base.Read7BitEncodedInt ();
77
internal class MonoDebuggerSupport
79
static GetMethodTokenFunc get_method_token;
80
static GetGuidFunc get_guid;
81
static GetLocalIndexFunc get_local_index;
83
delegate int GetMethodTokenFunc (MethodBase method);
84
delegate Guid GetGuidFunc (Module module);
85
delegate int GetLocalIndexFunc (SRE.LocalBuilder local);
87
static Delegate create_delegate (Type type, Type delegate_type, string name)
89
MethodInfo mi = type.GetMethod (name, BindingFlags.Static |
90
BindingFlags.NonPublic);
92
throw new Exception ("Can't find " + name);
94
return Delegate.CreateDelegate (delegate_type, mi);
97
static MonoDebuggerSupport ()
99
get_method_token = (GetMethodTokenFunc) create_delegate (
100
typeof (Assembly), typeof (GetMethodTokenFunc),
101
"MonoDebugger_GetMethodToken");
103
get_guid = (GetGuidFunc) create_delegate (
104
typeof (Module), typeof (GetGuidFunc), "Mono_GetGuid");
106
get_local_index = (GetLocalIndexFunc) create_delegate (
107
typeof (SRE.LocalBuilder), typeof (GetLocalIndexFunc),
108
"Mono_GetLocalIndex");
111
public static int GetMethodToken (MethodBase method)
113
return get_method_token (method);
116
public static Guid GetGuid (Module module)
118
return get_guid (module);
121
public static int GetLocalIndex (SRE.LocalBuilder local)
123
return get_local_index (local);
128
public class MonoSymbolFile : IDisposable
130
ArrayList methods = new ArrayList ();
131
ArrayList sources = new ArrayList ();
132
Hashtable method_source_hash = new Hashtable ();
133
Hashtable type_hash = new Hashtable ();
137
int last_method_index;
138
int last_source_index;
139
int last_namespace_index;
141
public int NumLineNumbers;
143
public MonoSymbolFile ()
146
internal int AddSource (SourceFileEntry source)
148
sources.Add (source);
149
return ++last_source_index;
152
internal int DefineType (Type type)
154
if (type_hash.Contains (type))
155
return (int) type_hash [type];
157
int index = ++last_type_index;
158
type_hash.Add (type, index);
162
internal void AddMethod (MethodEntry entry)
167
internal int GetNextTypeIndex ()
169
return ++last_type_index;
172
internal int GetNextMethodIndex ()
174
return ++last_method_index;
177
internal int GetNextNamespaceIndex ()
179
return ++last_namespace_index;
182
internal string ReadString (int offset)
184
int old_pos = (int) reader.BaseStream.Position;
185
reader.BaseStream.Position = offset;
187
string text = reader.ReadString ();
189
reader.BaseStream.Position = old_pos;
193
void Write (MyBinaryWriter bw, Guid guid)
195
// Magic number and file version.
196
bw.Write (OffsetTable.Magic);
197
bw.Write (OffsetTable.Version);
199
bw.Write (guid.ToByteArray ());
202
// Offsets of file sections; we must write this after we're done
203
// writing the whole file, so we just reserve the space for it here.
205
long offset_table_offset = bw.BaseStream.Position;
209
// Sort the methods according to their tokens and update their index.
212
for (int i = 0; i < methods.Count; i++)
213
((MethodEntry) methods [i]).Index = i + 1;
216
// Write data sections.
218
ot.DataSectionOffset = (int) bw.BaseStream.Position;
219
foreach (SourceFileEntry source in sources)
220
source.WriteData (bw);
221
ot.DataSectionSize = (int) bw.BaseStream.Position - ot.DataSectionOffset;
224
// Write the method index table.
226
ot.MethodTableOffset = (int) bw.BaseStream.Position;
227
for (int i = 0; i < methods.Count; i++) {
228
MethodEntry entry = (MethodEntry) methods [i];
229
entry.WriteIndex (bw);
231
ot.MethodTableSize = (int) bw.BaseStream.Position - ot.MethodTableOffset;
234
// Write source table.
236
ot.SourceTableOffset = (int) bw.BaseStream.Position;
237
for (int i = 0; i < sources.Count; i++) {
238
SourceFileEntry source = (SourceFileEntry) sources [i];
241
ot.SourceTableSize = (int) bw.BaseStream.Position - ot.SourceTableOffset;
244
// Fixup offset table.
246
ot.TypeCount = last_type_index;
247
ot.MethodCount = methods.Count;
248
ot.SourceCount = sources.Count;
251
// Write offset table.
253
ot.TotalFileSize = (int) bw.BaseStream.Position;
254
bw.Seek ((int) offset_table_offset, SeekOrigin.Begin);
256
bw.Seek (0, SeekOrigin.End);
259
public void CreateSymbolFile (Guid guid, FileStream fs)
262
throw new InvalidOperationException ();
264
Write (new MyBinaryWriter (fs), guid);
267
MyBinaryReader reader;
268
Hashtable method_hash;
269
Hashtable source_file_hash;
271
Hashtable method_token_hash;
272
Hashtable source_name_hash;
276
MonoSymbolFile (string filename)
278
FileStream stream = new FileStream (filename, FileMode.Open, FileAccess.Read);
279
reader = new MyBinaryReader (stream);
282
long magic = reader.ReadInt64 ();
283
long version = reader.ReadInt32 ();
284
if (magic != OffsetTable.Magic)
285
throw new MonoSymbolFileException (
286
"Symbol file `{0}' is not a valid " +
287
"Mono symbol file", filename);
288
if (version != OffsetTable.Version)
289
throw new MonoSymbolFileException (
290
"Symbol file `{0}' has version {1}, " +
291
"but expected {2}", filename, version,
292
OffsetTable.Version);
294
guid = new Guid (reader.ReadBytes (16));
296
ot = new OffsetTable (reader);
298
throw new MonoSymbolFileException (
299
"Cannot read symbol file `{0}'", filename);
302
method_hash = new Hashtable ();
303
source_file_hash = new Hashtable ();
306
void CheckGuidMatch (Guid other, string filename, string assembly)
311
throw new MonoSymbolFileException (
312
"Symbol file `{0}' does not match assembly `{1}'",
317
protected MonoSymbolFile (string filename, Mono.Cecil.AssemblyDefinition assembly) : this (filename)
319
Guid mvid = assembly.MainModule.Mvid;
321
CheckGuidMatch (mvid, filename, assembly.MainModule.Image.FileInformation.FullName);
324
public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.AssemblyDefinition assembly, string filename)
326
string name = filename + ".mdb";
328
return new MonoSymbolFile (name, assembly);
331
protected MonoSymbolFile (string filename, Assembly assembly) : this (filename)
333
// Check that the MDB file matches the assembly, if we have been
334
// passed an assembly.
335
if (assembly == null)
338
Module[] modules = assembly.GetModules ();
339
Guid assembly_guid = MonoDebuggerSupport.GetGuid (modules [0]);
341
CheckGuidMatch (assembly_guid, filename, assembly.Location);
344
public static MonoSymbolFile ReadSymbolFile (Assembly assembly)
346
string filename = assembly.Location;
347
string name = filename + ".mdb";
349
return new MonoSymbolFile (name, assembly);
353
public static MonoSymbolFile ReadSymbolFile (string mdbFilename)
355
return new MonoSymbolFile (mdbFilename, null);
358
public int SourceCount {
359
get { return ot.SourceCount; }
362
public int MethodCount {
363
get { return ot.MethodCount; }
366
public int TypeCount {
367
get { return ot.TypeCount; }
370
public int NamespaceCount {
371
get { return last_namespace_index; }
378
internal int LineNumberCount = 0;
379
internal int LocalCount = 0;
380
internal int StringSize = 0;
382
public SourceFileEntry GetSourceFile (int index)
384
if ((index < 1) || (index > ot.SourceCount))
385
throw new ArgumentException ();
387
throw new InvalidOperationException ();
389
SourceFileEntry source = (SourceFileEntry) source_file_hash [index];
393
reader.BaseStream.Position = ot.SourceTableOffset +
394
SourceFileEntry.Size * (index - 1);
395
source = new SourceFileEntry (this, reader);
396
source_file_hash.Add (index, source);
400
public SourceFileEntry[] Sources {
403
throw new InvalidOperationException ();
405
SourceFileEntry[] retval = new SourceFileEntry [SourceCount];
406
for (int i = 0; i < SourceCount; i++)
407
retval [i] = GetSourceFile (i + 1);
412
public MethodIndexEntry GetMethodIndexEntry (int index)
414
int old_pos = (int) reader.BaseStream.Position;
415
reader.BaseStream.Position = ot.MethodTableOffset +
416
MethodIndexEntry.Size * (index - 1);
417
MethodIndexEntry ie = new MethodIndexEntry (reader);
418
reader.BaseStream.Position = old_pos;
422
public MethodEntry GetMethodByToken (int token)
425
throw new InvalidOperationException ();
427
if (method_token_hash == null) {
428
method_token_hash = new Hashtable ();
430
for (int i = 0; i < MethodCount; i++) {
431
MethodIndexEntry ie = GetMethodIndexEntry (i + 1);
433
method_token_hash.Add (ie.Token, i + 1);
437
object value = method_token_hash [token];
441
return GetMethod ((int) value);
445
public MethodEntry GetMethod (MethodBase method)
448
throw new InvalidOperationException ();
449
int token = MonoDebuggerSupport.GetMethodToken (method);
450
return GetMethodByToken (token);
454
public MethodEntry GetMethod (int index)
456
if ((index < 1) || (index > ot.MethodCount))
457
throw new ArgumentException ();
459
throw new InvalidOperationException ();
461
MethodEntry entry = (MethodEntry) method_hash [index];
465
MethodIndexEntry ie = GetMethodIndexEntry (index);
466
reader.BaseStream.Position = ie.FileOffset;
468
entry = new MethodEntry (this, reader, index);
469
method_hash.Add (index, entry);
473
public MethodEntry[] Methods {
476
throw new InvalidOperationException ();
478
MethodEntry[] retval = new MethodEntry [MethodCount];
479
for (int i = 0; i < MethodCount; i++)
480
retval [i] = GetMethod (i + 1);
485
public MethodSourceEntry GetMethodSource (int index)
487
if ((index < 1) || (index > ot.MethodCount))
488
throw new ArgumentException ();
490
throw new InvalidOperationException ();
492
object entry = method_source_hash [index];
494
return (MethodSourceEntry) entry;
496
MethodEntry method = GetMethod (index);
497
foreach (MethodSourceEntry source in method.SourceFile.Methods) {
498
if (source.Index == index) {
499
method_source_hash.Add (index, source);
504
throw new MonoSymbolFileException ("Internal error.");
507
public int FindSource (string file_name)
510
throw new InvalidOperationException ();
512
if (source_name_hash == null) {
513
source_name_hash = new Hashtable ();
515
for (int i = 0; i < ot.SourceCount; i++) {
516
SourceFileEntry source = GetSourceFile (i + 1);
518
source_name_hash.Add (source.FileName, i);
522
object value = source_name_hash [file_name];
528
internal MyBinaryReader BinaryReader {
531
throw new InvalidOperationException ();
537
public void Dispose ()
542
protected virtual void Dispose (bool disposing)
545
if (reader != null) {