Implement mono_gc_alloc_fixed on Boehm to be uncollectable. This matches SGen behavio...
[mono.git] / mcs / tools / pdb2mdb / Driver.cs
1 //
2 // Driver.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@novell.com)
6 //
7 // (C) 2009 Novell, Inc. (http://www.novell.com)
8 //
9
10 using System;
11 using System.Collections.Generic;
12 using System.IO;
13 using System.Linq;
14
15 using Microsoft.Cci;
16 using Microsoft.Cci.Pdb;
17
18 using Mono.Cecil;
19
20 using Mono.CompilerServices.SymbolWriter;
21
22 namespace Pdb2Mdb {
23
24         public class Converter {
25
26                 MonoSymbolWriter mdb;
27                 Dictionary<string, SourceFile> files = new Dictionary<string, SourceFile> ();
28
29                 public static void Convert (string filename)
30                 {
31                         var asm = AssemblyDefinition.ReadAssembly (filename);
32
33                         var pdb = asm.Name.Name + ".pdb";
34                         pdb = Path.Combine (Path.GetDirectoryName (filename), pdb);
35
36                         using (var stream = File.OpenRead (pdb)) {
37                                 var funcs = PdbFile.LoadFunctions (stream, true);
38                                 Converter.Convert (asm, funcs, new MonoSymbolWriter (filename));
39                         }
40                 }
41
42                 internal Converter (MonoSymbolWriter mdb)
43                 {
44                         this.mdb = mdb;
45                 }
46
47                 internal static void Convert (AssemblyDefinition assembly, IEnumerable<PdbFunction> functions, MonoSymbolWriter mdb)
48                 {
49                         var converter = new Converter (mdb);
50
51                         foreach (var function in functions)
52                                 converter.ConvertFunction (function);
53
54                         mdb.WriteSymbolFile (assembly.MainModule.Mvid);
55                 }
56
57                 void ConvertFunction (PdbFunction function)
58                 {
59                         if (function.lines == null)
60                                 return;
61
62                         var method = new SourceMethod { Name = function.name, Token = (int) function.token };
63
64                         var file = GetSourceFile (mdb, function);
65
66                         var builder = mdb.OpenMethod (file.CompilationUnit, 0, method);
67
68                         ConvertSequencePoints (function, file, builder);
69
70                         ConvertVariables (function);
71
72                         mdb.CloseMethod ();
73                 }
74
75                 void ConvertSequencePoints (PdbFunction function, SourceFile file, SourceMethodBuilder builder)
76                 {
77                         int last_line = 0;
78                         foreach (var line in function.lines.SelectMany (lines => lines.lines)) {
79                                 // 0xfeefee is an MS convention, we can't pass it into mdb files, so we use the last non-hidden line
80                                 bool is_hidden = line.lineBegin == 0xfeefee;
81                                 builder.MarkSequencePoint (
82                                         (int) line.offset,
83                                         file.CompilationUnit.SourceFile,
84                                         is_hidden ? last_line : (int) line.lineBegin,
85                                         (int) line.colBegin, is_hidden ? -1 : (int)line.lineEnd, is_hidden ? -1 : (int)line.colEnd,
86                                         is_hidden);
87                                 if (!is_hidden)
88                                         last_line = (int) line.lineBegin;
89                         }
90                 }
91
92                 void ConvertVariables (PdbFunction function)
93                 {
94                         foreach (var scope in function.scopes)
95                                 ConvertScope (scope);
96                 }
97
98                 void ConvertScope (PdbScope scope)
99                 {
100                         ConvertSlots (scope, scope.slots);
101
102                         foreach (var s in scope.scopes)
103                                 ConvertScope (s);
104                 }
105
106                 void ConvertSlots (PdbScope scope, IEnumerable<PdbSlot> slots)
107                 {
108                         int scope_idx = mdb.OpenScope ((int)scope.address);
109                         foreach (var slot in slots) {
110                                 mdb.DefineLocalVariable ((int) slot.slot, slot.name);
111                                 mdb.DefineScopeVariable (scope_idx, (int)slot.slot);
112                         }
113                         mdb.CloseScope ((int)(scope.address + scope.length));
114                 }
115
116                 SourceFile GetSourceFile (MonoSymbolWriter mdb, PdbFunction function)
117                 {
118                         var name = (from l in function.lines where l.file != null select l.file.name).First ();
119
120                         SourceFile file;
121                         if (files.TryGetValue (name, out file))
122                                 return file;
123
124                         var entry = mdb.DefineDocument (name);
125                         var unit = mdb.DefineCompilationUnit (entry);
126
127                         file = new SourceFile (unit, entry);
128                         files.Add (name, file);
129                         return file;
130                 }
131
132                 class SourceFile : ISourceFile {
133                         CompileUnitEntry comp_unit;
134                         SourceFileEntry entry;
135
136                         public SourceFileEntry Entry
137                         {
138                                 get { return entry; }
139                         }
140
141                         public CompileUnitEntry CompilationUnit
142                         {
143                                 get { return comp_unit; }
144                         }
145
146                         public SourceFile (CompileUnitEntry comp_unit, SourceFileEntry entry)
147                         {
148                                 this.comp_unit = comp_unit;
149                                 this.entry = entry;
150                         }
151                 }
152
153                 class SourceMethod : IMethodDef {
154
155                         public string Name { get; set; }
156
157                         public int Token { get; set; }
158                 }
159         }
160
161         class Driver {
162
163                 static void Main (string [] args)
164                 {
165                         if (args.Length != 1)
166                                 Usage ();
167
168                         var asm = args [0];
169
170                         if (!File.Exists (asm))
171                                 Usage ();
172
173                         var assembly = AssemblyDefinition.ReadAssembly (asm);
174
175                         var pdb = assembly.Name.Name + ".pdb";
176                         pdb = Path.Combine (Path.GetDirectoryName (asm), pdb);
177
178                         if (!File.Exists (pdb))
179                                 Usage ();
180
181                         using (var stream = File.OpenRead (pdb)) {
182                                 Convert (assembly, stream, new MonoSymbolWriter (asm));
183                         }
184                 }
185
186                 static void Convert (AssemblyDefinition assembly, Stream pdb, MonoSymbolWriter mdb)
187                 {
188                         try {
189                                 Converter.Convert (assembly, PdbFile.LoadFunctions (pdb, true), mdb);
190                         } catch (Exception e) {
191                                 Error (e);
192                         }
193                 }
194
195                 static void Usage ()
196                 {
197                         Console.WriteLine ("Mono pdb to mdb debug symbol store converter");
198                         Console.WriteLine ("Usage: pdb2mdb assembly");
199
200                         Environment.Exit (1);
201                 }
202
203                 static void Error (Exception e)
204                 {
205                         Console.WriteLine ("Fatal error:");
206                         Console.WriteLine (e);
207                 }
208         }
209 }