123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446 |
- //
- // Mono.CSharp.Debugger/MonoSymbolTable.cs
- //
- // Author:
- // Martin Baulig (martin@ximian.com)
- //
- // (C) 2002 Ximian, Inc. http://www.ximian.com
- //
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- using System;
- using System.Security.Cryptography;
- using System.Collections.Generic;
- using System.Text;
- using System.IO;
- //
- // Parts which are actually written into the symbol file are marked with
- //
- // #region This is actually written to the symbol file
- // #endregion
- //
- // Please do not modify these regions without previously talking to me.
- //
- // All changes to the file format must be synchronized in several places:
- //
- // a) The fields in these regions (and their order) must match the actual
- // contents of the symbol file.
- //
- // This helps people to understand the symbol file format without reading
- // too much source code, ie. you look at the appropriate region and then
- // you know what's actually in the file.
- //
- // It is also required to help me enforce b).
- //
- // b) The regions must be kept in sync with the unmanaged code in
- // mono/metadata/debug-mono-symfile.h
- //
- // When making changes to the file format, you must also increase two version
- // numbers:
- //
- // i) OffsetTable.Version in this file.
- // ii) MONO_SYMBOL_FILE_VERSION in mono/metadata/debug-mono-symfile.h
- //
- // After doing so, recompile everything, including the debugger. Symbol files
- // with different versions are incompatible to each other and the debugger and
- // the runtime enfore this, so you need to recompile all your assemblies after
- // changing the file format.
- //
- namespace ILRuntime.Mono.CompilerServices.SymbolWriter
- {
- public class OffsetTable
- {
- public const int MajorVersion = 50;
- public const int MinorVersion = 0;
- public const long Magic = 0x45e82623fd7fa614;
- #region This is actually written to the symbol file
- public int TotalFileSize;
- public int DataSectionOffset;
- public int DataSectionSize;
- public int CompileUnitCount;
- public int CompileUnitTableOffset;
- public int CompileUnitTableSize;
- public int SourceCount;
- public int SourceTableOffset;
- public int SourceTableSize;
- public int MethodCount;
- public int MethodTableOffset;
- public int MethodTableSize;
- public int TypeCount;
- public int AnonymousScopeCount;
- public int AnonymousScopeTableOffset;
- public int AnonymousScopeTableSize;
- [Flags]
- public enum Flags
- {
- IsAspxSource = 1,
- WindowsFileNames = 2
- }
- public Flags FileFlags;
- public int LineNumberTable_LineBase = LineNumberTable.Default_LineBase;
- public int LineNumberTable_LineRange = LineNumberTable.Default_LineRange;
- public int LineNumberTable_OpcodeBase = LineNumberTable.Default_OpcodeBase;
- #endregion
- internal OffsetTable ()
- {
- #if !NET_CORE
- int platform = (int) Environment.OSVersion.Platform;
- if ((platform != 4) && (platform != 128))
- FileFlags |= Flags.WindowsFileNames;
- #endif
- }
- internal OffsetTable (BinaryReader reader, int major_version, int minor_version)
- {
- TotalFileSize = reader.ReadInt32 ();
- DataSectionOffset = reader.ReadInt32 ();
- DataSectionSize = reader.ReadInt32 ();
- CompileUnitCount = reader.ReadInt32 ();
- CompileUnitTableOffset = reader.ReadInt32 ();
- CompileUnitTableSize = reader.ReadInt32 ();
- SourceCount = reader.ReadInt32 ();
- SourceTableOffset = reader.ReadInt32 ();
- SourceTableSize = reader.ReadInt32 ();
- MethodCount = reader.ReadInt32 ();
- MethodTableOffset = reader.ReadInt32 ();
- MethodTableSize = reader.ReadInt32 ();
- TypeCount = reader.ReadInt32 ();
- AnonymousScopeCount = reader.ReadInt32 ();
- AnonymousScopeTableOffset = reader.ReadInt32 ();
- AnonymousScopeTableSize = reader.ReadInt32 ();
- LineNumberTable_LineBase = reader.ReadInt32 ();
- LineNumberTable_LineRange = reader.ReadInt32 ();
- LineNumberTable_OpcodeBase = reader.ReadInt32 ();
- FileFlags = (Flags) reader.ReadInt32 ();
- }
- internal void Write (BinaryWriter bw, int major_version, int minor_version)
- {
- bw.Write (TotalFileSize);
- bw.Write (DataSectionOffset);
- bw.Write (DataSectionSize);
- bw.Write (CompileUnitCount);
- bw.Write (CompileUnitTableOffset);
- bw.Write (CompileUnitTableSize);
- bw.Write (SourceCount);
- bw.Write (SourceTableOffset);
- bw.Write (SourceTableSize);
- bw.Write (MethodCount);
- bw.Write (MethodTableOffset);
- bw.Write (MethodTableSize);
- bw.Write (TypeCount);
- bw.Write (AnonymousScopeCount);
- bw.Write (AnonymousScopeTableOffset);
- bw.Write (AnonymousScopeTableSize);
- bw.Write (LineNumberTable_LineBase);
- bw.Write (LineNumberTable_LineRange);
- bw.Write (LineNumberTable_OpcodeBase);
- bw.Write ((int) FileFlags);
- }
- public override string ToString ()
- {
- return String.Format (
- "OffsetTable [{0} - {1}:{2} - {3}:{4}:{5} - {6}:{7}:{8} - {9}]",
- TotalFileSize, DataSectionOffset, DataSectionSize, SourceCount,
- SourceTableOffset, SourceTableSize, MethodCount, MethodTableOffset,
- MethodTableSize, TypeCount);
- }
- }
- public class LineNumberEntry
- {
- #region This is actually written to the symbol file
- public readonly int Row;
- public int Column;
- public int EndRow, EndColumn;
- public readonly int File;
- public readonly int Offset;
- public readonly bool IsHidden; // Obsolete is never used
- #endregion
- public sealed class LocationComparer : IComparer<LineNumberEntry>
- {
- public static readonly LocationComparer Default = new LocationComparer ();
- public int Compare (LineNumberEntry l1, LineNumberEntry l2)
- {
- return l1.Row == l2.Row ?
- l1.Column.CompareTo (l2.Column) :
- l1.Row.CompareTo (l2.Row);
- }
- }
- public static readonly LineNumberEntry Null = new LineNumberEntry (0, 0, 0, 0);
- public LineNumberEntry (int file, int row, int column, int offset)
- : this (file, row, column, offset, false)
- {
- }
- public LineNumberEntry (int file, int row, int offset)
- : this (file, row, -1, offset, false)
- {
- }
- public LineNumberEntry (int file, int row, int column, int offset, bool is_hidden)
- : this (file, row, column, -1, -1, offset, is_hidden)
- {
- }
- public LineNumberEntry (int file, int row, int column, int end_row, int end_column, int offset, bool is_hidden)
- {
- this.File = file;
- this.Row = row;
- this.Column = column;
- this.EndRow = end_row;
- this.EndColumn = end_column;
- this.Offset = offset;
- this.IsHidden = is_hidden;
- }
- public override string ToString ()
- {
- return String.Format ("[Line {0}:{1},{2}-{3},{4}:{5}]", File, Row, Column, EndRow, EndColumn, Offset);
- }
- }
- public class CodeBlockEntry
- {
- public int Index;
- #region This is actually written to the symbol file
- public int Parent;
- public Type BlockType;
- public int StartOffset;
- public int EndOffset;
- #endregion
- public enum Type {
- Lexical = 1,
- CompilerGenerated = 2,
- IteratorBody = 3,
- IteratorDispatcher = 4
- }
- public CodeBlockEntry (int index, int parent, Type type, int start_offset)
- {
- this.Index = index;
- this.Parent = parent;
- this.BlockType = type;
- this.StartOffset = start_offset;
- }
- internal CodeBlockEntry (int index, MyBinaryReader reader)
- {
- this.Index = index;
- int type_flag = reader.ReadLeb128 ();
- BlockType = (Type) (type_flag & 0x3f);
- this.Parent = reader.ReadLeb128 ();
- this.StartOffset = reader.ReadLeb128 ();
- this.EndOffset = reader.ReadLeb128 ();
- /* Reserved for future extensions. */
- if ((type_flag & 0x40) != 0) {
- int data_size = reader.ReadInt16 ();
- reader.BaseStream.Position += data_size;
- }
- }
- public void Close (int end_offset)
- {
- this.EndOffset = end_offset;
- }
- internal void Write (MyBinaryWriter bw)
- {
- bw.WriteLeb128 ((int) BlockType);
- bw.WriteLeb128 (Parent);
- bw.WriteLeb128 (StartOffset);
- bw.WriteLeb128 (EndOffset);
- }
- public override string ToString ()
- {
- return String.Format ("[CodeBlock {0}:{1}:{2}:{3}:{4}]",
- Index, Parent, BlockType, StartOffset, EndOffset);
- }
- }
- public struct LocalVariableEntry
- {
- #region This is actually written to the symbol file
- public readonly int Index;
- public readonly string Name;
- public readonly int BlockIndex;
- #endregion
- public LocalVariableEntry (int index, string name, int block)
- {
- this.Index = index;
- this.Name = name;
- this.BlockIndex = block;
- }
- internal LocalVariableEntry (MonoSymbolFile file, MyBinaryReader reader)
- {
- Index = reader.ReadLeb128 ();
- Name = reader.ReadString ();
- BlockIndex = reader.ReadLeb128 ();
- }
- internal void Write (MonoSymbolFile file, MyBinaryWriter bw)
- {
- bw.WriteLeb128 (Index);
- bw.Write (Name);
- bw.WriteLeb128 (BlockIndex);
- }
- public override string ToString ()
- {
- return String.Format ("[LocalVariable {0}:{1}:{2}]",
- Name, Index, BlockIndex - 1);
- }
- }
- public struct CapturedVariable
- {
- #region This is actually written to the symbol file
- public readonly string Name;
- public readonly string CapturedName;
- public readonly CapturedKind Kind;
- #endregion
- public enum CapturedKind : byte
- {
- Local,
- Parameter,
- This
- }
- public CapturedVariable (string name, string captured_name,
- CapturedKind kind)
- {
- this.Name = name;
- this.CapturedName = captured_name;
- this.Kind = kind;
- }
- internal CapturedVariable (MyBinaryReader reader)
- {
- Name = reader.ReadString ();
- CapturedName = reader.ReadString ();
- Kind = (CapturedKind) reader.ReadByte ();
- }
- internal void Write (MyBinaryWriter bw)
- {
- bw.Write (Name);
- bw.Write (CapturedName);
- bw.Write ((byte) Kind);
- }
- public override string ToString ()
- {
- return String.Format ("[CapturedVariable {0}:{1}:{2}]",
- Name, CapturedName, Kind);
- }
- }
- public struct CapturedScope
- {
- #region This is actually written to the symbol file
- public readonly int Scope;
- public readonly string CapturedName;
- #endregion
- public CapturedScope (int scope, string captured_name)
- {
- this.Scope = scope;
- this.CapturedName = captured_name;
- }
- internal CapturedScope (MyBinaryReader reader)
- {
- Scope = reader.ReadLeb128 ();
- CapturedName = reader.ReadString ();
- }
- internal void Write (MyBinaryWriter bw)
- {
- bw.WriteLeb128 (Scope);
- bw.Write (CapturedName);
- }
- public override string ToString ()
- {
- return String.Format ("[CapturedScope {0}:{1}]",
- Scope, CapturedName);
- }
- }
- public struct ScopeVariable
- {
- #region This is actually written to the symbol file
- public readonly int Scope;
- public readonly int Index;
- #endregion
- public ScopeVariable (int scope, int index)
- {
- this.Scope = scope;
- this.Index = index;
- }
- internal ScopeVariable (MyBinaryReader reader)
- {
- Scope = reader.ReadLeb128 ();
- Index = reader.ReadLeb128 ();
- }
- internal void Write (MyBinaryWriter bw)
- {
- bw.WriteLeb128 (Scope);
- bw.WriteLeb128 (Index);
- }
- public override string ToString ()
- {
- return String.Format ("[ScopeVariable {0}:{1}]", Scope, Index);
- }
- }
- public class AnonymousScopeEntry
- {
- #region This is actually written to the symbol file
- public readonly int ID;
- #endregion
- List<CapturedVariable> captured_vars = new List<CapturedVariable> ();
- List<CapturedScope> captured_scopes = new List<CapturedScope> ();
- public AnonymousScopeEntry (int id)
- {
- this.ID = id;
- }
- internal AnonymousScopeEntry (MyBinaryReader reader)
- {
- ID = reader.ReadLeb128 ();
- int num_captured_vars = reader.ReadLeb128 ();
- for (int i = 0; i < num_captured_vars; i++)
- captured_vars.Add (new CapturedVariable (reader));
- int num_captured_scopes = reader.ReadLeb128 ();
- for (int i = 0; i < num_captured_scopes; i++)
- captured_scopes.Add (new CapturedScope (reader));
- }
- internal void AddCapturedVariable (string name, string captured_name,
- CapturedVariable.CapturedKind kind)
- {
- captured_vars.Add (new CapturedVariable (name, captured_name, kind));
- }
- public CapturedVariable[] CapturedVariables {
- get {
- CapturedVariable[] retval = new CapturedVariable [captured_vars.Count];
- captured_vars.CopyTo (retval, 0);
- return retval;
- }
- }
- internal void AddCapturedScope (int scope, string captured_name)
- {
- captured_scopes.Add (new CapturedScope (scope, captured_name));
- }
- public CapturedScope[] CapturedScopes {
- get {
- CapturedScope[] retval = new CapturedScope [captured_scopes.Count];
- captured_scopes.CopyTo (retval, 0);
- return retval;
- }
- }
- internal void Write (MyBinaryWriter bw)
- {
- bw.WriteLeb128 (ID);
- bw.WriteLeb128 (captured_vars.Count);
- foreach (CapturedVariable cv in captured_vars)
- cv.Write (bw);
- bw.WriteLeb128 (captured_scopes.Count);
- foreach (CapturedScope cs in captured_scopes)
- cs.Write (bw);
- }
- public override string ToString ()
- {
- return String.Format ("[AnonymousScope {0}]", ID);
- }
- }
- public class CompileUnitEntry : ICompileUnit
- {
- #region This is actually written to the symbol file
- public readonly int Index;
- int DataOffset;
- #endregion
- MonoSymbolFile file;
- SourceFileEntry source;
- List<SourceFileEntry> include_files;
- List<NamespaceEntry> namespaces;
- bool creating;
- public static int Size {
- get { return 8; }
- }
- CompileUnitEntry ICompileUnit.Entry {
- get { return this; }
- }
- public CompileUnitEntry (MonoSymbolFile file, SourceFileEntry source)
- {
- this.file = file;
- this.source = source;
- this.Index = file.AddCompileUnit (this);
- creating = true;
- namespaces = new List<NamespaceEntry> ();
- }
- public void AddFile (SourceFileEntry file)
- {
- if (!creating)
- throw new InvalidOperationException ();
- if (include_files == null)
- include_files = new List<SourceFileEntry> ();
- include_files.Add (file);
- }
- public SourceFileEntry SourceFile {
- get {
- if (creating)
- return source;
- ReadData ();
- return source;
- }
- }
- public int DefineNamespace (string name, string[] using_clauses, int parent)
- {
- if (!creating)
- throw new InvalidOperationException ();
- int index = file.GetNextNamespaceIndex ();
- NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent);
- namespaces.Add (ns);
- return index;
- }
- internal void WriteData (MyBinaryWriter bw)
- {
- DataOffset = (int) bw.BaseStream.Position;
- bw.WriteLeb128 (source.Index);
- int count_includes = include_files != null ? include_files.Count : 0;
- bw.WriteLeb128 (count_includes);
- if (include_files != null) {
- foreach (SourceFileEntry entry in include_files)
- bw.WriteLeb128 (entry.Index);
- }
- bw.WriteLeb128 (namespaces.Count);
- foreach (NamespaceEntry ns in namespaces)
- ns.Write (file, bw);
- }
- internal void Write (BinaryWriter bw)
- {
- bw.Write (Index);
- bw.Write (DataOffset);
- }
- internal CompileUnitEntry (MonoSymbolFile file, MyBinaryReader reader)
- {
- this.file = file;
- Index = reader.ReadInt32 ();
- DataOffset = reader.ReadInt32 ();
- }
- public void ReadAll ()
- {
- ReadData ();
- }
- void ReadData ()
- {
- if (creating)
- throw new InvalidOperationException ();
- lock (file) {
- if (namespaces != null)
- return;
- MyBinaryReader reader = file.BinaryReader;
- int old_pos = (int) reader.BaseStream.Position;
- reader.BaseStream.Position = DataOffset;
- int source_idx = reader.ReadLeb128 ();
- source = file.GetSourceFile (source_idx);
- int count_includes = reader.ReadLeb128 ();
- if (count_includes > 0) {
- include_files = new List<SourceFileEntry> ();
- for (int i = 0; i < count_includes; i++)
- include_files.Add (file.GetSourceFile (reader.ReadLeb128 ()));
- }
- int count_ns = reader.ReadLeb128 ();
- namespaces = new List<NamespaceEntry> ();
- for (int i = 0; i < count_ns; i ++)
- namespaces.Add (new NamespaceEntry (file, reader));
- reader.BaseStream.Position = old_pos;
- }
- }
- public NamespaceEntry[] Namespaces {
- get {
- ReadData ();
- NamespaceEntry[] retval = new NamespaceEntry [namespaces.Count];
- namespaces.CopyTo (retval, 0);
- return retval;
- }
- }
- public SourceFileEntry[] IncludeFiles {
- get {
- ReadData ();
- if (include_files == null)
- return new SourceFileEntry [0];
- SourceFileEntry[] retval = new SourceFileEntry [include_files.Count];
- include_files.CopyTo (retval, 0);
- return retval;
- }
- }
- }
- public class SourceFileEntry
- {
- #region This is actually written to the symbol file
- public readonly int Index;
- int DataOffset;
- #endregion
- MonoSymbolFile file;
- string file_name;
- byte[] guid;
- byte[] hash;
- bool creating;
- bool auto_generated;
- readonly string sourceFile;
- public static int Size {
- get { return 8; }
- }
- public SourceFileEntry (MonoSymbolFile file, string file_name)
- {
- this.file = file;
- this.file_name = file_name;
- this.Index = file.AddSource (this);
- creating = true;
- }
- public SourceFileEntry (MonoSymbolFile file, string sourceFile, byte [] guid, byte [] checksum)
- : this (file, sourceFile, sourceFile, guid, checksum)
- {
- }
- public SourceFileEntry (MonoSymbolFile file, string fileName, string sourceFile, byte[] guid, byte[] checksum)
- : this (file, fileName)
- {
- this.guid = guid;
- this.hash = checksum;
- this.sourceFile = sourceFile;
- }
- public byte[] Checksum {
- get {
- return hash;
- }
- }
- internal void WriteData (MyBinaryWriter bw)
- {
- DataOffset = (int) bw.BaseStream.Position;
- bw.Write (file_name);
- if (guid == null)
- guid = new byte[16];
- if (hash == null) {
- try {
- using (FileStream fs = new FileStream (sourceFile, FileMode.Open, FileAccess.Read)) {
- MD5 md5 = MD5.Create ();
- hash = md5.ComputeHash (fs);
- }
- } catch {
- hash = new byte [16];
- }
- }
- bw.Write (guid);
- bw.Write (hash);
- bw.Write ((byte) (auto_generated ? 1 : 0));
- }
- internal void Write (BinaryWriter bw)
- {
- bw.Write (Index);
- bw.Write (DataOffset);
- }
- internal SourceFileEntry (MonoSymbolFile file, MyBinaryReader reader)
- {
- this.file = file;
- Index = reader.ReadInt32 ();
- DataOffset = reader.ReadInt32 ();
- int old_pos = (int) reader.BaseStream.Position;
- reader.BaseStream.Position = DataOffset;
- sourceFile = file_name = reader.ReadString ();
- guid = reader.ReadBytes (16);
- hash = reader.ReadBytes (16);
- auto_generated = reader.ReadByte () == 1;
- reader.BaseStream.Position = old_pos;
- }
- public string FileName {
- get { return file_name; }
- set { file_name = value; }
- }
- public bool AutoGenerated {
- get { return auto_generated; }
- }
- public void SetAutoGenerated ()
- {
- if (!creating)
- throw new InvalidOperationException ();
- auto_generated = true;
- file.OffsetTable.FileFlags |= OffsetTable.Flags.IsAspxSource;
- }
- public bool CheckChecksum ()
- {
- try {
- using (FileStream fs = new FileStream (sourceFile, FileMode.Open)) {
- MD5 md5 = MD5.Create ();
- byte[] data = md5.ComputeHash (fs);
- for (int i = 0; i < 16; i++)
- if (data [i] != hash [i])
- return false;
- return true;
- }
- } catch {
- return false;
- }
- }
- public override string ToString ()
- {
- return String.Format ("SourceFileEntry ({0}:{1})", Index, DataOffset);
- }
- }
- public class LineNumberTable
- {
- protected LineNumberEntry[] _line_numbers;
- public LineNumberEntry[] LineNumbers {
- get { return _line_numbers; }
- }
- public readonly int LineBase;
- public readonly int LineRange;
- public readonly byte OpcodeBase;
- public readonly int MaxAddressIncrement;
- #region Configurable constants
- public const int Default_LineBase = -1;
- public const int Default_LineRange = 8;
- public const byte Default_OpcodeBase = 9;
- #endregion
- public const byte DW_LNS_copy = 1;
- public const byte DW_LNS_advance_pc = 2;
- public const byte DW_LNS_advance_line = 3;
- public const byte DW_LNS_set_file = 4;
- public const byte DW_LNS_const_add_pc = 8;
- public const byte DW_LNE_end_sequence = 1;
- // MONO extensions.
- public const byte DW_LNE_MONO_negate_is_hidden = 0x40;
- internal const byte DW_LNE_MONO__extensions_start = 0x40;
- internal const byte DW_LNE_MONO__extensions_end = 0x7f;
- protected LineNumberTable (MonoSymbolFile file)
- {
- this.LineBase = file.OffsetTable.LineNumberTable_LineBase;
- this.LineRange = file.OffsetTable.LineNumberTable_LineRange;
- this.OpcodeBase = (byte) file.OffsetTable.LineNumberTable_OpcodeBase;
- this.MaxAddressIncrement = (255 - OpcodeBase) / LineRange;
- }
- internal LineNumberTable (MonoSymbolFile file, LineNumberEntry[] lines)
- : this (file)
- {
- this._line_numbers = lines;
- }
- internal void Write (MonoSymbolFile file, MyBinaryWriter bw, bool hasColumnsInfo, bool hasEndInfo)
- {
- int start = (int) bw.BaseStream.Position;
- bool last_is_hidden = false;
- int last_line = 1, last_offset = 0, last_file = 1;
- for (int i = 0; i < LineNumbers.Length; i++) {
- int line_inc = LineNumbers [i].Row - last_line;
- int offset_inc = LineNumbers [i].Offset - last_offset;
- if (LineNumbers [i].File != last_file) {
- bw.Write (DW_LNS_set_file);
- bw.WriteLeb128 (LineNumbers [i].File);
- last_file = LineNumbers [i].File;
- }
- if (LineNumbers [i].IsHidden != last_is_hidden) {
- bw.Write ((byte) 0);
- bw.Write ((byte) 1);
- bw.Write (DW_LNE_MONO_negate_is_hidden);
- last_is_hidden = LineNumbers [i].IsHidden;
- }
- if (offset_inc >= MaxAddressIncrement) {
- if (offset_inc < 2 * MaxAddressIncrement) {
- bw.Write (DW_LNS_const_add_pc);
- offset_inc -= MaxAddressIncrement;
- } else {
- bw.Write (DW_LNS_advance_pc);
- bw.WriteLeb128 (offset_inc);
- offset_inc = 0;
- }
- }
- if ((line_inc < LineBase) || (line_inc >= LineBase + LineRange)) {
- bw.Write (DW_LNS_advance_line);
- bw.WriteLeb128 (line_inc);
- if (offset_inc != 0) {
- bw.Write (DW_LNS_advance_pc);
- bw.WriteLeb128 (offset_inc);
- }
- bw.Write (DW_LNS_copy);
- } else {
- byte opcode;
- opcode = (byte) (line_inc - LineBase + (LineRange * offset_inc) +
- OpcodeBase);
- bw.Write (opcode);
- }
- last_line = LineNumbers [i].Row;
- last_offset = LineNumbers [i].Offset;
- }
- bw.Write ((byte) 0);
- bw.Write ((byte) 1);
- bw.Write (DW_LNE_end_sequence);
- if (hasColumnsInfo) {
- for (int i = 0; i < LineNumbers.Length; i++) {
- var ln = LineNumbers [i];
- if (ln.Row >= 0)
- bw.WriteLeb128 (ln.Column);
- }
- }
- if (hasEndInfo) {
- for (int i = 0; i < LineNumbers.Length; i++) {
- var ln = LineNumbers [i];
- if (ln.EndRow == -1 || ln.EndColumn == -1 || ln.Row > ln.EndRow) {
- bw.WriteLeb128 (0xffffff);
- } else {
- bw.WriteLeb128 (ln.EndRow - ln.Row);
- bw.WriteLeb128 (ln.EndColumn);
- }
- }
- }
- file.ExtendedLineNumberSize += (int) bw.BaseStream.Position - start;
- }
- internal static LineNumberTable Read (MonoSymbolFile file, MyBinaryReader br, bool readColumnsInfo, bool readEndInfo)
- {
- LineNumberTable lnt = new LineNumberTable (file);
- lnt.DoRead (file, br, readColumnsInfo, readEndInfo);
- return lnt;
- }
- void DoRead (MonoSymbolFile file, MyBinaryReader br, bool includesColumns, bool includesEnds)
- {
- var lines = new List<LineNumberEntry> ();
- bool is_hidden = false, modified = false;
- int stm_line = 1, stm_offset = 0, stm_file = 1;
- while (true) {
- byte opcode = br.ReadByte ();
- if (opcode == 0) {
- byte size = br.ReadByte ();
- long end_pos = br.BaseStream.Position + size;
- opcode = br.ReadByte ();
- if (opcode == DW_LNE_end_sequence) {
- if (modified)
- lines.Add (new LineNumberEntry (
- stm_file, stm_line, -1, stm_offset, is_hidden));
- break;
- } else if (opcode == DW_LNE_MONO_negate_is_hidden) {
- is_hidden = !is_hidden;
- modified = true;
- } else if ((opcode >= DW_LNE_MONO__extensions_start) &&
- (opcode <= DW_LNE_MONO__extensions_end)) {
- ; // reserved for future extensions
- } else {
- throw new MonoSymbolFileException ("Unknown extended opcode {0:x}", opcode);
- }
- br.BaseStream.Position = end_pos;
- continue;
- } else if (opcode < OpcodeBase) {
- switch (opcode) {
- case DW_LNS_copy:
- lines.Add (new LineNumberEntry (
- stm_file, stm_line, -1, stm_offset, is_hidden));
- modified = false;
- break;
- case DW_LNS_advance_pc:
- stm_offset += br.ReadLeb128 ();
- modified = true;
- break;
- case DW_LNS_advance_line:
- stm_line += br.ReadLeb128 ();
- modified = true;
- break;
- case DW_LNS_set_file:
- stm_file = br.ReadLeb128 ();
- modified = true;
- break;
- case DW_LNS_const_add_pc:
- stm_offset += MaxAddressIncrement;
- modified = true;
- break;
- default:
- throw new MonoSymbolFileException (
- "Unknown standard opcode {0:x} in LNT",
- opcode);
- }
- } else {
- opcode -= OpcodeBase;
- stm_offset += opcode / LineRange;
- stm_line += LineBase + (opcode % LineRange);
- lines.Add (new LineNumberEntry (
- stm_file, stm_line, -1, stm_offset, is_hidden));
- modified = false;
- }
- }
- _line_numbers = lines.ToArray ();
- if (includesColumns) {
- for (int i = 0; i < _line_numbers.Length; ++i) {
- var ln = _line_numbers[i];
- if (ln.Row >= 0)
- ln.Column = br.ReadLeb128 ();
- }
- }
- if (includesEnds) {
- for (int i = 0; i < _line_numbers.Length; ++i) {
- var ln = _line_numbers[i];
- int row = br.ReadLeb128 ();
- if (row == 0xffffff) {
- ln.EndRow = -1;
- ln.EndColumn = -1;
- } else {
- ln.EndRow = ln.Row + row;
- ln.EndColumn = br.ReadLeb128 ();
- }
- }
- }
- }
- public bool GetMethodBounds (out LineNumberEntry start, out LineNumberEntry end)
- {
- if (_line_numbers.Length > 1) {
- start = _line_numbers [0];
- end = _line_numbers [_line_numbers.Length - 1];
- return true;
- }
- start = LineNumberEntry.Null;
- end = LineNumberEntry.Null;
- return false;
- }
- }
- public class MethodEntry : IComparable
- {
- #region This is actually written to the symbol file
- public readonly int CompileUnitIndex;
- public readonly int Token;
- public readonly int NamespaceID;
- int DataOffset;
- int LocalVariableTableOffset;
- int LineNumberTableOffset;
- int CodeBlockTableOffset;
- int ScopeVariableTableOffset;
- int RealNameOffset;
- Flags flags;
- #endregion
- int index;
- public Flags MethodFlags {
- get { return flags; }
- }
- public readonly CompileUnitEntry CompileUnit;
- LocalVariableEntry[] locals;
- CodeBlockEntry[] code_blocks;
- ScopeVariable[] scope_vars;
- LineNumberTable lnt;
- string real_name;
- public readonly MonoSymbolFile SymbolFile;
- public int Index {
- get { return index; }
- set { index = value; }
- }
- [Flags]
- public enum Flags
- {
- LocalNamesAmbiguous = 1,
- ColumnsInfoIncluded = 1 << 1,
- EndInfoIncluded = 1 << 2
- }
- public const int Size = 12;
- internal MethodEntry (MonoSymbolFile file, MyBinaryReader reader, int index)
- {
- this.SymbolFile = file;
- this.index = index;
- Token = reader.ReadInt32 ();
- DataOffset = reader.ReadInt32 ();
- LineNumberTableOffset = reader.ReadInt32 ();
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = DataOffset;
- CompileUnitIndex = reader.ReadLeb128 ();
- LocalVariableTableOffset = reader.ReadLeb128 ();
- NamespaceID = reader.ReadLeb128 ();
- CodeBlockTableOffset = reader.ReadLeb128 ();
- ScopeVariableTableOffset = reader.ReadLeb128 ();
- RealNameOffset = reader.ReadLeb128 ();
- flags = (Flags) reader.ReadLeb128 ();
- reader.BaseStream.Position = old_pos;
- CompileUnit = file.GetCompileUnit (CompileUnitIndex);
- }
- internal MethodEntry (MonoSymbolFile file, CompileUnitEntry comp_unit,
- int token, ScopeVariable[] scope_vars,
- LocalVariableEntry[] locals, LineNumberEntry[] lines,
- CodeBlockEntry[] code_blocks, string real_name,
- Flags flags, int namespace_id)
- {
- this.SymbolFile = file;
- this.real_name = real_name;
- this.locals = locals;
- this.code_blocks = code_blocks;
- this.scope_vars = scope_vars;
- this.flags = flags;
- index = -1;
- Token = token;
- CompileUnitIndex = comp_unit.Index;
- CompileUnit = comp_unit;
- NamespaceID = namespace_id;
- CheckLineNumberTable (lines);
- lnt = new LineNumberTable (file, lines);
- file.NumLineNumbers += lines.Length;
- int num_locals = locals != null ? locals.Length : 0;
- if (num_locals <= 32) {
- // Most of the time, the O(n^2) factor is actually
- // less than the cost of allocating the hash table,
- // 32 is a rough number obtained through some testing.
- for (int i = 0; i < num_locals; i ++) {
- string nm = locals [i].Name;
- for (int j = i + 1; j < num_locals; j ++) {
- if (locals [j].Name == nm) {
- flags |= Flags.LocalNamesAmbiguous;
- goto locals_check_done;
- }
- }
- }
- locals_check_done :
- ;
- } else {
- var local_names = new Dictionary<string, LocalVariableEntry> ();
- foreach (LocalVariableEntry local in locals) {
- if (local_names.ContainsKey (local.Name)) {
- flags |= Flags.LocalNamesAmbiguous;
- break;
- }
- local_names.Add (local.Name, local);
- }
- }
- }
- static void CheckLineNumberTable (LineNumberEntry[] line_numbers)
- {
- int last_offset = -1;
- int last_row = -1;
- if (line_numbers == null)
- return;
- for (int i = 0; i < line_numbers.Length; i++) {
- LineNumberEntry line = line_numbers [i];
- if (line.Equals (LineNumberEntry.Null))
- throw new MonoSymbolFileException ();
- if (line.Offset < last_offset)
- throw new MonoSymbolFileException ();
- if (line.Offset > last_offset) {
- last_row = line.Row;
- last_offset = line.Offset;
- } else if (line.Row > last_row) {
- last_row = line.Row;
- }
- }
- }
- internal void Write (MyBinaryWriter bw)
- {
- if ((index <= 0) || (DataOffset == 0))
- throw new InvalidOperationException ();
- bw.Write (Token);
- bw.Write (DataOffset);
- bw.Write (LineNumberTableOffset);
- }
- internal void WriteData (MonoSymbolFile file, MyBinaryWriter bw)
- {
- if (index <= 0)
- throw new InvalidOperationException ();
- LocalVariableTableOffset = (int) bw.BaseStream.Position;
- int num_locals = locals != null ? locals.Length : 0;
- bw.WriteLeb128 (num_locals);
- for (int i = 0; i < num_locals; i++)
- locals [i].Write (file, bw);
- file.LocalCount += num_locals;
- CodeBlockTableOffset = (int) bw.BaseStream.Position;
- int num_code_blocks = code_blocks != null ? code_blocks.Length : 0;
- bw.WriteLeb128 (num_code_blocks);
- for (int i = 0; i < num_code_blocks; i++)
- code_blocks [i].Write (bw);
- ScopeVariableTableOffset = (int) bw.BaseStream.Position;
- int num_scope_vars = scope_vars != null ? scope_vars.Length : 0;
- bw.WriteLeb128 (num_scope_vars);
- for (int i = 0; i < num_scope_vars; i++)
- scope_vars [i].Write (bw);
- if (real_name != null) {
- RealNameOffset = (int) bw.BaseStream.Position;
- bw.Write (real_name);
- }
- foreach (var lne in lnt.LineNumbers) {
- if (lne.EndRow != -1 || lne.EndColumn != -1)
- flags |= Flags.EndInfoIncluded;
- }
- LineNumberTableOffset = (int) bw.BaseStream.Position;
- lnt.Write (file, bw, (flags & Flags.ColumnsInfoIncluded) != 0, (flags & Flags.EndInfoIncluded) != 0);
- DataOffset = (int) bw.BaseStream.Position;
- bw.WriteLeb128 (CompileUnitIndex);
- bw.WriteLeb128 (LocalVariableTableOffset);
- bw.WriteLeb128 (NamespaceID);
- bw.WriteLeb128 (CodeBlockTableOffset);
- bw.WriteLeb128 (ScopeVariableTableOffset);
- bw.WriteLeb128 (RealNameOffset);
- bw.WriteLeb128 ((int) flags);
- }
- public void ReadAll ()
- {
- GetLineNumberTable ();
- GetLocals ();
- GetCodeBlocks ();
- GetScopeVariables ();
- GetRealName ();
- }
- public LineNumberTable GetLineNumberTable ()
- {
- lock (SymbolFile) {
- if (lnt != null)
- return lnt;
- if (LineNumberTableOffset == 0)
- return null;
- MyBinaryReader reader = SymbolFile.BinaryReader;
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = LineNumberTableOffset;
- lnt = LineNumberTable.Read (SymbolFile, reader, (flags & Flags.ColumnsInfoIncluded) != 0, (flags & Flags.EndInfoIncluded) != 0);
- reader.BaseStream.Position = old_pos;
- return lnt;
- }
- }
- public LocalVariableEntry[] GetLocals ()
- {
- lock (SymbolFile) {
- if (locals != null)
- return locals;
- if (LocalVariableTableOffset == 0)
- return null;
- MyBinaryReader reader = SymbolFile.BinaryReader;
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = LocalVariableTableOffset;
- int num_locals = reader.ReadLeb128 ();
- locals = new LocalVariableEntry [num_locals];
- for (int i = 0; i < num_locals; i++)
- locals [i] = new LocalVariableEntry (SymbolFile, reader);
- reader.BaseStream.Position = old_pos;
- return locals;
- }
- }
- public CodeBlockEntry[] GetCodeBlocks ()
- {
- lock (SymbolFile) {
- if (code_blocks != null)
- return code_blocks;
- if (CodeBlockTableOffset == 0)
- return null;
- MyBinaryReader reader = SymbolFile.BinaryReader;
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = CodeBlockTableOffset;
- int num_code_blocks = reader.ReadLeb128 ();
- code_blocks = new CodeBlockEntry [num_code_blocks];
- for (int i = 0; i < num_code_blocks; i++)
- code_blocks [i] = new CodeBlockEntry (i, reader);
- reader.BaseStream.Position = old_pos;
- return code_blocks;
- }
- }
- public ScopeVariable[] GetScopeVariables ()
- {
- lock (SymbolFile) {
- if (scope_vars != null)
- return scope_vars;
- if (ScopeVariableTableOffset == 0)
- return null;
- MyBinaryReader reader = SymbolFile.BinaryReader;
- long old_pos = reader.BaseStream.Position;
- reader.BaseStream.Position = ScopeVariableTableOffset;
- int num_scope_vars = reader.ReadLeb128 ();
- scope_vars = new ScopeVariable [num_scope_vars];
- for (int i = 0; i < num_scope_vars; i++)
- scope_vars [i] = new ScopeVariable (reader);
- reader.BaseStream.Position = old_pos;
- return scope_vars;
- }
- }
- public string GetRealName ()
- {
- lock (SymbolFile) {
- if (real_name != null)
- return real_name;
- if (RealNameOffset == 0)
- return null;
- real_name = SymbolFile.BinaryReader.ReadString (RealNameOffset);
- return real_name;
- }
- }
- public int CompareTo (object obj)
- {
- MethodEntry method = (MethodEntry) obj;
- if (method.Token < Token)
- return 1;
- else if (method.Token > Token)
- return -1;
- else
- return 0;
- }
- public override string ToString ()
- {
- return String.Format ("[Method {0}:{1:x}:{2}:{3}]",
- index, Token, CompileUnitIndex, CompileUnit);
- }
- }
- public struct NamespaceEntry
- {
- #region This is actually written to the symbol file
- public readonly string Name;
- public readonly int Index;
- public readonly int Parent;
- public readonly string[] UsingClauses;
- #endregion
- public NamespaceEntry (string name, int index, string[] using_clauses, int parent)
- {
- this.Name = name;
- this.Index = index;
- this.Parent = parent;
- this.UsingClauses = using_clauses != null ? using_clauses : new string [0];
- }
- internal NamespaceEntry (MonoSymbolFile file, MyBinaryReader reader)
- {
- Name = reader.ReadString ();
- Index = reader.ReadLeb128 ();
- Parent = reader.ReadLeb128 ();
- int count = reader.ReadLeb128 ();
- UsingClauses = new string [count];
- for (int i = 0; i < count; i++)
- UsingClauses [i] = reader.ReadString ();
- }
- internal void Write (MonoSymbolFile file, MyBinaryWriter bw)
- {
- bw.Write (Name);
- bw.WriteLeb128 (Index);
- bw.WriteLeb128 (Parent);
- bw.WriteLeb128 (UsingClauses.Length);
- foreach (string uc in UsingClauses)
- bw.Write (uc);
- }
- public override string ToString ()
- {
- return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent);
- }
- }
- }
|