summaryrefslogtreecommitdiff
path: root/src/ToolBox/SOS/DacTableGen/diautil.cs
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
commit4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch)
tree98110734c91668dfdbb126fcc0e15ddbd93738ca /src/ToolBox/SOS/DacTableGen/diautil.cs
parentfa45f57ed55137c75ac870356a1b8f76c84b229c (diff)
downloadcoreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src/ToolBox/SOS/DacTableGen/diautil.cs')
-rw-r--r--src/ToolBox/SOS/DacTableGen/diautil.cs809
1 files changed, 809 insertions, 0 deletions
diff --git a/src/ToolBox/SOS/DacTableGen/diautil.cs b/src/ToolBox/SOS/DacTableGen/diautil.cs
new file mode 100644
index 0000000000..d0e9c811a7
--- /dev/null
+++ b/src/ToolBox/SOS/DacTableGen/diautil.cs
@@ -0,0 +1,809 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Text;
+using System.IO;
+using Dia;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+/***************************************************************************************
+ *
+ ***************************************************************************************/
+
+namespace Dia.Util
+{
+
+/***************************************************************************************
+ *
+ ***************************************************************************************/
+
+class Util
+{
+ public static IDiaSymbol FindSymbol(String symName, IDiaSymbol parent, SymTagEnum symTag)
+ {
+ IDiaEnumSymbols e;
+ parent.findChildren(symTag,
+ symName,
+ (uint)(NameSearchOptions.nsfCaseSensitive),
+ out e);
+
+ IDiaSymbol s;
+ uint celt;
+
+ if (e == null || e.count == 0)
+ return null;
+
+ e.Next(1, out s, out celt);
+
+ if (e.count > 1)
+ {
+ for (int i = 1; i < e.count; i++)
+ {
+ IDiaSymbol s2;
+ e.Next(1, out s2, out celt);
+
+ // Diasym reader returns multiple symbols with same RVA in some cases. Issue the warning only
+ // if the returned symbols actually differ.
+ if (s.virtualAddress != s2.virtualAddress)
+ {
+ Shell.Error("Symbol " + symName + " has " + e.count + " matches. Taking first.");
+ break;
+ }
+ }
+ }
+
+ return s;
+ }
+
+ public static IDiaSymbol FindClassSymbol(String name, IDiaSymbol sym, SymTagEnum tag)
+ {
+ IDiaSymbol res = null;
+ //Console.WriteLine("Looking for " + name + " in " + sym.name);
+
+ res = Util.FindSymbol(name, sym, tag);
+
+ if (res == null)
+ {
+ IDiaEnumSymbols e;
+
+ sym.findChildren(
+ SymTagEnum.SymTagBaseClass,
+ null,
+ (uint)NameSearchOptions.nsNone,
+ out e);
+
+ if (e == null || e.count == 0)
+ return null;
+
+ for (int i = 0; i < e.count && res == null; i++)
+ {
+ UInt32 celt;
+ IDiaSymbol s;
+ e.Next(1, out s, out celt);
+ res = FindClassSymbol(name, s.type, tag);
+ }
+ }
+
+ return res;
+ }
+}
+
+/***************************************************************************************
+ *
+ ***************************************************************************************/
+
+public class DiaFile
+{
+ DiaSourceClass m_dsc;
+ IDiaSession m_session;
+ DiaSymbol m_global;
+ IDiaEnumSymbols m_publicsEnum;
+ UInt32 m_debugTimestamp;
+ String m_loadedPdbPath;
+
+ public DiaFile(String pdbFile, String dllFile)
+ {
+ m_dsc = new DiaSourceClass();
+ string pdbPath = System.IO.Path.GetDirectoryName(pdbFile);
+
+ // Open the PDB file, validating it matches the supplied DLL file
+ DiaLoadCallback loadCallback = new DiaLoadCallback();
+ try
+ {
+ m_dsc.loadDataForExe(dllFile, pdbPath, loadCallback);
+ }
+ catch (System.Exception diaEx)
+ {
+ // Provide additional diagnostics context and rethrow
+ string msg = "ERROR from DIA loading PDB for specified DLL";
+ COMException comEx = diaEx as COMException;
+ if (comEx != null)
+ {
+ if (Enum.IsDefined(typeof(DiaHResults), comEx.ErrorCode))
+ {
+ // This is a DIA-specific error code,
+ DiaHResults hr = (DiaHResults)comEx.ErrorCode;
+ msg += ": " + hr.ToString();
+
+ // Additional clarification for the common case of the DLL not matching the PDB
+ if (hr == DiaHResults.E_PDB_NOT_FOUND)
+ {
+ msg += " - The specified PDB file does not match the specified DLL file";
+ }
+ }
+ }
+ throw new ApplicationException(msg, diaEx);
+ }
+
+ // Save the path of the PDB file actually loaded
+ Debug.Assert(loadCallback.LoadedPdbPath != null, "Didn't get PDB load callback");
+ m_loadedPdbPath = loadCallback.LoadedPdbPath;
+
+ // Also use DIA to get the debug directory entry in the DLL referring
+ // to the PDB, and save it's timestamp comparison at runtime.
+ m_debugTimestamp = loadCallback.DebugTimeDateStamp;
+ Debug.Assert(m_debugTimestamp != 0, "Didn't find debug directory entry");
+
+ m_dsc.openSession(out m_session);
+ m_global = new DiaSymbol(m_session.globalScope);
+ m_publicsEnum = null;
+ }
+
+ public DiaSymbol GlobalSymbol
+ {
+ get
+ { return m_global; }
+ }
+
+ /// <summary>
+ /// Path of the PDB file actually loaded (must be non-null)
+ /// </summary>
+ public String LoadedPdbPath
+ {
+ get { return m_loadedPdbPath; }
+ }
+
+ /// <summary>
+ /// Timestamp in the debug directory of the DLL corresponding to the PDB loaded (always set non-zero).
+ /// </summary>
+ public UInt32 DebugTimestamp
+ {
+ get { return m_debugTimestamp; }
+ }
+
+ private void GetPublicsEnum()
+ {
+ if (m_publicsEnum != null)
+ return;
+
+ m_session.findChildren(m_global.IDiaSymbol, SymTagEnum.SymTagPublicSymbol,
+ null, (UInt32) NameSearchOptions.nsNone, out m_publicsEnum);
+ }
+
+ public IDiaEnumSymbols PublicSymbols
+ {
+ get
+ {
+ GetPublicsEnum();
+
+ if (m_publicsEnum != null)
+ {
+ IDiaEnumSymbols en;
+ m_publicsEnum.Clone(out en);
+ return en;
+ }
+ else
+ return null;
+ }
+ }
+
+ public IDiaEnumSymbols FindPublicSymbols(String name)
+ {
+ IDiaEnumSymbols se;
+ m_session.findChildren(m_global.IDiaSymbol, SymTagEnum.SymTagPublicSymbol,
+ name, (UInt32) NameSearchOptions.nsNone, out se);
+
+ return se;
+ }
+
+ // Use only the path we supply, don't look for PDBs anywhere else
+ private class DiaLoadCallback : IDiaLoadCallback2
+ {
+ /// <summary>
+ /// The path from with the PDB file was actually loaded, or null if none yet.
+ /// </summary>
+ public string LoadedPdbPath
+ {
+ get { return m_loadedPdbPath; }
+ }
+
+ /// <summary>
+ /// The time stamp in the debug directory corresponding to the PDB that was loaded
+ /// </summary>
+ public UInt32 DebugTimeDateStamp
+ {
+ get { return m_debugTimeDateStamp; }
+ }
+
+ private string m_loadedPdbPath = null;
+ private UInt32 m_debugTimeDateStamp = 0;
+
+ public void NotifyDebugDir(int fExecutable, uint cbData, ref IMAGE_DEBUG_DIRECTORY pbData)
+ {
+ Debug.Assert(cbData == Marshal.SizeOf(typeof(IMAGE_DEBUG_DIRECTORY)), "Got unexpected size for IMAGE_DEBUG_DIRECTORY");
+ // There may be mutliple calls, or calls with no timestamp, but only one entry should be
+ // for the code-view record describing the PDB file.
+ if (pbData.Type == ImageDebugType.IMAGE_DEBUG_TYPE_CODEVIEW)
+ {
+ Debug.Assert(fExecutable == 1, "Got debug directory that wasn't read from an executable");
+ Debug.Assert(m_debugTimeDateStamp == 0, "Got unexpected duplicate NotifyDebugDir callback");
+ Debug.Assert(pbData.TimeDateStamp != 0, "Got unexpected 0 debug timestamp in DLL");
+ m_debugTimeDateStamp = pbData.TimeDateStamp;
+ }
+ }
+
+ public void NotifyOpenDBG(string dbgPath, int resultCode)
+ {
+ Debug.Assert(false, "Unexpected DBG opening: " + dbgPath);
+ }
+
+ public void NotifyOpenPDB(string pdbPath, int resultCode)
+ {
+ // Keep track of the path from which DIA loaded the PDB.
+ // If resultCode is non-zero, it means DIA is not loading this PDB (eg. just probing paths
+ // that may not exist).
+ // The DIA SDK docs say the caller will generally ignore any error HResult we return, so we
+ // don't get the chance to reject any non-matching paths.
+ if (resultCode >= 0)
+ {
+ Debug.Assert(m_loadedPdbPath == null, "DIA indicated it was loading more than one PDB file!");
+ m_loadedPdbPath = pdbPath;
+ }
+ }
+
+ public int RestrictRegistryAccess()
+ {
+ return 1; // don't query the registry
+ }
+
+ public int RestrictSymbolServerAccess()
+ {
+ return 1; // don't use the symbol server
+ }
+
+ public int RestrictDBGAccess()
+ {
+ return 1; // don't look for DBG files
+ }
+
+ public int RestrictOriginalPathAccess()
+ {
+ return 1; // don't look in the full path specified in the debug directory
+ }
+
+ public int RestrictReferencePathAccess()
+ {
+ return 1; // Don't look in the directory next to the DLL
+ }
+
+ public int RestrictSystemRootAccess()
+ {
+ return 1; // Don't look in the system directory
+ }
+ }
+
+ // From WinNt.h
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ private struct IMAGE_DEBUG_DIRECTORY
+ {
+ public UInt32 Characteristics;
+ public UInt32 TimeDateStamp;
+ public UInt16 MajorVersion;
+ public UInt16 MinorVersion;
+ public ImageDebugType Type;
+ public UInt32 SizeOfData;
+ public UInt32 AddressOfRawData;
+ public UInt32 PointerToRawData;
+ }
+ private enum ImageDebugType : uint
+ {
+ IMAGE_DEBUG_TYPE_UNKNOWN = 0,
+ IMAGE_DEBUG_TYPE_COFF = 1,
+ IMAGE_DEBUG_TYPE_CODEVIEW = 2,
+ IMAGE_DEBUG_TYPE_FPO = 3,
+ IMAGE_DEBUG_TYPE_MISC = 4,
+ IMAGE_DEBUG_TYPE_EXCEPTION = 5,
+ IMAGE_DEBUG_TYPE_FIXUP = 6,
+ IMAGE_DEBUG_TYPE_BORLAND = 9
+ }
+
+ // DIA Callback interface definitions
+ // These should be in the interop assembly, but due to a bug in dia2.idl, they're missing.
+ // dia2.idl should include these interfaces in the library section to get them into the TLB.
+ // However, it's handy to be able to define them ourselves, because it lets us easily
+ // set the interface that's most convenient (specifically PreserveSig, and explicit use
+ // of IMAGE_DEBUG_DIRECTORY)
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("C32ADB82-73F4-421B-95D5-A4706EDF5DBE"),
+ System.Security.SuppressUnmanagedCodeSecurity]
+ private interface IDiaLoadCallback
+ {
+ void NotifyDebugDir(int fExecutable, uint cbData, [In] ref IMAGE_DEBUG_DIRECTORY pbData);
+
+ void NotifyOpenDBG([In, MarshalAs(UnmanagedType.LPWStr)] string dbgPath, int resultCode);
+
+ void NotifyOpenPDB([In, MarshalAs(UnmanagedType.LPWStr)] string pdbPath, int resultCode);
+
+ [PreserveSig]
+ // return S_OK (0) to allow symbol path lookup from registry
+ int RestrictRegistryAccess();
+
+ [PreserveSig]
+ // return S_OK (0) to allow symbol server lookup
+ int RestrictSymbolServerAccess();
+ }
+
+ [ComImport,
+ Guid("4688A074-5A4D-4486-AEA8-7B90711D9F7C"),
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ System.Security.SuppressUnmanagedCodeSecurity]
+ private interface IDiaLoadCallback2 : IDiaLoadCallback
+ {
+ new void NotifyDebugDir(int fExecutable, uint cbData, [In] ref IMAGE_DEBUG_DIRECTORY pbData);
+
+ new void NotifyOpenDBG([In, MarshalAs(UnmanagedType.LPWStr)] string dbgPath, int resultCode);
+
+ new void NotifyOpenPDB([In, MarshalAs(UnmanagedType.LPWStr)] string pdbPath, int resultCode);
+
+ [PreserveSig]
+ // return S_OK (0) to allow symbol path lookup from registry
+ new int RestrictRegistryAccess();
+
+ [PreserveSig]
+ // return S_OK (0) to allow symbol server lookup
+ new int RestrictSymbolServerAccess();
+
+ [PreserveSig]
+ // return S_OK (0) to allow symbol path lookup from registry
+ int RestrictDBGAccess();
+
+ [PreserveSig]
+ // return S_OK (0) to allow symbol path lookup from registry
+ int RestrictOriginalPathAccess();
+
+ [PreserveSig]
+ // return S_OK (0) to allow symbol path lookup from registry
+ int RestrictReferencePathAccess();
+
+ [PreserveSig]
+ // return S_OK (0) to allow symbol lookup in the system directory
+ int RestrictSystemRootAccess();
+ }
+
+ // DIA specific HResults from dia2.idl, for providing better diagnostics messages
+ private enum DiaHResults : int
+ {
+ E_PDB_OK = unchecked((int)0x806d0001),
+ E_PDB_USAGE ,
+ E_PDB_OUT_OF_MEMORY , // not used, use E_OUTOFMEMORY
+ E_PDB_FILE_SYSTEM ,
+ E_PDB_NOT_FOUND ,
+ E_PDB_INVALID_SIG ,
+ E_PDB_INVALID_AGE ,
+ E_PDB_PRECOMP_REQUIRED ,
+ E_PDB_OUT_OF_TI ,
+ E_PDB_NOT_IMPLEMENTED , // use E_NOTIMPL
+ E_PDB_V1_PDB ,
+ E_PDB_FORMAT ,
+ E_PDB_LIMIT ,
+ E_PDB_CORRUPT ,
+ E_PDB_TI16 ,
+ E_PDB_ACCESS_DENIED , // use E_ACCESSDENIED
+ E_PDB_ILLEGAL_TYPE_EDIT ,
+ E_PDB_INVALID_EXECUTABLE ,
+ E_PDB_DBG_NOT_FOUND ,
+ E_PDB_NO_DEBUG_INFO ,
+ E_PDB_INVALID_EXE_TIMESTAMP ,
+ E_PDB_RESERVED ,
+ E_PDB_DEBUG_INFO_NOT_IN_PDB ,
+ E_PDB_SYMSRV_BAD_CACHE_PATH ,
+ E_PDB_SYMSRV_CACHE_FULL ,
+ E_PDB_MAX
+ }
+}
+
+/***************************************************************************************
+ *
+ ***************************************************************************************/
+
+public class DiaSymbol
+{
+ protected IDiaSymbol m_symbol;
+
+ public DiaSymbol(IDiaSymbol symbol)
+ {
+ if (symbol == null)
+ throw new ArgumentNullException();
+
+ m_symbol = symbol;
+ }
+
+ public DiaSymbol FindSymbol(String name, SymTagEnum tag)
+ {
+ DiaSymbol res = null;
+ IDiaSymbol sym = Util.FindSymbol(name, m_symbol, tag);
+
+ if (sym != null)
+ {
+ if ((SymTagEnum)sym.symTag == SymTagEnum.SymTagData)
+ res = new DiaDataSymbol(sym);
+ else
+ res = new DiaSymbol(sym);
+ }
+
+ return res;
+ }
+
+ public DiaSymbol FindSymbol(String name)
+ {
+ return FindSymbol(name, SymTagEnum.SymTagNull);
+ }
+
+ public DiaSymbol FindClassSymbol(String name, SymTagEnum tag)
+ {
+ DiaSymbol res = null;
+ IDiaSymbol sym = Util.FindClassSymbol(name, m_symbol, tag);
+
+ if (sym != null)
+ {
+ if ((SymTagEnum)sym.symTag == SymTagEnum.SymTagData)
+ res = new DiaDataSymbol(sym);
+ else
+ res = new DiaSymbol(sym);
+ }
+
+ return res;
+ }
+
+ public DiaSymbol FindClassSymbol(String name)
+ {
+ return FindClassSymbol(name, SymTagEnum.SymTagNull);
+ }
+
+ public DiaSymbol FindUDTSymbol(String name)
+ {
+ DiaSymbol res = null;
+ IDiaSymbol sym = Util.FindSymbol(name, m_symbol, SymTagEnum.SymTagUDT);
+
+ if (sym == null)
+ {
+ sym = Util.FindSymbol(name, m_symbol, SymTagEnum.SymTagTypedef);
+
+ if (sym != null)
+ sym = sym.type;
+ }
+
+ if (sym != null)
+ res = new DiaSymbol(sym);
+
+ return res;
+ }
+
+ private String GetVariantString(Object o)
+ {
+ /*
+ switch( v.vt )
+ {
+ //* LONGLONG VT_I8
+ case VT_I8:
+ printf( "%ld", v.llVal );
+ break;
+ //* LONG VT_I4
+ case VT_I4:
+ printf( "%d", v.lVal );
+ break;
+ //* BYTE VT_UI1
+ case VT_UI1:
+ printf( "%d", v.bVal);
+ break;
+ //* SHORT VT_I2
+ case VT_I2:
+ printf( "%d", v.iVal);
+ break;
+ //* CHAR VT_I1
+ case VT_I1:
+ printf( "%d", v.cVal);
+ break;
+ //* USHORT VT_UI2
+ case VT_UI2:
+ printf( "%d", v.uiVal);
+ break;
+ //* ULONG VT_UI4
+ case VT_UI4:
+ printf( "%d", v.ulVal);
+ break;
+ //* ULONGLONG VT_UI8
+ case VT_UI8:
+ printf( "%ld", v.ullVal);
+ break;
+ //* INT VT_INT
+ case VT_INT:
+ printf( "%d", v.intVal);
+ break;
+ //* UINT VT_UINT
+ case VT_UINT:
+ printf( "%d", v.uintVal);
+ break;
+ default:
+ printf( "<Not implemented>" );
+ break;
+ }
+ */
+ return "VARIANT";
+ }
+
+ private String GetBoundString(IDiaSymbol bound)
+ {
+ SymTagEnum tag = (SymTagEnum) bound.symTag;
+ LocationType kind = (LocationType) bound.locationType;
+
+ System.Diagnostics.Debugger.Break();
+ if (tag == SymTagEnum.SymTagData && kind == LocationType.LocIsConstant)
+ {
+ return GetVariantString(bound.value);
+ }
+
+ return bound.name;
+ }
+
+ public String GetTypeString()
+ {
+ return GetTypeString(m_symbol);
+ }
+
+ private String GetTypeString(IDiaSymbol s)
+ {
+ SymTagEnum tag = (SymTagEnum) s.symTag;
+
+ if (tag == SymTagEnum.SymTagData || tag == SymTagEnum.SymTagTypedef)
+ {
+ s = s.type;
+ tag = (SymTagEnum) s.symTag;
+ }
+
+ StringBuilder str = new StringBuilder();
+
+ if (s.name != null)
+ {
+ str.Append(s.name);
+ }
+ else if (tag == SymTagEnum.SymTagPointerType)
+ {
+ str.Append(GetTypeString(s.type));
+ str.Append("*");
+ }
+ else if (tag == SymTagEnum.SymTagBaseType)
+ {
+ BasicType bt = (BasicType) s.baseType;
+ str.AppendFormat("(base type={0}, len={1:d})", bt.ToString(), s.length);
+ }
+ else if (tag == SymTagEnum.SymTagArrayType)
+ {
+ str.Append(GetTypeString(s.type));
+
+ bool succ = true;
+ int i;
+
+ try
+ {
+ UInt32 rank = s.rank;
+
+ IDiaEnumSymbols e;
+ s.findChildren(SymTagEnum.SymTagDimension, null, (UInt32) NameSearchOptions.nsNone, out e);
+
+ for (i = 0; i < e.count; i++)
+ {
+ IDiaSymbol ds;
+ UInt32 celt;
+ e.Next(1, out ds, out celt);
+
+ str.Append("[" + GetBoundString(ds.lowerBound) + ".." + GetBoundString(ds.upperBound) + "]");
+ }
+ }
+ catch (Exception)
+ {
+ succ = false;
+ }
+
+ if (succ == false)
+ {
+ try
+ {
+ succ = true;
+ IDiaEnumSymbols e;
+ s.findChildren(SymTagEnum.SymTagCustomType, null, (UInt32) NameSearchOptions.nsNone, out e);
+
+ for (i = 0; i < e.count; i++)
+ {
+ IDiaSymbol ds;
+ UInt32 celt;
+ e.Next(1, out ds, out celt);
+
+ str.Append("[" + GetTypeString(ds) + "]");
+ }
+ }
+ catch (Exception)
+ {
+ succ = false;
+ }
+ }
+
+ if (succ == false)
+ {
+ try
+ {
+ succ = true;
+ str.AppendFormat("[{0:d}]", s.length/s.type.length );
+ }
+ catch (Exception)
+ {
+ succ = false;
+ }
+ }
+ }
+ else if (tag == SymTagEnum.SymTagFunctionType)
+ {
+ str.Append("Function Type");
+ }
+ else if (tag == SymTagEnum.SymTagCustomType)
+ {
+ throw new Exception("NYI");
+ /*
+ str.Append("Custom Type: ");
+ try
+ {
+ str.Append(s.guid.ToString());
+ }
+ catch (Exception e)
+ {
+ try
+ {
+ str.AppendFormat("{0:x}:{0:x}", s.oemId, s.oemSymbolId);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ DWORD len = 0;
+ if ( s.get_types( 0, &len, NULL ) == S_OK && len > 0 ) {
+ IDiaSymbol** psyms = new IDiaSymbol*[ len ];
+ s.get_types( len, &len, psyms );
+ for ( DWORD i = 0; i < len; ++i ) {
+ printf( " <" );
+ printType( psyms[i] );
+ printf( ">" );
+ psyms[i]->Release();
+ }
+ delete [] psyms;
+ }
+ len = 0;
+ if ( s.get_dataBytes( 0, &len, NULL ) == S_OK && len > 0 ) {
+ BYTE* pdata = new BYTE[ len ];
+ s.get_dataBytes( len, &len, pdata );
+ printf( "<data" );
+ for ( DWORD i = 0; i < len; ++i ) {
+ printf( " %02x", pdata[i] );
+ }
+ printf( " data>" );
+ delete [] pdata;
+ }
+ */
+ } else {
+ str.Append( "No Type.");
+ }
+
+ return str.ToString();
+ }
+
+ public string Name
+ {
+ get
+ { return m_symbol.name; }
+ }
+
+ public UInt64 Address
+ {
+ get
+ { return m_symbol.virtualAddress; }
+ }
+
+ public UInt32 Offset
+ {
+ get
+ { return (UInt32) m_symbol.offset; }
+ }
+
+ public UInt64 Size
+ {
+ get
+ {
+ IDiaSymbol symbol = m_symbol;
+ UInt64 size = symbol.length;
+ if (size != 0)
+ return size;
+
+ SymTagEnum tag = (SymTagEnum) symbol.symTag;
+
+ if (tag == SymTagEnum.SymTagData || tag == SymTagEnum.SymTagTypedef)
+ {
+ symbol = symbol.type;
+ tag = (SymTagEnum) symbol.symTag;
+
+ size = symbol.length;
+ if (size != 0)
+ return size;
+ }
+
+ if (tag == SymTagEnum.SymTagPointerType)
+ {
+ // @TODO: find a way of determining native word size
+ return 4;
+ }
+ else
+ {
+ throw new Exception("Unknown length.");
+ }
+ }
+ }
+
+ public IDiaSymbol IDiaSymbol
+ {
+ get
+ { return m_symbol; }
+ }
+}
+
+public class DiaDataSymbol : DiaSymbol
+{
+ public DiaDataSymbol(IDiaSymbol symbol) : base(symbol)
+ {
+ if ((SymTagEnum)symbol.symTag != SymTagEnum.SymTagData)
+ throw new Exception("Not a data symbol.");
+ }
+
+ public DataKind DataKind
+ {
+ get
+ { return ((DataKind) m_symbol.dataKind); }
+ }
+
+ public bool IsGlobal
+ {
+ get
+ { return (DataKind == DataKind.DataIsGlobal); }
+ }
+
+ public bool IsFileStatic
+ {
+ get
+ { return (DataKind == DataKind.DataIsFileStatic); }
+ }
+
+ public bool IsMember
+ {
+ get
+ { return (DataKind == DataKind.DataIsMember); }
+ }
+
+ public bool IsStaticMember
+ {
+ get
+ { return (DataKind == DataKind.DataIsStaticMember); }
+ }
+}
+
+} // Namespace Dia.Util