2 // System.Diagnostics.SymbolStore/MonoSymbolFile.cs
5 // Martin Baulig (martin@gnome.org)
7 // (C) 2003 Ximian, Inc. http://www.ximian.com
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Collections;
17 namespace Mono.CSharp.Debugger
19 public class MonoSymbolFileException : Exception
21 public MonoSymbolFileException ()
25 public MonoSymbolFileException (string message, params object[] args)
26 : base (String.Format (message, args))
30 public class MonoSymbolFile : IDisposable
32 ArrayList methods = new ArrayList ();
33 ArrayList sources = new ArrayList ();
34 Hashtable source_hash = new Hashtable ();
35 Hashtable type_hash = new Hashtable ();
39 int last_method_index;
41 public MonoSymbolFile ()
44 public SourceFileEntry DefineSource (string source_file)
47 throw new InvalidOperationException ();
49 SourceFileEntry source = (SourceFileEntry) source_hash [source_file];
51 source = new SourceFileEntry (this, source_file, sources.Count + 1);
52 source_hash.Add (source_file, source);
58 internal int DefineType (Type type)
60 if (type_hash.Contains (type))
61 return (int) type_hash [type];
63 int index = ++last_type_index;
64 type_hash.Add (type, index);
68 internal void AddMethod (MethodEntry entry)
73 internal int GetNextTypeIndex ()
75 return ++last_type_index;
78 internal int GetNextMethodIndex ()
80 return ++last_method_index;
83 internal void WriteString (BinaryWriter bw, string text)
85 byte[] data = Encoding.UTF8.GetBytes (text);
86 bw.Write ((int) data.Length);
90 internal string ReadString (int offset)
92 int old_pos = (int) reader.BaseStream.Position;
93 reader.BaseStream.Position = offset;
94 int length = reader.ReadInt32 ();
96 byte[] data = reader.ReadBytes (length);
97 string text = Encoding.UTF8.GetString (data);
98 reader.BaseStream.Position = old_pos;
102 void Write (BinaryWriter bw)
104 // Magic number and file version.
105 bw.Write (OffsetTable.Magic);
106 bw.Write (OffsetTable.Version);
109 // Offsets of file sections; we must write this after we're done
110 // writing the whole file, so we just reserve the space for it here.
112 long offset_table_offset = bw.BaseStream.Position;
116 // Write data sections.
118 ot.DataSectionOffset = (int) bw.BaseStream.Position;
119 foreach (SourceFileEntry source in sources)
120 source.WriteData (bw);
121 ot.DataSectionSize = (int) bw.BaseStream.Position - ot.DataSectionOffset;
124 // Write method table.
126 ot.MethodTableOffset = (int) bw.BaseStream.Position;
127 for (int i = 0; i < methods.Count; i++) {
128 MethodEntry entry = (MethodEntry) methods [i];
129 entry.WriteIndex (bw);
131 ot.MethodTableSize = (int) bw.BaseStream.Position - ot.MethodTableOffset;
134 // Write source table.
136 ot.SourceTableOffset = (int) bw.BaseStream.Position;
137 for (int i = 0; i < sources.Count; i++) {
138 SourceFileEntry source = (SourceFileEntry) sources [i];
141 ot.SourceTableSize = (int) bw.BaseStream.Position - ot.SourceTableOffset;
144 // Fixup offset table.
146 ot.TypeCount = last_type_index;
147 ot.MethodCount = methods.Count;
148 ot.SourceCount = sources.Count;
151 // Write offset table.
153 ot.TotalFileSize = (int) bw.BaseStream.Position;
154 bw.Seek ((int) offset_table_offset, SeekOrigin.Begin);
156 bw.Seek (0, SeekOrigin.End);
159 public void WriteSymbolFile (string output_filename)
162 throw new InvalidOperationException ();
164 using (FileStream stream = new FileStream (output_filename, FileMode.Create))
165 Write (new BinaryWriter (stream));
170 Hashtable method_hash;
171 Hashtable source_file_hash;
173 Hashtable method_name_hash;
174 Hashtable source_name_hash;
176 public MonoSymbolFile (string file_name)
178 stream = File.OpenRead (file_name);
179 reader = new BinaryReader (stream);
182 long magic = reader.ReadInt64 ();
183 long version = reader.ReadInt32 ();
184 if ((magic != OffsetTable.Magic) || (version != OffsetTable.Version))
185 throw new MonoSymbolFileException ();
186 ot = new OffsetTable (reader);
188 throw new MonoSymbolFileException ();
191 method_hash = new Hashtable ();
192 source_file_hash = new Hashtable ();
195 public int SourceCount {
196 get { return ot.SourceCount; }
199 public int MethodCount {
200 get { return ot.MethodCount; }
203 public int TypeCount {
204 get { return ot.TypeCount; }
207 public SourceFileEntry GetSourceFile (int index)
209 if ((index < 1) || (index > ot.SourceCount))
210 throw new ArgumentException ();
212 throw new InvalidOperationException ();
214 SourceFileEntry source = (SourceFileEntry) source_file_hash [index];
218 reader.BaseStream.Position = ot.SourceTableOffset +
219 SourceFileEntry.Size * (index - 1);
220 source = new SourceFileEntry (this, reader);
221 source_file_hash.Add (index, source);
225 public MethodEntry GetMethod (int index)
227 if ((index < 1) || (index > ot.MethodCount))
228 throw new ArgumentException ();
230 throw new InvalidOperationException ();
232 MethodEntry entry = (MethodEntry) method_hash [index];
236 reader.BaseStream.Position = ot.MethodTableOffset + 8 * (index - 1);
237 reader.BaseStream.Position = reader.ReadInt32 ();
239 entry = new MethodEntry (this, reader);
240 method_hash.Add (index, entry);
244 public int FindMethod (string full_name)
247 throw new InvalidOperationException ();
249 if (method_name_hash == null) {
250 method_name_hash = new Hashtable ();
252 for (int i = 0; i < ot.MethodCount; i++) {
253 reader.BaseStream.Position = ot.MethodTableOffset + 8 * i;
255 int offset = reader.ReadInt32 ();
256 int name_offset = reader.ReadInt32 ();
257 string name = ReadString (name_offset);
259 method_name_hash.Add (name, i);
263 object value = method_name_hash [full_name];
269 public int FindSource (string file_name)
272 throw new InvalidOperationException ();
274 if (source_name_hash == null) {
275 source_name_hash = new Hashtable ();
277 for (int i = 0; i < ot.SourceCount; i++) {
278 SourceFileEntry source = GetSourceFile (i + 1);
280 source_name_hash.Add (source.FileName, i);
284 object value = source_name_hash [file_name];
290 internal BinaryReader BinaryReader {
293 throw new InvalidOperationException ();
299 void IDisposable.Dispose ()
304 protected virtual void Dispose (bool disposing)
307 if (stream != null) {
311 if (reader != null) {