private readonly IDisposable _onChangeEvent;
private Flags _flags;
- private PdbInfo _pdbInfo;
+ private PdbFileInfo _pdbFileInfo;
private ImmutableArray<byte> _buildId;
- private VersionInfo? _version;
+ private VersionData _versionData;
private PEImage _peImage;
public readonly ServiceProvider ServiceProvider;
}
}
- public PdbInfo PdbInfo
+ public PdbFileInfo PdbFileInfo
{
get
{
GetPEInfo();
- return _pdbInfo;
+ return _pdbFileInfo;
}
}
}
}
- public virtual VersionInfo? Version
+ public virtual VersionData VersionData
{
- get { return _version; }
- set { _version = value; }
+ get { return _versionData; }
+ set { _versionData = value; }
}
public abstract string VersionString { get; }
GetPEInfo();
// If we can't get the version from the PE, search for version string embedded in the module data
- if (!_version.HasValue && !IsPEImage)
+ if (_versionData is null && !IsPEImage)
{
string versionString = VersionString;
if (versionString != null)
try
{
Version version = System.Version.Parse(versionToParse);
- _version = new VersionInfo(version.Major, version.Minor, version.Build, version.Revision);
+ _versionData = new VersionData(version.Major, version.Minor, version.Build, version.Revision);
}
catch (ArgumentException ex)
{
protected PEImage GetPEInfo()
{
if (InitializeValue(Flags.InitializePEInfo)) {
- _peImage = ModuleService.GetPEInfo(ImageBase, ImageSize, ref _pdbInfo, ref _version, ref _flags);
+ _peImage = ModuleService.GetPEInfo(ImageBase, ImageSize, ref _pdbFileInfo, ref _versionData, ref _flags);
}
return _peImage;
}
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.Diagnostics.Runtime;
using Microsoft.Diagnostics.Runtime.Utilities;
using Microsoft.FileFormats;
using Microsoft.FileFormats.ELF;
/// </summary>
/// <param name="address">module base address</param>
/// <param name="size">module size</param>
- /// <param name="pdbInfo">the pdb record or null</param>
- /// <param name="version">the PE version or null</param>
+ /// <param name="pdbFileInfo">the pdb record or null</param>
+ /// <param name="versionData">the PE version or null</param>
/// <param name="flags">module flags</param>
/// <returns>PEImage instance or null</returns>
- internal PEImage GetPEInfo(ulong address, ulong size, ref PdbInfo pdbInfo, ref VersionInfo? version, ref Module.Flags flags)
+ internal PEImage GetPEInfo(ulong address, ulong size, ref PdbFileInfo pdbFileInfo, ref VersionData versionData, ref Module.Flags flags)
{
PEImage peImage = null;
if (Target.Host.HostType != HostType.Lldb)
{
// First try getting the PE info as load layout (native Windows DLLs and most managed PEs on Linux/MacOS).
- peImage = GetPEInfo(isVirtual: true, address, size, ref pdbInfo, ref version, ref flags);
+ peImage = GetPEInfo(isVirtual: true, address, size, ref pdbFileInfo, ref versionData, ref flags);
if (peImage == null)
{
if (Target.OperatingSystem != OSPlatform.Windows)
{
// Then try getting the PE info as file layout (some managed PEs on Linux/MacOS).
- peImage = GetPEInfo(isVirtual: false, address, size, ref pdbInfo, ref version, ref flags);
+ peImage = GetPEInfo(isVirtual: false, address, size, ref pdbFileInfo, ref versionData, ref flags);
}
}
}
/// <param name="isVirtual">the memory layout of the module</param>
/// <param name="address">module base address</param>
/// <param name="size">module size</param>
- /// <param name="pdbInfo">the pdb record or null</param>
- /// <param name="version">the PE version or null</param>
+ /// <param name="pdbFileInfo">the pdb record or null</param>
+ /// <param name="versionData">the PE version or null</param>
/// <param name="flags">module flags</param>
/// <returns>PEImage instance or null</returns>
- private PEImage GetPEInfo(bool isVirtual, ulong address, ulong size, ref PdbInfo pdbInfo, ref VersionInfo? version, ref Module.Flags flags)
+ private PEImage GetPEInfo(bool isVirtual, ulong address, ulong size, ref PdbFileInfo pdbFileInfo, ref VersionData versionData, ref Module.Flags flags)
{
Stream stream = MemoryService.CreateMemoryStream(address, size);
try
{
flags |= Module.Flags.IsPEImage;
flags |= peImage.IsManaged ? Module.Flags.IsManaged : Module.Flags.None;
- pdbInfo = peImage.DefaultPdb;
- if (!version.HasValue)
+ pdbFileInfo = peImage.DefaultPdb.ToPdbFileInfo();
+ if (versionData is null)
{
FileVersionInfo fileVersionInfo = peImage.GetFileVersionInfo();
if (fileVersionInfo != null)
{
- version = fileVersionInfo.VersionInfo;
+ versionData = fileVersionInfo.VersionInfo.ToVersionData();
}
}
flags &= ~(Module.Flags.IsLoadedLayout | Module.Flags.IsFileLayout);
// This is what clrmd returns for non-PE modules that don't have a timestamp
private const uint InvalidTimeStamp = 0;
- private static readonly VersionInfo EmptyVersionInfo = new VersionInfo(0, 0, 0, 0);
+ private static readonly Microsoft.Diagnostics.Runtime.VersionInfo EmptyVersionInfo = new (0, 0, 0, 0);
private readonly ModuleServiceFromDataReader _moduleService;
private readonly IExportReader _exportReader;
private readonly ModuleInfo _moduleInfo;
public override uint? IndexTimeStamp => _moduleInfo.IndexTimeStamp == InvalidTimeStamp ? null : (uint)_moduleInfo.IndexTimeStamp;
- public override VersionInfo? Version
+ public override VersionData VersionData
{
get
{
{
if (_moduleInfo.Version != EmptyVersionInfo)
{
- base.Version = _moduleInfo.Version;
+ base.VersionData = _moduleInfo.Version.ToVersionData();
}
else
{
}
}
}
- return base.Version;
+ return base.VersionData;
}
}
return ImmutableArray<byte>.Empty;
}
- bool IDataReader.GetVersionInfo(ulong baseAddress, out VersionInfo version)
+ bool IDataReader.GetVersionInfo(ulong baseAddress, out Microsoft.Diagnostics.Runtime.VersionInfo version)
{
try
{
- VersionInfo? v = ModuleService.GetModuleFromBaseAddress(baseAddress).Version;
- if (v.HasValue)
+ VersionData versionData = ModuleService.GetModuleFromBaseAddress(baseAddress).VersionData;
+ if (versionData is not null)
{
- version = v.Value;
+ version = versionData.ToVersionInfo();
return true;
}
}
namespace Microsoft.Diagnostics.DebugServices.Implementation
{
- public class Utilities
+ public static class Utilities
{
/// <summary>
/// Combines two hash codes into a single hash code, in an order-dependent manner.
return hashCode0 ^ (hashCode1 + (int) 0x9e3779b9 + (hashCode0 << 6) + (hashCode0 >> 2));
}
}
+
+ /// <summary>
+ /// Convert from CLRMD VersionInfo to DebugServices VersionData
+ /// </summary>
+ public static VersionData ToVersionData(this Microsoft.Diagnostics.Runtime.VersionInfo versionInfo)
+ {
+ return new VersionData(versionInfo.Major, versionInfo.Minor, versionInfo.Revision, versionInfo.Patch);
+ }
+
+ /// <summary>
+ /// Convert from DebugServices VersionData to CLRMD VersionInfo
+ /// </summary>
+ public static Microsoft.Diagnostics.Runtime.VersionInfo ToVersionInfo(this VersionData versionData)
+ {
+ return new Microsoft.Diagnostics.Runtime.VersionInfo(versionData.Major, versionData.Minor, versionData.Revision, versionData.Patch);
+ }
+
+ /// <summary>
+ /// Convert from CLRMD PdbInfo to DebugServices PdbFileInfo
+ /// </summary>
+ public static PdbFileInfo ToPdbFileInfo(this Microsoft.Diagnostics.Runtime.PdbInfo pdbInfo)
+ {
+ return new PdbFileInfo(pdbInfo.Path, pdbInfo.Guid, pdbInfo.Revision);
+ }
}
}
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.Diagnostics.Runtime;
using System;
using System.Collections.Immutable;
ulong ImageBase { get; }
/// <summary>
- /// Returns the image size of module in memory
+ /// Returns the image size of module in memory.
/// </summary>
ulong ImageSize { get; }
ImmutableArray<byte> BuildId { get; }
/// <summary>
- /// Returns true if Windows PE format image (native or IL)
+ /// Returns true if Windows PE format image (native or IL).
/// </summary>
bool IsPEImage { get; }
/// <summary>
- /// Returns true if managed or IL assembly
+ /// Returns true if managed or IL assembly.
/// </summary>
bool IsManaged { get; }
/// <summary>
- /// Returns true if the PE module is layout is file. False, layout is loaded image. Null, not a PE image.
+ /// Returns true if the PE module is layout is file. False, layout is loaded image. If null, not a PE image.
/// </summary>
bool? IsFileLayout { get; }
/// <summary>
- /// PDB information for Windows PE modules (managed or native
+ /// PDB information for Windows PE modules (managed or native).
/// </summary>
- PdbInfo PdbInfo { get; }
+ PdbFileInfo PdbFileInfo { get; }
/// <summary>
/// Version information for Window PE modules (managed or native).
/// </summary>
- VersionInfo? Version { get; }
+ VersionData VersionData { get; }
/// <summary>
/// This is the file version string containing the build version and commit id.
<ItemGroup>
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
- <PackageReference Include="Microsoft.Diagnostics.Runtime" Version="$(MicrosoftDiagnosticsRuntimeVersion)" />
<PackageReference Include="Microsoft.SymbolStore" Version="$(MicrosoftSymbolStoreVersion)" />
</ItemGroup>
</Project>
--- /dev/null
+// 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;
+
+namespace Microsoft.Diagnostics.DebugServices
+{
+ /// <summary>
+ /// Information about a specific PDB instance obtained from a PE image.
+ /// </summary>
+ public sealed class PdbFileInfo
+ {
+ /// <summary>
+ /// Gets the Guid of the PDB.
+ /// </summary>
+ public Guid Guid { get; }
+
+ /// <summary>
+ /// Gets the PDB revision.
+ /// </summary>
+ public int Revision { get; }
+
+ /// <summary>
+ /// Gets the path to the PDB.
+ /// </summary>
+ public string Path { get; }
+
+ /// <summary>
+ /// Creates an instance of the PdbInfo with the corresponding properties initialized.
+ /// </summary>
+ public PdbFileInfo(string path, Guid guid, int revision)
+ {
+ Path = path;
+ Guid = guid;
+ Revision = revision;
+ }
+
+ public override string ToString() => $"{Guid} {Revision} {Path}";
+ }
+}
/// <summary>
/// Details about a register
/// </summary>
- public struct RegisterInfo
+ public readonly struct RegisterInfo
{
public readonly int RegisterIndex;
public readonly int RegisterOffset;
--- /dev/null
+// 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;
+
+namespace Microsoft.Diagnostics.DebugServices
+{
+ /// <summary>
+ /// Represents the version of a module
+ /// </summary>
+ public sealed class VersionData : IEquatable<VersionData>, IComparable<VersionData>
+ {
+ /// <summary>
+ /// In a version 'A.B.C.D', this field represents 'A'.
+ /// </summary>
+ public int Major { get; }
+
+ /// <summary>
+ /// In a version 'A.B.C.D', this field represents 'B'.
+ /// </summary>
+ public int Minor { get; }
+
+ /// <summary>
+ /// In a version 'A.B.C.D', this field represents 'C'.
+ /// </summary>
+ public int Revision { get; }
+
+ /// <summary>
+ /// In a version 'A.B.C.D', this field represents 'D'.
+ /// </summary>
+ public int Patch { get; }
+
+ public VersionData(int major, int minor, int revision, int patch)
+ {
+ if (major < 0)
+ throw new ArgumentOutOfRangeException(nameof(major));
+
+ if (minor < 0)
+ throw new ArgumentOutOfRangeException(nameof(minor));
+
+ if (revision < 0)
+ throw new ArgumentOutOfRangeException(nameof(revision));
+
+ if (patch < 0)
+ throw new ArgumentOutOfRangeException(nameof(patch));
+
+ Major = major;
+ Minor = minor;
+ Revision = revision;
+ Patch = patch;
+ }
+
+ /// <inheritdoc/>
+ public bool Equals(VersionData other) => Major == other.Major && Minor == other.Minor && Revision == other.Revision && Patch == other.Patch;
+
+ /// <inheritdoc/>
+ public override bool Equals(object obj) => obj is VersionData other && Equals(other);
+
+ /// <inheritdoc/>
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ int hashCode = Major;
+ hashCode = (hashCode * 397) ^ Minor;
+ hashCode = (hashCode * 397) ^ Revision;
+ hashCode = (hashCode * 397) ^ Patch;
+ return hashCode;
+ }
+ }
+
+ /// <inheritdoc/>
+ public int CompareTo(VersionData other)
+ {
+ if (Major != other.Major)
+ return Major.CompareTo(other.Major);
+
+ if (Minor != other.Minor)
+ return Minor.CompareTo(other.Minor);
+
+ if (Revision != other.Revision)
+ return Revision.CompareTo(other.Revision);
+
+ return Patch.CompareTo(other.Patch);
+ }
+
+ public override string ToString() => $"{Major}.{Minor}.{Revision}.{Patch}";
+
+ public static bool operator ==(VersionData left, VersionData right) => left.Equals(right);
+
+ public static bool operator !=(VersionData left, VersionData right) => !(left == right);
+
+ public static bool operator <(VersionData left, VersionData right) => left.CompareTo(right) < 0;
+
+ public static bool operator <=(VersionData left, VersionData right) => left.CompareTo(right) <= 0;
+
+ public static bool operator >(VersionData left, VersionData right) => right < left;
+
+ public static bool operator >=(VersionData left, VersionData right) => right <= left;
+ }
+}
\ No newline at end of file
using Microsoft.Diagnostics.DebugServices;
using Microsoft.Diagnostics.Runtime;
-using System;
-using System.Linq;
namespace Microsoft.Diagnostics.ExtensionCommands
{
WriteLine(" MetadataAddress: {0:X16}", module.MetadataAddress);
WriteLine(" MetadataSize: {0:X16}", module.MetadataLength);
WriteLine(" PdbInfo: {0}", module.Pdb?.ToString() ?? "<none>");
- VersionInfo? version = null;
+ VersionData version = null;
try
{
- version = ModuleService.GetModuleFromBaseAddress(module.ImageBase).Version;
+ version = ModuleService.GetModuleFromBaseAddress(module.ImageBase).VersionData;
}
catch (DiagnosticsException)
{
WriteLine(" IsFileLayout: {0}", module.IsFileLayout?.ToString() ?? "<unknown>");
WriteLine(" IndexFileSize: {0}", module.IndexFileSize?.ToString("X8") ?? "<none>");
WriteLine(" IndexTimeStamp: {0}", module.IndexTimeStamp?.ToString("X8") ?? "<none>");
- WriteLine(" Version: {0}", module.Version?.ToString() ?? "<none>");
+ WriteLine(" Version: {0}", module.VersionData?.ToString() ?? "<none>");
string versionString = module.VersionString;
if (!string.IsNullOrEmpty(versionString)) {
WriteLine(" {0}", versionString);
}
- WriteLine(" PdbInfo: {0}", module.PdbInfo?.ToString() ?? "<none>");
+ WriteLine(" PdbInfo: {0}", module.PdbFileInfo?.ToString() ?? "<none>");
WriteLine(" BuildId: {0}", !module.BuildId.IsDefaultOrEmpty ? string.Concat(module.BuildId.Select((b) => b.ToString("x2"))) : "<none>");
}
else
public override uint? IndexTimeStamp { get; }
- public override VersionInfo? Version
+ public override VersionData VersionData
{
get
{
int minor = (int)fileInfo.dwFileVersionMS & 0xffff;
int revision = (int)fileInfo.dwFileVersionLS >> 16;
int patch = (int)fileInfo.dwFileVersionLS & 0xffff;
- base.Version = new VersionInfo(major, minor, revision, patch);
+ base.VersionData = new VersionData(major, minor, revision, patch);
}
else
{
}
}
}
- return base.Version;
+ return base.VersionData;
}
}
{
return HResult.E_FAIL;
}
- if (!module.Version.HasValue)
+ if (module.VersionData is null)
{
return HResult.E_FAIL;
}
pFileInfo->dwFileFlagsMask = 0;
pFileInfo->dwFileFlags = 0;
- VersionInfo versionInfo = module.Version.Value;
- pFileInfo->dwFileVersionMS = (uint)versionInfo.Minor | (uint)versionInfo.Major << 16;
- pFileInfo->dwFileVersionLS = (uint)versionInfo.Patch | (uint)versionInfo.Revision << 16;
+ VersionData versionData = module.VersionData;
+ pFileInfo->dwFileVersionMS = (uint)versionData.Minor | (uint)versionData.Major << 16;
+ pFileInfo->dwFileVersionLS = (uint)versionData.Patch | (uint)versionData.Revision << 16;
// Attempt to get the FileVersion string that contains version and the "built by" and commit id info
if (fileVersionBuffer != null)
{
return HResult.E_INVALIDARG;
}
- if (!module.Version.HasValue)
+ if (module.VersionData is null)
{
return HResult.E_FAIL;
}
fileInfo->dwFileFlagsMask = 0;
fileInfo->dwFileFlags = 0;
- VersionInfo versionInfo = module.Version.Value;
- fileInfo->dwFileVersionMS = (uint)versionInfo.Minor | (uint)versionInfo.Major << 16;
- fileInfo->dwFileVersionLS = (uint)versionInfo.Patch | (uint)versionInfo.Revision << 16;
+ VersionData versionData = module.VersionData;
+ fileInfo->dwFileVersionMS = (uint)versionData.Minor | (uint)versionData.Major << 16;
+ fileInfo->dwFileVersionLS = (uint)versionData.Patch | (uint)versionData.Revision << 16;
}
else if (item == "\\StringFileInfo\\040904B0\\FileVersion")
{
// These are the values set in m_dwTransientFlags.
// Note that none of these flags survive a prejit save/restore.
- M_CRST_NOTINITIALIZED = 0x00000001, // Used to prevent destruction of garbage m_crst
- M_LOOKUPCRST_NOTINITIALIZED = 0x00000002,
+ MODULE_IS_TENURED = 0x00000001, // Set once we know for sure the Module will not be freed until the appdomain itself exits
+ // unused = 0x00000002,
+ CLASSES_FREED = 0x00000004,
+ IS_EDIT_AND_CONTINUE = 0x00000008, // is EnC Enabled for this module
- SUPPORTS_UPDATEABLE_METHODS = 0x00000020,
- CLASSES_FREED = 0x00000040,
- HAS_PHONY_IL_RVAS = 0x00000080,
- IS_EDIT_AND_CONTINUE = 0x00000200,
+ IS_PROFILER_NOTIFIED = 0x00000010,
+ IS_ETW_NOTIFIED = 0x00000020,
+
+ //
+ // Note: the order of these must match the order defined in
+ // cordbpriv.h for DebuggerAssemblyControlFlags. The three
+ // values below should match the values defined in
+ // DebuggerAssemblyControlFlags when shifted right
+ // DEBUGGER_INFO_SHIFT bits.
+ //
+ DEBUGGER_USER_OVERRIDE_PRIV = 0x00000400,
+ DEBUGGER_ALLOW_JIT_OPTS_PRIV= 0x00000800,
+ DEBUGGER_TRACK_JIT_INFO_PRIV= 0x00001000,
+ DEBUGGER_ENC_ENABLED_PRIV = 0x00002000, // this is what was attempted to be set. IS_EDIT_AND_CONTINUE is actual result.
+ DEBUGGER_PDBS_COPIED = 0x00004000,
+ DEBUGGER_IGNORE_PDBS = 0x00008000,
+ DEBUGGER_INFO_MASK_PRIV = 0x0000Fc00,
+ DEBUGGER_INFO_SHIFT_PRIV = 10,
+
+ // Used to indicate that this module has had it's IJW fixups properly installed.
+ IS_IJW_FIXED_UP = 0x00080000,
+ IS_BEING_UNLOADED = 0x00100000,
+
+ // Used to indicate that the module is loaded sufficiently for generic candidate instantiations to work
+ MODULE_READY_FOR_TYPELOAD = 0x00200000,
+
+ // Used during NGen only
+ TYPESPECS_TRIAGED = 0x40000000,
+ MODULE_SAVED = 0x80000000,
};
void ModuleMapTraverse(UINT index, CLRDATA_ADDRESS methodTable, LPVOID token)
ExtOut("PEFile ");
if (module.bIsReflection)
ExtOut("Reflection ");
- if (module.dwTransientFlags & SUPPORTS_UPDATEABLE_METHODS)
- ExtOut("SupportsUpdateableMethods ");
ToRelease<IXCLRDataModule> dataModule;
if (SUCCEEDED(g_sos->GetModule(TO_CDADDR(p_ModuleAddr), &dataModule)))
}
ExtOut("\n");
+ ExtOut("TransientFlags: %08x ", module.dwTransientFlags);
+ if (module.dwTransientFlags & IS_EDIT_AND_CONTINUE)
+ ExtOut("IS_EDIT_AND_CONTINUE");
+ ExtOut("\n");
+
DMLOut("Assembly: %s\n", DMLAssembly(module.Assembly));
ExtOut("BaseAddress: %p\n", SOS_PTR(module.ilBase));