diff --git a/src/Microsoft.Diagnostics.Runtime/Microsoft.Diagnostics.Runtime.csproj b/src/Microsoft.Diagnostics.Runtime/Microsoft.Diagnostics.Runtime.csproj
index 5948e6e19..1af31773c 100644
--- a/src/Microsoft.Diagnostics.Runtime/Microsoft.Diagnostics.Runtime.csproj
+++ b/src/Microsoft.Diagnostics.Runtime/Microsoft.Diagnostics.Runtime.csproj
@@ -30,10 +30,4 @@
-
-
-
-
-
-
diff --git a/src/Microsoft.Diagnostics.Runtime/src/Extensions/DebugOnly.cs b/src/Microsoft.Diagnostics.Runtime/src/Extensions/DebugOnly.cs
deleted file mode 100644
index 4d83491b5..000000000
--- a/src/Microsoft.Diagnostics.Runtime/src/Extensions/DebugOnly.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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.Diagnostics;
-
-namespace Microsoft.Diagnostics.Runtime
-{
- internal static class DebugOnly
- {
- [Conditional("DEBUG")]
- public static void Assert(bool mustBeTrue) => Assert(mustBeTrue, "Assertion Failed");
-
- [Conditional("DEBUG")]
- public static void Assert(bool mustBeTrue, string msg)
- {
- if (!mustBeTrue)
- Fail(msg);
- }
-
- [Conditional("DEBUG")]
- public static void Fail(string message)
- {
- throw new AssertionException(message);
- }
- }
-
-#pragma warning disable CA1032 // Implement standard exception constructors
-#pragma warning disable CA1064 // Exceptions should be public
- internal sealed class AssertionException : Exception
- {
- public AssertionException(string msg)
- : base(msg)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.Diagnostics.Runtime/src/Extensions/SpanExtensions.cs b/src/Microsoft.Diagnostics.Runtime/src/Extensions/SpanExtensions.cs
deleted file mode 100644
index f842a511d..000000000
--- a/src/Microsoft.Diagnostics.Runtime/src/Extensions/SpanExtensions.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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.Buffers;
-using System.IO;
-using System.Runtime.InteropServices;
-
-namespace Microsoft.Diagnostics.Runtime
-{
- internal static class SpanExtensions
- {
- public static int Read(this Stream stream, Span span)
- {
- byte[] buffer = ArrayPool.Shared.Rent(span.Length);
- try
- {
- int numRead = stream.Read(buffer, 0, span.Length);
- new ReadOnlySpan(buffer, 0, numRead).CopyTo(span);
- return numRead;
- }
- finally
- {
- ArrayPool.Shared.Return(buffer);
- }
- }
-
- public static ulong AsPointer(this Span span, int index = 0)
- {
- if (index != 0)
- span = span.Slice(index * IntPtr.Size, IntPtr.Size);
-
- DebugOnly.Assert(span.Length >= IntPtr.Size);
- return IntPtr.Size == 4
- ? MemoryMarshal.Read(span)
- : MemoryMarshal.Read(span);
- }
-
- public static int AsInt32(this Span span)
- {
- DebugOnly.Assert(span.Length >= sizeof(int));
- return MemoryMarshal.Read(span);
- }
-
- public static uint AsUInt32(this Span span)
- {
- DebugOnly.Assert(span.Length >= sizeof(uint));
- return MemoryMarshal.Read(span);
- }
-
- public static ulong AsUInt64(this Span span)
- {
- DebugOnly.Assert(span.Length >= sizeof(ulong));
- return MemoryMarshal.Read(span);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEFile/PEFile.cs b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEFile/PEFile.cs
index 8354ccba5..4cb6d8fe7 100644
--- a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEFile/PEFile.cs
+++ b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEFile/PEFile.cs
@@ -206,7 +206,7 @@ public FileVersionInfo GetFileVersionInfo()
PEBuffer buff = AllocBuff();
byte* bytes = versionNode.FetchData(0, versionNode.DataLength, buff);
- FileVersionInfo ret = new FileVersionInfo(new Span(bytes, versionNode.DataLength));
+ FileVersionInfo ret = new FileVersionInfo(bytes, versionNode.DataLength);
FreeBuff(buff);
return ret;
diff --git a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEFile/ResourceNode.cs b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEFile/ResourceNode.cs
index cfea6d4f7..cd85c4fe6 100644
--- a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEFile/ResourceNode.cs
+++ b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEFile/ResourceNode.cs
@@ -26,8 +26,7 @@ public FileVersionInfo GetFileVersionInfo()
{
PEBuffer buff = _file.AllocBuff();
byte* bytes = FetchData(0, DataLength, buff);
-
- FileVersionInfo ret = new FileVersionInfo(new Span(bytes, DataLength));
+ FileVersionInfo ret = new FileVersionInfo(bytes, DataLength);
_file.FreeBuff(buff);
return ret;
}
diff --git a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/FileVersionInfo.cs b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/FileVersionInfo.cs
index 51d834f04..6e1e78fc2 100644
--- a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/FileVersionInfo.cs
+++ b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/FileVersionInfo.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Text;
namespace Microsoft.Diagnostics.Runtime.Utilities
{
@@ -27,16 +28,33 @@ public sealed unsafe class FileVersionInfo
///
public string? Comments { get; }
- internal FileVersionInfo(Span data)
+ internal FileVersionInfo(byte[] data, int dataLen)
{
- data = data.Slice(DataOffset);
- fixed (byte* ptr = data)
- {
- string dataAsString = new string((char*)ptr, 0, data.Length / 2);
+ FileVersion = "";
+ if (dataLen <= DataOffset)
+ return;
- FileVersion = GetDataString(dataAsString, "FileVersion");
- Comments = GetDataString(dataAsString, "Comments");
- }
+ var dataAsString = Encoding.Unicode.GetString(data, DataOffset, dataLen - DataOffset);
+
+ FileVersion = GetDataString(dataAsString, "FileVersion");
+ Comments = GetDataString(dataAsString, "Comments");
+ }
+
+ [Obsolete]
+ internal FileVersionInfo(byte* data, int dataLen)
+ {
+ FileVersion = "";
+ if (dataLen <= 0x5c)
+ return;
+
+ // See http://msdn.microsoft.com/en-us/library/ms647001(v=VS.85).aspx
+ byte* stringInfoPtr = data + 0x5c; // Gets to first StringInfo
+
+ // TODO search for FileVersion string ...
+ string dataAsString = new string((char*)stringInfoPtr, 0, (dataLen - 0x5c) / 2);
+
+ FileVersion = GetDataString(dataAsString, "FileVersion");
+ Comments = GetDataString(dataAsString, "Comments");
}
private static string? GetDataString(string dataAsString, string fileVersionKey)
diff --git a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/PEImage.cs b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/PEImage.cs
index aa8c07cdf..871f0c8d4 100644
--- a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/PEImage.cs
+++ b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/PEImage.cs
@@ -1,8 +1,8 @@
using Microsoft.Diagnostics.Runtime.Interop;
using System;
-using System.Buffers;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@@ -220,27 +220,11 @@ public int Read(byte[] dest, int virtualAddress, int bytesRequested)
return read;
}
- ///
- /// Reads data out of PE image into a native buffer.
- ///
- /// The address to read from.
- /// The location to write the data.
- /// The number of bytes actually read from the image and written to dest.
- public int Read(int virtualAddress, Span dest)
- {
- int offset = RvaToOffset(virtualAddress);
- if (offset == -1)
- return 0;
-
- SeekTo(offset);
- return Stream.Read(dest);
- }
-
///
/// Gets the File Version Information that is stored as a resource in the PE file. (This is what the
/// version tab a file's property page is populated with).
///
- public FileVersionInfo? GetFileVersionInfo()
+ public unsafe FileVersionInfo? GetFileVersionInfo()
{
ResourceEntry? versionNode = Resources.Children.FirstOrDefault(r => r.Name == "Version");
if (versionNode == null || versionNode.Children.Count != 1)
@@ -254,18 +238,11 @@ public int Read(int virtualAddress, Span dest)
if (size <= FileVersionInfo.DataOffset)
return null;
- byte[] buffer = ArrayPool.Shared.Rent(size);
- try
- {
- int count = versionNode.GetData(buffer);
- Span span = new Span(buffer, 0, count);
- FileVersionInfo result = new FileVersionInfo(span);
- return result;
- }
- finally
- {
- ArrayPool.Shared.Return(buffer);
- }
+ byte[] bytes = versionNode.GetData();
+
+ FileVersionInfo ret = new FileVersionInfo(bytes, versionNode.Size);
+
+ return ret;
}
private ResourceEntry CreateResourceRoot()
diff --git a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/ResourceEntry.cs b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/ResourceEntry.cs
index a842b43c5..b684aa39a 100644
--- a/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/ResourceEntry.cs
+++ b/src/Microsoft.Diagnostics.Runtime/src/Utilities/PEImage/ResourceEntry.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.Diagnostics.Runtime.Utilities
@@ -98,36 +98,24 @@ public byte[] GetData()
return result;
}
- ///
- /// Get the data associated with this entry.
- ///
- /// The location to write the data
- /// The number of bytes actually read from the image and written to dest
- public int GetData(Span span)
- {
- GetDataVaAndSize(out int va, out int size);
- if (size == 0 || va == 0)
- return 0;
-
- return Image.Read(va, span);
- }
-
///
/// A convenience function to get structured data out of this entry.
///
/// A struct type to convert.
/// The offset into the data.
/// The struct that was read out of the data section.
- public unsafe T GetData(int offset = 0) where T : unmanaged
+ public T GetData(int offset = 0) where T : struct
{
- int size = Unsafe.SizeOf();
- GetDataVaAndSize(out int va, out int sectionSize);
- if (va == 0 || sectionSize < size + offset)
- return default;
-
- T output;
- int read = Image.Read(va + offset, new Span(&output, size));
- return read == size ? output : default;
+ byte[] data = GetData();
+ int size = Marshal.SizeOf(typeof(T));
+ if (size + offset > data.Length)
+ throw new IndexOutOfRangeException();
+
+ GCHandle hnd = GCHandle.Alloc(data, GCHandleType.Pinned);
+ T result = (T)Marshal.PtrToStructure(hnd.AddrOfPinnedObject(), typeof(T));
+ hnd.Free();
+
+ return result;
}
private ResourceEntry[] GetChildren()