2002-09-18 Martin Baulig <martin@gnome.org>
[mono.git] / mcs / class / Mono.CSharp.Debugger / MonoSymbolTableWriter.cs
1 //
2 // System.Diagnostics.SymbolStore/MonoSymbolTableWriter.cs
3 //
4 // Author:
5 //   Martin Baulig (martin@gnome.org)
6 //
7 // (C) 2002 Ximian, Inc.  http://www.ximian.com
8 //
9
10 using System;
11 using System.Reflection;
12 using System.Reflection.Emit;
13 using System.Collections;
14 using System.Text;
15 using System.IO;
16         
17 namespace Mono.CSharp.Debugger
18 {
19         internal class MonoSymbolTableWriter : IDisposable
20         {
21                 BinaryWriter bw;
22
23                 public MonoSymbolTableWriter (string output_filename)
24                 {
25                         FileStream stream = new FileStream (output_filename, FileMode.Create);
26                         bw = new BinaryWriter (stream);
27                 }
28
29                 public void WriteSymbolTable (MonoSymbolWriter symwriter)
30                 {
31                         // Magic number and file version.
32                         bw.Write (OffsetTable.Magic);
33                         bw.Write (OffsetTable.Version);
34
35                         OffsetTable ot = new OffsetTable ();
36
37                         //
38                         // Offsets of file sections; we must write this after we're done
39                         // writing the whole file, so we just reserve the space for it here.
40                         //
41                         long offset_table_offset = bw.BaseStream.Position;
42                         ot.Write (bw);
43
44                         //
45                         // Write source file table.
46                         //
47                         Hashtable sources = new Hashtable ();
48
49                         ot.source_table_offset = (int) bw.BaseStream.Position;
50                         foreach (ISourceFile source in symwriter.Sources) {
51                                 if (sources.ContainsKey (source))
52                                         continue;
53
54                                 sources.Add (source, (int) bw.BaseStream.Position);
55                                 byte[] file_name = Encoding.UTF8.GetBytes (source.FileName);
56                                 bw.Write ((int) file_name.Length);
57                                 bw.Write (file_name);
58                         }
59                         ot.source_table_size = (int) bw.BaseStream.Position - ot.source_table_offset;
60
61                         //
62                         // Write line number table
63                         //
64                         Hashtable methods = new Hashtable ();
65
66                         int address_table_size = 0;
67
68                         ot.line_number_table_offset = (int) bw.BaseStream.Position;
69                         foreach (ISourceMethod method in symwriter.Methods) {
70                                 if (method.Start == null || method.Start.Row == 0)
71                                         continue;
72
73                                 int count = method.Lines.Length;
74                                 LineNumberEntry[] lines = new LineNumberEntry [count];
75
76                                 int pos = (int) bw.BaseStream.Position;
77
78                                 int address_table_offset = address_table_size;
79                                 int my_size = (int) (MethodAddress.Size + count * 8);
80                                 address_table_size += my_size;
81
82                                 for (int i = 0; i < count; i++) {
83                                         lines [i] = new LineNumberEntry (method.Lines [i]);
84                                         lines [i].Write (bw);
85                                 }
86
87                                 MethodEntry entry = new MethodEntry (
88                                         (int) method.Token, (int) sources [method.SourceFile],
89                                         method.SourceFile.FileName, lines, pos, address_table_offset,
90                                         my_size, (int) method.Start.Row, (int) method.End.Row);
91
92                                 methods.Add (method, entry);
93
94                         }
95                         ot.line_number_table_size = (int) bw.BaseStream.Position -
96                                 ot.line_number_table_offset;
97
98                         //
99                         // Write method table
100                         //
101                         ot.method_count = methods.Count;
102                         ot.method_table_offset = (int) bw.BaseStream.Position;
103                         foreach (MethodEntry entry in methods.Values)
104                                 entry.Write (bw);
105                         ot.method_table_size = (int) bw.BaseStream.Position -  ot.method_table_offset;
106
107                         //
108                         // Write offset table
109                         //
110                         ot.address_table_size = address_table_size;
111                         ot.total_file_size = (int) bw.BaseStream.Position;
112                         bw.Seek ((int) offset_table_offset, SeekOrigin.Begin);
113                         ot.Write (bw);
114                         bw.Seek (0, SeekOrigin.End);
115                 }
116
117                 void IDisposable.Dispose() {
118                         Dispose (true);
119                 }
120
121                 protected virtual void Dispose (bool disposing)
122                 {
123                         if (disposing)
124                         {
125                                 bw.Close ();
126                         }
127                 }
128         }
129 }