dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Dotgnu-pnet-commits] CVS: pnetlib/ISymWrapper .cvsignore, NONE, 1.1 ISy


From: Rhys Weatherley <address@hidden>
Subject: [Dotgnu-pnet-commits] CVS: pnetlib/ISymWrapper .cvsignore, NONE, 1.1 ISymUnmanaged.cs, NONE, 1.1 ISymWrapper.build, NONE, 1.1 Makefile.am, NONE, 1.1 SymBinder.cs, NONE, 1.1 SymDocument.cs, NONE, 1.1 SymDocumentWriter.cs, NONE, 1.1 SymInfoEnumerator.cs, NONE, 1.1 SymMethod.cs, NONE, 1.1 SymReader.cs, NONE, 1.1 SymScope.cs, NONE, 1.1 SymVariable.cs, NONE, 1.1 SymWriter.cs, NONE, 1.1 Utils.cs, NONE, 1.1
Date: Fri, 19 Sep 2003 20:30:53 -0400

Update of /cvsroot/dotgnu-pnet/pnetlib/ISymWrapper
In directory subversions:/tmp/cvs-serv4424/ISymWrapper

Added Files:
        .cvsignore ISymUnmanaged.cs ISymWrapper.build Makefile.am 
        SymBinder.cs SymDocument.cs SymDocumentWriter.cs 
        SymInfoEnumerator.cs SymMethod.cs SymReader.cs SymScope.cs 
        SymVariable.cs SymWriter.cs Utils.cs 
Log Message:


Add the "ISymWrapper" assembly, which provides API's for reading
debug symbol tables.


--- NEW FILE ---
Makefile
Makefile.in
.deps
*.dll

--- NEW FILE ---
/*
 * ISymUnmanaged.cs - Implementation of unmanaged classes for C++ interop.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#if CONFIG_EXTENDED_DIAGNOSTICS

using System;
using Microsoft.VisualC;
using System.Runtime.InteropServices;

// We don't use these types - they are for backwards-compatibility only.

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct ISymUnmanagedBinder
{
}; // struct ISymUnmanagedBinder

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct ISymUnmanagedDocument
{
}; // struct ISymUnmanagedDocument

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct ISymUnmanagedDocumentWriter
{
}; // struct ISymUnmanagedDocumentWriter

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct ISymUnmanagedMethod
{
}; // struct ISymUnmanagedMethod

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct ISymUnmanagedReader
{
}; // struct ISymUnmanagedReader

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct ISymUnmanagedScope
{
}; // struct ISymUnmanagedScope

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct ISymUnmanagedVariable
{
}; // struct ISymUnmanagedVariable

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct ISymUnmanagedWriter
{
}; // struct ISymUnmanagedWriter

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct IUnknown
{
}; // struct IUnknown

[StructLayout(LayoutKind.Sequential, Size=4, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct IStream
{
}; // struct IStream

[StructLayout(LayoutKind.Sequential, Size=16, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct _GUID
{
}; // struct _GUID

[StructLayout(LayoutKind.Sequential, Size=16, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct tagPROPVARIANT
{
}; // struct tagPROPVARIANT

[StructLayout(LayoutKind.Sequential, Size=16, Pack=1)]
[DebugInfoInPDB]
[MiscellaneousBits(0x0041)]
public struct tagVARIANT
{
}; // struct tagVARIANT

#if __CSCC__

__module
{
        // Some global rubbish to keep Managed C++ applications happy.

        public static _GUID CLSID_CorSymBinder_SxS;
        public static _GUID CLSID_CorSymWriter_SxS;
        public static _GUID IID_ISymUnmanagedBinder;
        public static _GUID IID_ISymUnmanagedWriter;
        public unsafe static int CoCreateInstance
                                (_GUID *A_0, IUnknown *A_1, uint A_2,
                                 _GUID *A_3, void **A_4)
                        {
                                return 0;
                        }
        public unsafe static void @delete(void *A_0) {}
        public unsafe static void address@hidden(uint A_0)
                        {
                                return null;
                        }

}; // __module

#endif // __CSCC__

#endif // CONFIG_EXTENDED_DIAGNOSTICS

--- NEW FILE ---
<?xml version="1.0"?>
<project name="pnetlib ISymWrapper" default="all">
        <target name="all">

                <!-- Build the primary ISymWrapper.dll library -->
                <compile output="ISymWrapper.dll"
                                 target="library"
                                 unsafe="true"
                                 nostdlib="true"
                                 debug="${CONFIG_DEBUG_LINES}"
                                 optimize="true">

                        <sources>
                                <includes name="**/*.cs"/>
                                <excludes name="symtest.cs"/>
                        </sources>

                        <references>
                                <file name="../compat/Microsoft.VisualC.dll"/>
                                <file name="../runtime/mscorlib.dll"/>
                        </references>

                        <arg compiler="cscc" value="-Wno-empty-input"/>
                        <!-- arg compiler="cscc" value="-fminimize-parameters"/ 
-->
                        <arg compiler="cscc" value="-flatin1-charset"/>
                        <arg compiler="csc" value="/nowarn:626"/>
                        <arg compiler="csc" value="/nowarn:649"/>
                        <arg compiler="csc" value="/nowarn:168"/>
                        <arg compiler="csc" value="/nowarn:67"/>
                        <arg compiler="csc" value="/nowarn:169"/>
                        <arg compiler="csc" value="/nowarn:679"/>
                </compile>

        </target>
</project>

--- NEW FILE ---

.PHONY: ISymWrapper.dll

all-local: ISymWrapper.dll

ISymWrapper.dll:
        "$(CSANT)" $(CSANT_FLAGS) -f ISymWrapper.build all

CLEANFILES = ISymWrapper.dll

pnetassembliesdir = $(libdir)/cscc/lib
pnetassemblies_DATA = ISymWrapper.dll

--- NEW FILE ---
/*
 * SymBinder.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymBinder" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

using System.IO;

public class SymBinder : ISymbolBinder
{
        // Constructor.
        public SymBinder() {}

        // Destructor (C++ style).
        ~SymBinder() {}
        public void __dtor()
                        {
                                GC.SuppressFinalize(this);
                                Finalize();
                        }

        // Create a symbol reader for a file.  Will set "wasBinary" to
        // true if the file is a PE/COFF binary that does not contain
        // debug symbol information.  Returns null if the file does not
        // contain debug symbol information.
        private static ISymbolReader CreateReader
                                (String filename, out bool wasBinary)
                        {
                                FileStream stream;
                                byte[] buffer = new byte [1024];
                                byte[] section;
                                int len, offset;

                                // Clear the "wasBinary" flag before we start.
                                wasBinary = false;

                                // Open the file.
                                try
                                {
                                        stream = new FileStream
                                                (filename, FileMode.Open, 
FileAccess.Read);
                                }
                                catch(Exception)
                                {
                                        return null;
                                }
                                try
                                {
                                        // Check the magic number to determine 
the file type.
                                        if(stream.Read(buffer, 0, 8) != 8)
                                        {
                                                return null;
                                        }
                                        if(buffer[0] == (byte)'I' &&
                                           buffer[1] == (byte)'L' &&
                                           buffer[2] == (byte)'D' &&
                                           buffer[3] == (byte)'B' &&
                                           buffer[4] == (byte)0x01 &&
                                           buffer[5] == (byte)0x00 &&
                                           buffer[6] == (byte)0x00 &&
                                           buffer[7] == (byte)0x00)
                                        {
                                                // This is a standalone debug 
symbol file.
                                                len = (int)(stream.Length);
                                                section = new byte [len];
                                                Array.Copy(buffer, 0, section, 
0, 8);
                                                stream.Read(section, 8, len - 
8);
                                                return new SymReader(filename, 
section);
                                        }
                                        else if(buffer[0] == (byte)'M' &&
                                                        buffer[1] == (byte)'Z')
                                        {
                                                // We are processing a binary 
for embedded symbols.
                                                wasBinary = true;

                                                // Skip past the MS-DOS stub 
portion of the binary.
                                                stream.Read(buffer, 8, 64 - 8);
                                                offset = 
Utils.ReadInt32(buffer, 60);
                                                if(offset < 64)
                                                {
                                                        return null;
                                                }
                                                stream.Position = offset;

                                                // Read the PE/COFF header.
                                                stream.Read(buffer, 0, 24);
                                                if(buffer[0] != (byte)'P' ||
                                                   buffer[1] != (byte)'E' ||
                                                   buffer[2] != (byte)0x00 ||
                                                   buffer[3] != (byte)0x00)
                                                {
                                                        return null;
                                                }
                                                Array.Copy(buffer, 4, buffer, 
0, 20);
                                        }
                                        else if(buffer[0] == (byte)0x4C &&
                                                        buffer[1] == (byte)0x01)
                                        {
                                                // This is a PE/COFF object 
file: read the rest
                                                // of the PE/COFF header into 
memory.
                                                stream.Read(buffer, 8, 20 - 8);
                                        }
                                        else
                                        {
                                                // We don't know what format 
the file is in.
                                                return null;
                                        }

                                        // If we get here, then we have a 
PE/COFF header
                                        // in "buffer", minus the "PE".
                                        int numSections = 
Utils.ReadUInt16(buffer, 2);
                                        int headerSize = 
Utils.ReadUInt16(buffer, 16);
                                        if(headerSize != 0 &&
                                           (headerSize < 216 || headerSize > 
1024))
                                        {
                                                return null;
                                        }
                                        if(numSections == 0)
                                        {
                                                return null;
                                        }

                                        // Skip the optional header.
                                        stream.Seek(headerSize, 
SeekOrigin.Current);

                                        // Search the section table for 
".ildebug".
                                        while(numSections > 0)
                                        {
                                                if(stream.Read(buffer, 0, 40) 
!= 40)
                                                {
                                                        return null;
                                                }
                                                if(buffer[0] == (byte)'.' &&
                                                   buffer[1] == (byte)'i' &&
                                                   buffer[2] == (byte)'l' &&
                                                   buffer[3] == (byte)'d' &&
                                                   buffer[4] == (byte)'e' &&
                                                   buffer[5] == (byte)'b' &&
                                                   buffer[6] == (byte)'u' &&
                                                   buffer[7] == (byte)'g')
                                                {
                                                        // Skip to the debug 
data and read it.
                                                        offset = 
Utils.ReadInt32(buffer, 20);
                                                        len = 
Utils.ReadInt32(buffer, 8);
                                                        stream.Position = 
offset;
                                                        section = new byte 
[len];
                                                        stream.Read(section, 0, 
len);
                                                        return new 
SymReader(filename, section);
                                                }
                                                --numSections;
                                        }
                                }
                                finally
                                {
                                        stream.Close();
                                }

                                // We were unable to find the debug symbols if 
we get here.
                                return null;
                        }

        // Get a symbol reader for a particular file.
        public virtual ISymbolReader GetReader
                                (int importer, String filename, String 
searchPath)
                        {
                                // Try the file in its specified location.
                                if(File.Exists(filename))
                                {
                                        return GetReader(filename);
                                }

                                // Bail out if the filename was absolute, or 
there is no path.
                                if(Path.IsPathRooted(filename))
                                {
                                        throw new ArgumentException();
                                }
                                else if(searchPath == null || searchPath.Length 
== 0)
                                {
                                        throw new ArgumentException();
                                }

                                // Search the path for the file.
                                int posn = 0;
                                int index1, index2;
                                String dir;
                                String combined;
                                while(posn < searchPath.Length)
                                {
                                        // Find the next path separator.
                                        index1 = 
searchPath.IndexOf(Path.PathSeparator, posn);
                                        if(Path.PathSeparator == ':')
                                        {
                                                // Unix-like system: use either 
":" or ";" to separate.
                                                index2 = 
searchPath.IndexOf(';', posn);
                                                if(index2 != -1 && index2 < 
index1)
                                                {
                                                        index1 = index2;
                                                }
                                        }
                                        if(index1 == -1)
                                        {
                                                index1 = searchPath.Length;
                                        }

                                        // Extract the directory from the path.
                                        dir = searchPath.Substring(posn, index1 
- posn).Trim();
                                        posn = index1 + 1;
                                        if(dir.Length == 0)
                                        {
                                                continue;
                                        }

                                        // See if the specified file exists.
                                        combined = Path.Combine(dir, filename);
                                        if(File.Exists(combined))
                                        {
                                                return GetReader(combined);
                                        }
                                }

                                // We were unable to find the file.
                                throw new ArgumentException();
                        }
        private static ISymbolReader GetReader(String filename)
                        {
                                ISymbolReader reader;
                                bool wasBinary;

                                // Try to create a symbol reader for the file 
itself.
                                reader = CreateReader(filename, out wasBinary);
                                if(reader != null)
                                {
                                        return reader;
                                }

                                // If the file was a PE/COFF binary that does 
not
                                // include debug symbol information, then look 
for
                                // the "*.pdb" file corresponding to the binary.
                                if(wasBinary)
                                {
                                        filename = 
Path.ChangeExtension(filename, "pdb");
                                        reader = CreateReader(filename, out 
wasBinary);
                                        if(reader != null)
                                        {
                                                return reader;
                                        }
                                }

                                // We were unable to locate the debug symbols.
                                throw new ArgumentException();
                        }

}; // class SymBinder

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * SymDocument.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymDocument" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

using System.IO;

public class SymDocument : ISymbolDocument
{
        // Internal state.
        private unsafe ISymUnmanagedDocument *pDocument;
        private SymReader reader;
        private String language;
        private String url;

        // Constructors.
        public unsafe SymDocument(ISymUnmanagedDocument *pDocument)
                        {
                                this.pDocument = pDocument;
                        }
        internal SymDocument(SymReader reader, String language, String url)
                        {
                                this.reader = reader;
                                this.language = language;
                                this.url = url;
                        }

        // Destructor (C++ style).
        ~SymDocument() {}
        public void __dtor()
                        {
                                GC.SuppressFinalize(this);
                                Finalize();
                        }

        // Get the unmanaged version of this document.
        public unsafe ISymUnmanagedDocument *GetUnmanaged()
                        {
                                return pDocument;
                        }

        // Implement the ISymbolDocument interface.
        public virtual int FindClosestLine(int line)
                        {
                                // Not used in this implementation.
                                return line;
                        }
        public virtual byte[] GetCheckSum()
                        {
                                throw new NotSupportedException();
                        }
        public virtual byte[] GetSourceRange
                                (int startLine, int startColumn, int endLine, 
int endColumn)
                        {
                                throw new NotSupportedException();
                        }
        public virtual Guid CheckSumAlgorithmId 
                        {
                                get
                                {
                                        throw new NotSupportedException();
                                }
                        }
        public virtual Guid DocumentType 
                        {
                                get
                                {
                                        // We assume that all source code is 
text-based.
                                        return SymDocumentType.Text;
                                }
                        }
        public virtual bool HasEmbeddedSource 
                        {
                                get
                                {
                                        // We never store source documents in 
the symbol data.
                                        return false;
                                }
                        }
        public virtual Guid Language 
                        {
                                get
                                {
                                        String ext = language;
                                        if(ext == null)
                                        {
                                                // If we don't have an explicit 
language specification,
                                                // then use the extension on 
the URL.
                                                String url = URL;
                                                if(url != null)
                                                {
                                                        ext = 
Path.GetExtension(url);
                                                }
                                        }
                                        if(ext == null)
                                        {
                                                return SymLanguageType.CSharp;
                                        }
                                        ext = ext.ToLower();
                                        switch(ext)
                                        {
                                                case "bas": case "basic": case 
"vb": case "vb.net":
                                                case "visualbasic": case 
"visualbasic.net":
                                                        return 
SymLanguageType.Basic;
                                                case "c": case "h":
                                                        return 
SymLanguageType.C;
                                                case "cob": case "cobol":
                                                        return 
SymLanguageType.Cobol;
                                                case "cpp": case "cxx": case 
"cc": case "cplusplus":
                                                case "hpp": case "hxx": case 
"hh":
                                                        return 
SymLanguageType.CPlusPlus;
                                                case "cs": case "csharp":
                                                        return 
SymLanguageType.CSharp;
                                                case "il": case "iltmp": case 
"ilasm":
                                                case "ilassembly":
                                                        return 
SymLanguageType.ILAssembly;
                                                case "java": case "jav":
                                                        return 
SymLanguageType.Java;
                                                case "js": case "jscript":
                                                        return 
SymLanguageType.JScript;
                                                case "mcpp": case "mcxx": case 
"mcc":
                                                case "mcplusplus": case "mhpp": 
case "mhxx":
                                                case "mhh":
                                                        return 
SymLanguageType.MCPlusPlus;
                                                case "pas": case "pascal":
                                                        return 
SymLanguageType.Pascal;
                                                case "smc":
                                                        return 
SymLanguageType.SMC;
                                                default: break;
                                        }
                                        return SymLanguageType.CSharp;
                                }
                        }
        public virtual Guid LanguageVendor 
                        {
                                get
                                {
                                        // For backwards-compatibility only.
                                        return SymLanguageVendor.Microsoft;
                                }
                        }
        public virtual int SourceLength 
                        {
                                get
                                {
                                        // We never store source documents in 
the symbol data.
                                        return 0;
                                }
                        }
        public virtual String URL 
                        {
                                get
                                {
                                        return url;
                                }
                        }

}; // class SymDocument

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * SymDocumentWriter.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymDocumentWriter" 
class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

public class SymDocumentWriter : ISymbolDocumentWriter
{
        // Internal state.
        private unsafe ISymUnmanagedDocumentWriter *pDocumentWriter;

        // Constructors.
        public unsafe SymDocumentWriter
                                (ISymUnmanagedDocumentWriter *pDocumentWriter)
                        {
                                this.pDocumentWriter = pDocumentWriter;
                        }
        internal SymDocumentWriter() {}

        // Destructor (C++ style).
        ~SymDocumentWriter() {}
        public void __dtor()
                        {
                                GC.SuppressFinalize(this);
                                Finalize();
                        }

        // Get the unmanaged version of this document.
        public unsafe ISymUnmanagedDocumentWriter *GetUnmanaged()
                        {
                                return pDocumentWriter;
                        }

        // Implement the ISymbolDocumentWriter interface.
        public virtual void SetCheckSum(Guid algorithmId, byte[] checkSum)
                        {
                                throw new NotSupportedException();
                        }
        public virtual void SetSource(byte[] source)
                        {
                                throw new NotSupportedException();
                        }

}; // class SymDocumentWriter

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * SymInfoEnumerator.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymInfoEnumerator" 
class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

using System.Collections;

// Utility class for enumerating over all of the data blocks
// that are associated with a particular token.

internal class SymInfoEnumerator : IEnumerator
{
        // Internal state.
        private SymReader reader;
        private int token;
        private int start;
        private int num;
        private int index;
        private int type;
        private int offset;
        private int length;
        private int readPosn;

        // Constructors.
        public SymInfoEnumerator(SymReader reader, String name)
                        : this(reader, Utils.CreatePseudoToken(name)) {}
        public SymInfoEnumerator(SymReader reader, int token)
                        {
                                // Save the reader and token information for 
later.
                                this.reader = reader;
                                this.token = token;
                                this.index = -1;
                                if(reader == null || reader.data == null)
                                {
                                        // There is no symbol information to be 
processed.
                                        this.start = 0;
                                        this.num = 0;
                                        return;
                                }

                                // Locate the token information in the symbol 
data.
                                int left = 0;
                                int right = reader.numIndexEntries - 1;
                                int middle, temp;
                                while(left <= right)
                                {
                                        middle = left + (right - left) / 2;
                                        temp = Utils.ReadInt32
                                                (reader.data, 
reader.indexOffset + middle * 8);
                                        if(((uint)temp) < ((uint)token))
                                        {
                                                left = middle + 1;
                                        }
                                        else if(((uint)temp) > ((uint)token))
                                        {
                                                right = middle - 1;
                                        }
                                        else
                                        {
                                                // We've found an entry: search 
forwards and
                                                // backwards to find the extent 
of the token.
                                                left = middle;
                                                while(left > 0)
                                                {
                                                        temp = Utils.ReadInt32
                                                                (reader.data,
                                                                 
reader.indexOffset + (left - 1) * 8);
                                                        if(temp == token)
                                                        {
                                                                --left;
                                                        }
                                                        else
                                                        {
                                                                break;
                                                        }
                                                }
                                                right = middle;
                                                while(right < 
(reader.numIndexEntries - 1))
                                                {
                                                        temp = Utils.ReadInt32
                                                                (reader.data,
                                                                 
reader.indexOffset + (right + 1) * 8);
                                                        if(temp == token)
                                                        {
                                                                ++right;
                                                        }
                                                        else
                                                        {
                                                                break;
                                                        }
                                                }
                                                this.start = left;
                                                this.num = right - left + 1;
                                                return;
                                        }
                                }

                                // We were unable to find the token data.
                                this.start = 0;
                                this.num = 0;
                        }
        public SymInfoEnumerator(SymReader reader)
                        {
                                // This version enumerates over all of the data 
blocks.
                                this.reader = reader;
                                this.token = 0;
                                this.start = 0;
                                if(reader != null)
                                {
                                        this.num = reader.numIndexEntries;
                                }
                                else
                                {
                                        this.num = 0;
                                }
                                this.index = -1;
                        }

        // Implement the IEnumerator interface.
        public bool MoveNext()
                        {
                                if(++index < num)
                                {
                                        // Read the information about this data 
block.
                                        token = Utils.ReadInt32
                                                (reader.data,
                                                 reader.indexOffset + (start + 
index) * 8);
                                        offset = Utils.ReadInt32
                                                (reader.data,
                                                 reader.indexOffset + (start + 
index) * 8 + 4);
                                        if(offset < 0 || offset >= 
reader.data.Length)
                                        {
                                                return false;
                                        }

                                        // Get the type and length information.
                                        int size;
                                        type = Utils.ReadMetaInt
                                                (reader.data, offset, out size);
                                        offset += size;
                                        length = Utils.ReadMetaInt
                                                (reader.data, offset, out size);
                                        offset += size;
                                        if(length < 0 || (reader.data.Length - 
offset) < length)
                                        {
                                                return false;
                                        }

                                        // Ready to process this data item.
                                        readPosn = offset;
                                        return true;
                                }
                                else
                                {
                                        return false;
                                }
                        }
        public void Reset()
                        {
                                index = -1;
                        }
        public Object Current
                        {
                                get
                                {
                                        return token;
                                }
                        }

        // Get the number of data blocks that will be enumerated.
        public int Count
                        {
                                get
                                {
                                        return num;
                                }
                        }

        // Get additional information about the data block.
        public int Token
                        {
                                get
                                {
                                        return token;
                                }
                        }
        public int Type
                        {
                                get
                                {
                                        return type;
                                }
                        }
        public int Offset
                        {
                                get
                                {
                                        return offset;
                                }
                        }
        public int Length
                        {
                                get
                                {
                                        return length;
                                }
                        }
        public byte[] Data
                        {
                                get
                                {
                                        byte[] data = new byte [length];
                                        Array.Copy(reader.data, offset, data, 
0, length);
                                        return data;
                                }
                        }

        // Get the next metadata-encoded integer from the data section.
        public int GetNextInt()
                        {
                                int value, size;
                                if(readPosn < (offset + length))
                                {
                                        value = Utils.ReadMetaInt(reader.data, 
readPosn, out size);
                                        readPosn += size;
                                        return value;
                                }
                                else
                                {
                                        return -1;
                                }
                        }

}; // class SymInfoEnumerator

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * SymMethod.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymMethod" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

using System.Collections;

public class SymMethod : ISymbolMethod
{
        // Internal state.
        private unsafe ISymUnmanagedMethod *pMethod;
        private SymReader reader;
        private int token;
        private SymScope rootScope;
        private ArrayList sequencePoints;

        // Information about a sequence point.
        private class SequencePoint
        {
                // Accessible internal state.
                public int offset;
                public ISymbolDocument document;
                public int line;
                public int column;

                // Constructor.
                public SequencePoint(int offset, ISymbolDocument document,
                                                         int line, int column)
                                {
                                        this.offset = offset;
                                        this.document = document;
                                        this.line = line;
                                        this.column = column;
                                }

        }; // class SequencePoint

        // Comparison class for sorting on ascending offset.
        private class SequencePointComparer : IComparer
        {
                // Compare two sequence points.
                public int Compare(Object x, Object y)
                                {
                                        return ((SequencePoint)x).offset -
                                                   ((SequencePoint)y).offset;
                                }

        }; // class SequencePointComparer

        // Constructors.
        public unsafe SymMethod(ISymUnmanagedMethod *pMethod)
                        {
                                this.pMethod = pMethod;
                        }
        internal SymMethod(SymReader reader, int token)
                        {
                                this.reader = reader;
                                this.token = token;
                        }

        // Destructor (C++ style).
        ~SymMethod() {}
        public void __dtor()
                        {
                                GC.SuppressFinalize(this);
                                Finalize();
                        }

        // Implement the ISymbolMethod interface.
        public virtual ISymbolNamespace GetNamespace()
                        {
                                throw new NotSupportedException();
                        }
        public virtual int GetOffset
                                (ISymbolDocument document, int line, int column)
                        {
                                // Load the sequence point information.
                                LoadSequencePoints();

                                // Search for an applicable block, based on the 
line number.
                                int index;
                                SequencePoint seq1;
                                SequencePoint seq2;
                                for(index = 0; index < sequencePoints.Count; 
++index)
                                {
                                        seq1 = 
(SequencePoint)(sequencePoints[index]);
                                        if(line >= seq1.line)
                                        {
                                                if(index < sequencePoints.Count 
- 1)
                                                {
                                                        seq2 = 
(SequencePoint)(sequencePoints[index + 1]);
                                                        if(line < seq2.line)
                                                        {
                                                                if(document == 
null || seq1.document == null ||
                                                                   document.URL 
== seq1.document.URL)
                                                                {
                                                                        return 
seq1.offset;
                                                                }
                                                        }
                                                }
                                                else
                                                {
                                                        if(document == null || 
seq1.document == null ||
                                                           document.URL == 
seq1.document.URL)
                                                        {
                                                                return 
seq1.offset;
                                                        }
                                                }
                                        }
                                }

                                // Could not find the offset, so assume offset 
zero.
                                return 0;
                        }
        public virtual ISymbolVariable[] GetParameters()
                        {
                                // We don't store debug symbol information for
                                // parameters in this implementation, because
                                // parameter data can be retrieved from 
metadata.
                                return new ISymbolVariable [0];
                        }
        public virtual int[] GetRanges
                                (ISymbolDocument document, int line, int column)
                        {
                                // Not used in this implementation.
                                return new int [0];
                        }
        public virtual ISymbolScope GetScope(int offset)
                        {
                                SymScope scope = (SymScope)RootScope;
                                if(scope != null)
                                {
                                        return scope.FindOffset(offset);
                                }
                                else
                                {
                                        return null;
                                }
                        }
        public virtual void GetSequencePoints
                                        (int[] offsets, ISymbolDocument[] 
documents, 
                                         int[] lines, int[] columns, int[] 
endLines, 
                                         int[] endColumns)
                        {
                                int index;
                                LoadSequencePoints();
                                for(index = 0; index < sequencePoints.Count; 
++index)
                                {
                                        if(offsets != null && index < 
offsets.Length)
                                        {
                                                offsets[index] =
                                                        
((SequencePoint)(sequencePoints[index])).offset;
                                        }
                                        if(documents != null && index < 
documents.Length)
                                        {
                                                documents[index] =
                                                        
((SequencePoint)(sequencePoints[index])).document;
                                        }
                                        if(lines != null && index < 
lines.Length)
                                        {
                                                lines[index] = 
                                                        
((SequencePoint)(sequencePoints[index])).line;
                                        }
                                        if(columns != null && index < 
columns.Length)
                                        {
                                                columns[index] =
                                                        
((SequencePoint)(sequencePoints[index])).column;
                                        }
                                        if(endLines != null && index < 
endLines.Length)
                                        {
                                                // This information is not 
available.
                                                endLines[index] = 0;
                                        }
                                        if(endColumns != null && index < 
endColumns.Length)
                                        {
                                                // This information is not 
available.
                                                endColumns[index] = 0;
                                        }
                                }
                        }
        public virtual bool GetSourceStartEnd
                                        (ISymbolDocument[] docs, int[] lines, 
int[] columns)
                        {
                                throw new NotSupportedException();
                        }
        public virtual ISymbolScope RootScope 
                        {
                                get
                                {
                                        if(rootScope == null)
                                        {
                                                rootScope = new SymScope(this);
                                                LoadVariables();
                                        }
                                        return rootScope;
                                }
                        }
        public virtual int SequencePointCount 
                        {
                                get
                                {
                                        LoadSequencePoints();
                                        return sequencePoints.Count;
                                }
                        }
        public virtual SymbolToken Token 
                        {
                                get
                                {
                                        return new SymbolToken(token);
                                }
                        }

        // Load the local variable information.
        private void LoadVariables()
                        {
                                SymInfoEnumerator e;
                                int nameIndex, index;
                                int start, end;
                                SymScope childScope;
                                e = new SymInfoEnumerator(reader, token);
                                while(e.MoveNext())
                                {
                                        if(e.Type == 
SymReader.DataType_LocalVariables)
                                        {
                                                // Local variables within the 
root scope.
                                                while((nameIndex = 
e.GetNextInt()) != -1)
                                                {
                                                        index = e.GetNextInt();
                                                        rootScope.AddLocal
                                                                
(reader.ReadString(nameIndex), index);
                                                }
                                        }
                                        else if(e.Type == 
SymReader.DataType_LocalVariablesOffsets)
                                        {
                                                // Local variables within a 
child scope.
                                                start = e.GetNextInt();
                                                end = e.GetNextInt();
                                                childScope = 
rootScope.FindScope(end, start);
                                                while((nameIndex = 
e.GetNextInt()) != -1)
                                                {
                                                        index = e.GetNextInt();
                                                        childScope.AddLocal
                                                                
(reader.ReadString(nameIndex), index);
                                                }
                                        }
                                }
                        }

        // Load the sequence point information.
        private void LoadSequencePoints()
                        {
                                SymInfoEnumerator e;
                                String filename;
                                ISymbolDocument document;
                                int line, column, offset;

                                // Bail out if we have already loaded the 
sequence points.
                                if(sequencePoints != null)
                                {
                                        return;
                                }

                                // Create the sequence point list.
                                sequencePoints = new ArrayList();

                                // Load the sequence point information.
                                e = new SymInfoEnumerator(reader, token);
                                while(e.MoveNext())
                                {
                                        if(e.Type == 
SymReader.DataType_LineColumn)
                                        {
                                                // Block contains line and 
column values only.
                                                filename = 
reader.ReadString(e.GetNextInt());
                                                document = 
reader.GetDocument(filename);
                                                while((line = e.GetNextInt()) 
!= -1)
                                                {
                                                        column = e.GetNextInt();
                                                        sequencePoints.Add
                                                                (new 
SequencePoint(0, document, line, column));
                                                }
                                        }
                                        else if(e.Type == 
SymReader.DataType_LineOffsets)
                                        {
                                                // Block contains line and 
offset values only.
                                                filename = 
reader.ReadString(e.GetNextInt());
                                                document = 
reader.GetDocument(filename);
                                                while((line = e.GetNextInt()) 
!= -1)
                                                {
                                                        offset = e.GetNextInt();
                                                        sequencePoints.Add
                                                                (new 
SequencePoint(offset, document, line, 0));
                                                }
                                        }
                                        else if(e.Type == 
SymReader.DataType_LineColumnOffsets)
                                        {
                                                // Block contains line, column, 
and offset values.
                                                filename = 
reader.ReadString(e.GetNextInt());
                                                document = 
reader.GetDocument(filename);
                                                while((line = e.GetNextInt()) 
!= -1)
                                                {
                                                        column = e.GetNextInt();
                                                        offset = e.GetNextInt();
                                                        sequencePoints.Add
                                                                (new 
SequencePoint
                                                                        
(offset, document, line, column));
                                                }
                                        }
                                }

                                // Sort the sequence points on ascending offset.
                                sequencePoints.Sort(new 
SequencePointComparer());
                        }

}; // class SymMethod

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * SymReader.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymReader" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

using System.IO;
using System.Text;
using System.Collections;

public class SymReader : ISymbolReader
{
        // Internal state.
        private unsafe ISymUnmanagedReader *pReader;
        private String filename;
        private Encoding utf8;
        internal byte[] data;
        internal int indexOffset;
        internal int numIndexEntries;
        private int stringOffset;
        private int stringLength;
        private ISymbolDocument[] documents;
        private Hashtable documentCache;
        private Hashtable methodCache;

        // Types of data blocks within debug symbol data.
        internal const int DataType_LineColumn                          = 1;
        internal const int DataType_LineOffsets                         = 2;
        internal const int DataType_LineColumnOffsets           = 3;
        internal const int DataType_LocalVariables                      = 4;
        internal const int DataType_LocalVariablesOffsets       = 5;

        // Constructors.
        public unsafe SymReader(ISymUnmanagedReader *pReader)
                        {
                                this.pReader = pReader;
                        }
        internal SymReader(String filename, byte[] data)
                        {
                                // Store the parameters for later.
                                this.filename = filename;
                                this.data = data;

                                // We need the UTF8 encoding object to decode 
strings.
                                utf8 = Encoding.UTF8;

                                // Read and validate the header.
                                if(data.Length < 24)
                                {
                                        throw new ArgumentException();
                                }
                                if(data[0] != (byte)'I' ||
                                   data[1] != (byte)'L' ||
                                   data[2] != (byte)'D' ||
                                   data[3] != (byte)'B' ||
                                   data[4] != (byte)0x01 ||
                                   data[5] != (byte)0x00 ||
                                   data[6] != (byte)0x00 ||
                                   data[7] != (byte)0x00)
                                {
                                        throw new ArgumentException();
                                }
                                indexOffset = Utils.ReadInt32(data, 8);
                                numIndexEntries = Utils.ReadInt32(data, 12);
                                stringOffset = Utils.ReadInt32(data, 16);
                                stringLength = Utils.ReadInt32(data, 20);
                                if(indexOffset < 24 || indexOffset >= 
data.Length)
                                {
                                        throw new ArgumentException();
                                }
                                if(numIndexEntries < 0 ||
                                   ((data.Length - indexOffset) / 8) < 
numIndexEntries)
                                {
                                        throw new ArgumentException();
                                }
                                if(stringOffset < 24 || stringOffset >= 
data.Length)
                                {
                                        throw new ArgumentException();
                                }
                                if(stringLength <= 0 ||
                                   stringLength > (data.Length - stringOffset) 
||
                                   data[stringOffset + stringLength - 1] != 0)
                                {
                                        throw new ArgumentException();
                                }
                        }

        // Destructor (C++ style).
        ~SymReader() {}
        public void __dtor()
                        {
                                GC.SuppressFinalize(this);
                                Finalize();
                        }

        // Implement the ISymbolReader interface.
        public virtual ISymbolDocument GetDocument
                                (String url, Guid language, Guid languageVendor,
                                 Guid documentType)
                        {
                                String lang;

                                // Validate the url parameter.
                                if(url == null)
                                {
                                        throw new ArgumentNullException("url");
                                }

                                // Convert the language GUID into a language 
name.
                                // We ignore the vendor and document type, 
because
                                // they are not important.
                                if(language == SymLanguageType.Basic)
                                {
                                        lang = "basic";
                                }
                                else if(language == SymLanguageType.C)
                                {
                                        lang = "c";
                                }
                                else if(language == SymLanguageType.Cobol)
                                {
                                        lang = "cobol";
                                }
                                else if(language == SymLanguageType.CPlusPlus)
                                {
                                        lang = "cplusplus";
                                }
                                else if(language == SymLanguageType.CSharp)
                                {
                                        lang = "csharp";
                                }
                                else if(language == SymLanguageType.ILAssembly)
                                {
                                        lang = "ilassembly";
                                }
                                else if(language == SymLanguageType.Java)
                                {
                                        lang = "java";
                                }
                                else if(language == SymLanguageType.JScript)
                                {
                                        lang = "jscript";
                                }
                                else if(language == SymLanguageType.MCPlusPlus)
                                {
                                        lang = "mcplusplus";
                                }
                                else if(language == SymLanguageType.Pascal)
                                {
                                        lang = "pascal";
                                }
                                else if(language == SymLanguageType.SMC)
                                {
                                        lang = "smc";
                                }
                                else
                                {
                                        lang = null;
                                }

                                // Create a new document object for the URL and 
return it.
                                return new SymDocument(this, lang, url);
                        }
        public virtual ISymbolDocument[] GetDocuments()
                        {
                                // Bail out early if we already loaded the 
document list.
                                if(documents != null)
                                {
                                        return documents;
                                }

                                // Read the document information list from the 
symbol data.
                                ArrayList list = new ArrayList();
                                SymInfoEnumerator e = new 
SymInfoEnumerator(this);
                                String filename;
                                ISymbolDocument doc;
                                while(e.MoveNext())
                                {
                                        if(e.Type == DataType_LineColumn ||
                                           e.Type == DataType_LineOffsets ||
                                           e.Type == DataType_LineColumnOffsets)
                                        {
                                                filename = 
ReadString(e.GetNextInt());
                                                doc = GetDocument(filename);
                                                if(doc != null && 
!list.Contains(doc))
                                                {
                                                        list.Add(doc);
                                                }
                                        }
                                }

                                // Return the final document list.
                                documents = new ISymbolDocument [list.Count];
                                int index = 0;
                                foreach(ISymbolDocument d in list)
                                {
                                        documents[index++] = d;
                                }
                                return documents;
                        }
        public virtual ISymbolVariable[] GetGlobalVariables()
                        {
                                throw new NotSupportedException();
                        }
        public virtual ISymbolMethod GetMethod(SymbolToken method)
                        {
                                return GetMethod(method, 0);
                        }
        public virtual ISymbolMethod GetMethod(SymbolToken method, int version)
                        {
                                ISymbolMethod meth;
                                if(methodCache == null)
                                {
                                        methodCache = new Hashtable();
                                }
                                else if((meth = (ISymbolMethod)methodCache
                                                        [method.GetToken()]) != 
null)
                                {
                                        return meth;
                                }
                                meth = new SymMethod(this, method.GetToken());
                                methodCache[method.GetToken()] = meth;
                                return meth;
                        }
        public virtual ISymbolMethod GetMethodFromDocumentPosition
                                (ISymbolDocument document, int line, int column)
                        {
                                if(document == null || document.URL == null)
                                {
                                        return null;
                                }
                                SymInfoEnumerator e = new 
SymInfoEnumerator(this);
                                String filename;
                                ISymbolDocument doc;
                                int tempLine, tempColumn, tempOffset;
                                int closestBelow = 0;
                                int closestBelowToken = 0;
                                while(e.MoveNext())
                                {
                                        // We only check on line because column 
values
                                        // are likely to be inaccurate.
                                        if(e.Type == DataType_LineColumn)
                                        {
                                                filename = 
ReadString(e.GetNextInt());
                                                doc = GetDocument(filename);
                                                if(doc != null && doc.URL == 
document.URL)
                                                {
                                                        while((tempLine = 
e.GetNextInt()) != -1)
                                                        {
                                                                tempColumn = 
e.GetNextInt();
                                                                if(tempLine == 
line)
                                                                {
                                                                        return 
GetMethod(new SymbolToken(e.Token));
                                                                }
                                                                else 
if(tempLine < line &&
                                                                        
tempLine > closestBelow)
                                                                {
                                                                        
closestBelow = tempLine;
                                                                        
closestBelowToken = e.Token;
                                                                }
                                                        }
                                                }
                                        }
                                        else if(e.Type == DataType_LineOffsets)
                                        {
                                                filename = 
ReadString(e.GetNextInt());
                                                doc = GetDocument(filename);
                                                if(doc != null && doc.URL == 
document.URL)
                                                {
                                                        while((tempLine = 
e.GetNextInt()) != -1)
                                                        {
                                                                tempOffset = 
e.GetNextInt();
                                                                if(tempLine == 
line)
                                                                {
                                                                        return 
GetMethod(new SymbolToken(e.Token));
                                                                }
                                                                else 
if(tempLine < line &&
                                                                        
tempLine > closestBelow)
                                                                {
                                                                        
closestBelow = tempLine;
                                                                        
closestBelowToken = e.Token;
                                                                }
                                                        }
                                                }
                                        }
                                        else if(e.Type == 
DataType_LineColumnOffsets)
                                        {
                                                filename = 
ReadString(e.GetNextInt());
                                                doc = GetDocument(filename);
                                                if(doc != null && doc.URL == 
document.URL)
                                                {
                                                        while((tempLine = 
e.GetNextInt()) != -1)
                                                        {
                                                                tempColumn = 
e.GetNextInt();
                                                                tempOffset = 
e.GetNextInt();
                                                                if(tempLine == 
line)
                                                                {
                                                                        return 
GetMethod(new SymbolToken(e.Token));
                                                                }
                                                                else 
if(tempLine < line &&
                                                                        
tempLine > closestBelow)
                                                                {
                                                                        
closestBelow = tempLine;
                                                                        
closestBelowToken = e.Token;
                                                                }
                                                        }
                                                }
                                        }
                                }
                                if(closestBelowToken != 0)
                                {
                                        // Return the closest match that we 
found in the
                                        // document that is below the specified 
line.
                                        return GetMethod(new 
SymbolToken(closestBelowToken));
                                }
                                return null;
                        }
        public virtual ISymbolNamespace[] GetNamespaces()
                        {
                                throw new NotSupportedException();
                        }
        public virtual byte[] GetSymAttribute(SymbolToken parent, String name)
                        {
                                throw new NotSupportedException();
                        }
        public virtual ISymbolVariable[] GetVariables(SymbolToken parent)
                        {
                                throw new NotSupportedException();
                        }
        public virtual SymbolToken UserEntryPoint 
                        {
                                get
                                {
                                        // Not used in this implementation, 
because it
                                        // duplicates information available via 
metadata.
                                        return new SymbolToken(0);
                                }
                        }

        // Read a string value from the debug symbol information.
        internal String ReadString(int offset)
                        {
                                if(data == null)
                                {
                                        return String.Empty;
                                }
                                if(offset < 0 || offset >= stringLength)
                                {
                                        return String.Empty;
                                }
                                offset += stringOffset;
                                int len = 0;
                                while(data[offset + len] != 0)
                                {
                                        ++len;
                                }
                                return utf8.GetString(data, offset, len);
                        }

        // Convert a filename into a URL.
        internal String FilenameToURL(String name)
                        {
                                // Bail out if the name is empty.
                                if(name == null || name.Length == 0)
                                {
                                        return null;
                                }
                                
                                // Get the full absolute pathname for the file.
                                if(!Path.IsPathRooted(name) && filename != null)
                                {
                                        String temp = Path.Combine
                                                
(Path.GetDirectoryName(filename), name);
                                        if(File.Exists(temp))
                                        {
                                                name = temp;
                                        }
                                }
                                name = Path.GetFullPath(name);

                                // Normalize pathname separators to "/".
                                name = name.Replace('\\', '/');

                                // Add the "file:" prefix to the name to form 
the URL.
                                if(name.Length >= 2 && name[1] == ':')
                                {
                                        // The filename includes a 
Windows-style drive letter.
                                        return "file:/" + name;
                                }
                                else
                                {
                                        // The filename is absolute from a 
Unix-style root.
                                        return "file:" + name;
                                }
                        }

        // Get a document block for a particular filename.
        internal ISymbolDocument GetDocument(String filename)
                        {
                                ISymbolDocument document;

                                // Convert the filename into a full URL.
                                filename = FilenameToURL(filename);
                                if(filename == null)
                                {
                                        return null;
                                }

                                // See if we already have a document for this 
file.
                                if(documentCache == null)
                                {
                                        documentCache = new Hashtable();
                                }
                                else if((document = 
(ISymbolDocument)documentCache[filename])
                                                        != null)
                                {
                                        return document;
                                }

                                // Create a new document object and add it to 
the cache.
                                document = new SymDocument(this, null, 
filename);
                                documentCache[filename] = document;
                                return document;
                        }

}; // class SymReader

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * SymScope.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymScope" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

public class SymScope : ISymbolScope
{
        // Internal state.
        private unsafe ISymUnmanagedScope *pScope;
        private ISymbolMethod method;
        private ISymbolScope parent;
        private ISymbolScope[] children;
        private ISymbolVariable[] locals;
        private int endOffset;
        private int startOffset;

        // Constructors.
        public unsafe SymScope(ISymUnmanagedScope *pScope)
                        {
                                this.pScope = pScope;
                                this.children = new ISymbolScope [0];
                                this.locals = new ISymbolVariable [0];
                        }
        internal SymScope(ISymbolMethod method)
                        {
                                // Create the root scope for a method.
                                this.method = method;
                                this.parent = null;
                                this.children = new ISymbolScope [0];
                                this.locals = new ISymbolVariable [0];
                                this.endOffset = Int32.MaxValue;
                                this.startOffset = 0;
                        }
        private SymScope(SymScope parent, int endOffset, int startOffset)
                        {
                                // Create a new child scope.
                                this.method = parent.method;
                                this.parent = parent;
                                this.children = new ISymbolScope [0];
                                this.locals = new ISymbolVariable [0];
                                this.endOffset = endOffset;
                                this.startOffset = startOffset;
                        }

        // Destructor (C++ style).
        ~SymScope() {}
        public void __dtor()
                        {
                                GC.SuppressFinalize(this);
                                Finalize();
                        }

        // Implement the ISymbolScope interface.
        public virtual ISymbolScope[] GetChildren()
                        {
                                return children;
                        }
        public virtual ISymbolVariable[] GetLocals()
                        {
                                return locals;
                        }
        public virtual ISymbolNamespace[] GetNamespaces()
                        {
                                throw new NotSupportedException();
                        }
        public virtual int EndOffset 
                        {
                                get
                                {
                                        return endOffset;
                                }
                        }
        public virtual ISymbolMethod Method 
                        {
                                get
                                {
                                        return method;
                                }
                        }
        public virtual ISymbolScope Parent 
                        {
                                get
                                {
                                        return parent;
                                }
                        }
        public virtual int StartOffset 
                        {
                                get
                                {
                                        return startOffset;
                                }
                        }

        // Insert a new scope into this one at a particular position.
        private SymScope InsertScope(int index, int endOffset, int startOffset)
                        {
                                SymScope scope = new SymScope(this, endOffset, 
startOffset);
                                ISymbolScope[] newChildren;
                                newChildren = new ISymbolScope [children.Length 
+ 1];
                                Array.Copy(children, 0, newChildren, 0, index);
                                Array.Copy(children, index, newChildren, index 
+ 1,
                                                   children.Length - index);
                                newChildren[index] = scope;
                                children = newChildren;
                                return scope;
                        }

        // Find or create a particular scope underneath this one.
        internal SymScope FindScope(int endOffset, int startOffset)
                        {
                                int posn = 0;
                                while(posn < children.Length)
                                {
                                        if(endOffset <= 
children[posn].StartOffset)
                                        {
                                                // Insert a new scope before 
this one.
                                                return InsertScope(posn, 
endOffset, startOffset);
                                        }
                                        else if(startOffset >= 
children[posn].EndOffset)
                                        {
                                                // Insert a new scope after 
this one.
                                                return InsertScope(posn + 1, 
endOffset, startOffset);
                                        }
                                        else if(startOffset == 
children[posn].StartOffset &&
                                                        endOffset == 
children[posn].EndOffset)
                                        {
                                                // We already have this scope.
                                                return 
(SymScope)(children[posn]);
                                        }
                                        else if(startOffset <= 
children[posn].StartOffset &&
                                                        endOffset >= 
children[posn].EndOffset)
                                        {
                                                // The child scope is 
completely contained,
                                                // so we need to insert a new 
scope level.
                                                SymScope scope = new SymScope
                                                        (this, endOffset, 
startOffset);
                                                scope.children = new 
ISymbolScope [1];
                                                scope.children[0] = 
children[posn];
                                                children[posn] = scope;
                                                return scope;
                                        }
                                        else
                                        {
                                                // Insert within a child scope.
                                                return 
((SymScope)(children[posn]))
                                                        .FindScope(endOffset, 
startOffset);
                                        }
                                        ++posn;
                                }
                                return InsertScope(children.Length, endOffset, 
startOffset);
                        }

        // Find the scope that contains a particular offset.
        internal ISymbolScope FindOffset(int offset)
                        {
                                foreach(SymScope scope in children)
                                {
                                        if(offset >= scope.startOffset && 
offset < scope.endOffset)
                                        {
                                                return scope.FindOffset(offset);
                                        }
                                }
                                return this;
                        }

        // Add a local variable to this scope.
        internal void AddLocal(String name, int ilOffset)
                        {
                                SymVariable var = new SymVariable(name, 
ilOffset, this);
                                ISymbolVariable[] newLocals;
                                newLocals = new ISymbolVariable [locals.Length 
+ 1];
                                Array.Copy(locals, 0, newLocals, 0, 
locals.Length);
                                newLocals[locals.Length] = var;
                                locals = newLocals;
                        }

}; // class SymScope

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * SymVariable.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymVariable" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

public class SymVariable : ISymbolVariable
{
        // Internal state.
        private unsafe ISymUnmanagedVariable *pVariable;
        private String name;
        private int ilOffset;
        private SymScope scope;

        // Constructors.
        public unsafe SymVariable(ISymUnmanagedVariable *pVariable)
                        {
                                this.pVariable = pVariable;
                        }
        internal SymVariable(String name, int ilOffset, SymScope scope)
                        {
                                this.name = name;
                                this.ilOffset = ilOffset;
                                this.scope = scope;
                        }

        // Destructor (C++ style).
        ~SymVariable() {}
        public void __dtor()
                        {
                                GC.SuppressFinalize(this);
                                Finalize();
                        }

        // Implement the ISymbolVariable interface.
        public virtual byte[] GetSignature()
                        {
                                // We don't support signatures in this 
implementation.
                                return null;
                        }
        public virtual int AddressField1 
                        {
                                get
                                {
                                        // Return the IL offset as the first 
address.
                                        return ilOffset;
                                }
                        }
        public virtual int AddressField2 
                        {
                                get
                                {
                                        // Second addresses aren't needed for 
IL offsets.
                                        return 0;
                                }
                        }
        public virtual int AddressField3 
                        {
                                get
                                {
                                        // Third addresses aren't needed for IL 
offsets.
                                        return 0;
                                }
                        }
        public virtual SymAddressKind AddressKind 
                        {
                                get
                                {
                                        // We only support local variable 
offsets.
                                        return SymAddressKind.ILOffset;
                                }
                        }
        public virtual Object Attributes 
                        {
                                get
                                {
                                        // We don't support attributes in this 
implementation.
                                        return null;
                                }
                        }
        public virtual int EndOffset 
                        {
                                get
                                {
                                        return scope.EndOffset;
                                }
                        }
        public virtual String Name 
                        {
                                get
                                {
                                        return name;
                                }
                        }
        public virtual int StartOffset 
                        {
                                get
                                {
                                        return scope.StartOffset;
                                }
                        }

}; // class SymVariable

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * SymWriter.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.SymWriter" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

using System.Reflection;

// We don't support symbol file writing in this implementation.

public class SymWriter : ISymbolWriter
{
        // Constructors.
        public SymWriter() {}
        public SymWriter(bool noUnderlyingWriter) {}

        // Destructor (C++ style).
        ~SymWriter() {}
        public void __dtor()
                        {
                                GC.SuppressFinalize(this);
                                Finalize();
                        }

        // Implement the ISymbolWriter interface.
        public virtual void Close()
                        {
                                // Nothing to do here.
                        }
        public virtual void CloseMethod()
                        {
                                // Nothing to do here.
                        }
        public virtual void CloseNamespace()
                        {
                                // Nothing to do here.
                        }
        public virtual void CloseScope(int endOffset)
                        {
                                // Nothing to do here.
                        }
        public virtual ISymbolDocumentWriter DefineDocument
                                (String url, Guid language, Guid languageVendor,
                                 Guid documentType)
                        {
                                // Nothing to do here.
                                return new SymDocumentWriter();
                        }
        public virtual void DefineField
                                (SymbolToken parent, String name,
                                 FieldAttributes attributes, 
                                 byte[] signature, 
                                 SymAddressKind addrKind, 
                                 int addr1, int addr2, int addr3)
                        {
                                throw new NotSupportedException();
                        }
        public virtual void DefineGlobalVariable
                                (String name, FieldAttributes attributes, 
                                 byte[] signature, SymAddressKind addrKind,
                                 int addr1, int addr2, int addr3)
                        {
                                throw new NotSupportedException();
                        }
        public virtual void DefineLocalVariable
                                (String name, FieldAttributes attributes, 
                                 byte[] signature, SymAddressKind addrKind, 
                                 int addr1, int addr2, int addr3, 
                                 int startOffset, int endOffset)
                        {
                                // Nothing to do here.
                        }
        public virtual void DefineParameter
                                (String name, ParameterAttributes attributes, 
                                 int sequence, SymAddressKind addrKind, 
                                 int addr1, int addr2, int addr3)
                        {
                                throw new NotSupportedException();
                        }
        public virtual void DefineSequencePoints
                                (ISymbolDocumentWriter document, 
                                 int[] offsets, int[] lines, 
                                 int[] columns, int[] endLines, 
                                 int[] endColumns)
                        {
                                // Nothing to do here.
                        }
        public virtual void Initialize
                                (IntPtr emitter, String filename, bool 
fFullBuild)
                        {
                                // Nothing to do here.
                        }
        public virtual void OpenMethod(SymbolToken method)
                        {
                                // Nothing to do here.
                        }
        public virtual void OpenNamespace(String name)
                        {
                                // Nothing to do here.
                        }
        public virtual int OpenScope(int startOffset)
                        {
                                // Nothing to do here.
                                return 0;
                        }
        public virtual void SetMethodSourceRange
                                (ISymbolDocumentWriter startDoc, 
                                 int startLine, int startColumn, 
                                 ISymbolDocumentWriter endDoc, 
                                 int endLine, int endColumn)
                        {
                                throw new NotSupportedException();
                        }
        public virtual void SetScopeRange
                                (int scopeID, int startOffset, int endOffset)
                        {
                                // Nothing to do here.
                        }
        public virtual void SetSymAttribute
                                (SymbolToken parent, String name, byte[] data)
                        {
                                // Nothing to do here.
                        }
        public virtual void SetUnderlyingWriter(IntPtr underlyingWriter)
                        {
                                // Nothing to do here.
                        }
        public virtual void SetUserEntryPoint(SymbolToken entryMethod)
                        {
                                // Nothing to do here.
                        }
        public virtual void UsingNamespace(String fullName)
                        {
                                // Nothing to do here.
                        }

}; // class SymWriter

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore

--- NEW FILE ---
/*
 * Utils.cs - Implementation of the
 *                      "System.Diagnostics.SymbolStore.Utils" class.
 *
 * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

namespace System.Diagnostics.SymbolStore
{

#if CONFIG_EXTENDED_DIAGNOSTICS

internal sealed class Utils
{
        // Read an int32 value from a buffer.
        public static int ReadInt32(byte[] buffer, int offset)
                        {
                                return (buffer[offset] |
                                        (buffer[offset + 1] << 8) |
                                        (buffer[offset + 2] << 16) |
                                        (buffer[offset + 3] << 24));
                        }

        // Read a uint16 value from a buffer.
        public static int ReadUInt16(byte[] buffer, int offset)
                        {
                                return (buffer[offset] |
                                        (buffer[offset + 1] << 8));
                        }

        // Read a metadata-encoded integer.
        public static int ReadMetaInt(byte[] buffer, int offset, out int size)
                        {
                                int value;
                                if(offset >= buffer.Length)
                                {
                                        size = 0;
                                        return 0;
                                }
                                value = buffer[offset++];
                                if(value < 128)
                                {
                                        size = 1;
                                        return value;
                                }
                                else if((value & 0xC0) == 0x80)
                                {
                                        if(offset >= buffer.Length)
                                        {
                                                size = 0;
                                                return 0;
                                        }
                                        size = 2;
                                        return ((value & 0x3F) << 8) | 
buffer[offset];
                                }
                                else if((value & 0xE0) == 0xC0)
                                {
                                        if((offset + 2) >= buffer.Length)
                                        {
                                                size = 0;
                                                return 0;
                                        }
                                        size = 4;
                                        return ((value & 0x1F) << 24) |
                                                   (buffer[offset] << 16) |
                                                   (buffer[offset + 1] << 8) |
                                                   buffer[offset + 2];
                                }
                                else if((value & 0xE0) == 0xE0)
                                {
                                        if((offset + 3) >= buffer.Length)
                                        {
                                                size = 0;
                                                return 0;
                                        }
                                        size = 5;
                                        return (buffer[offset] << 24) |
                                                   (buffer[offset + 1] << 16) |
                                                   (buffer[offset + 2] << 8) |
                                                   buffer[offset + 3];
                                }
                                else
                                {
                                        size = 0;
                                        return 0;
                                }
                        }

        // Create a pseudo-token value.  The "name" must be at least
        // four characters in length.
        public static int CreatePseudoToken(String name)
                        {
                                return ((int)(name[0])) |
                                           (((int)(name[1])) << 8) |
                                           (((int)(name[2])) << 16) |
                                           (((int)(name[3])) << 24) |
                                           unchecked((int)0x80000000);
                        }

}; // class Utils

#endif // CONFIG_EXTENDED_DIAGNOSTICS

}; // namespace System.Diagnostics.SymbolStore





reply via email to

[Prev in Thread] Current Thread [Next in Thread]