Skip to content

Commit

Permalink
Add ReadMemory() to DmdModule
Browse files Browse the repository at this point in the history
  • Loading branch information
wtfsck committed Oct 22, 2017
1 parent 5f7b732 commit 2678850
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,53 @@ public DmdMethodInfo GetMethod(string name, DmdBindingFlags bindingAttr, DmdCall
/// <returns></returns>
public abstract DmdReadOnlyAssemblyName[] GetReferencedAssemblies();

/// <summary>
/// Reads memory. Returns false if data couldn't be read.
/// </summary>
/// <param name="rva">RVA of data</param>
/// <param name="destination">Destination address</param>
/// <param name="size">Number of bytes to read</param>
/// <returns></returns>
public abstract unsafe bool ReadMemory(uint rva, void* destination, int size);

/// <summary>
/// Reads memory. Returns false if data couldn't be read.
/// </summary>
/// <param name="rva">RVA of data</param>
/// <param name="destination">Destination buffer</param>
/// <param name="destinationIndex">Destination index</param>
/// <param name="size">Number of bytes to read</param>
/// <returns></returns>
public unsafe bool ReadMemory(uint rva, byte[] destination, int destinationIndex, int size) {
if (destination == null)
throw new ArgumentNullException(nameof(destination));
if ((uint)destinationIndex > (uint)destination.Length)
throw new ArgumentOutOfRangeException(nameof(destinationIndex));
if (size < 0)
throw new ArgumentOutOfRangeException(nameof(size));
if ((uint)(destinationIndex + size) > (uint)destination.Length)
throw new ArgumentOutOfRangeException(nameof(destinationIndex));
if (size == 0)
return true;
fixed (void* p = &destination[destinationIndex])
return ReadMemory(rva, p, size);
}

/// <summary>
/// Reads memory. Returns null if data couldn't be read.
/// </summary>
/// <param name="rva">RVA of data</param>
/// <param name="size">Number of bytes to read</param>
/// <returns></returns>
public byte[] ReadMemory(uint rva, int size) {
if (size == 0)
return Array.Empty<byte>();
var res = new byte[size];
if (!ReadMemory(rva, res, 0, size))
return null;
return res;
}

/// <summary>
/// Returns the metadata name (<see cref="ScopeName"/>)
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,8 @@ internal DmdReadOnlyAssemblyName ReadAssemblyName_COMThread(uint rid) {
return new DmdReadOnlyAssemblyName(name, version, cultureName, flags, publicKeyOrToken, DmdAssemblyHashAlgorithm.None);
}

public override unsafe bool ReadMemory(uint rva, void* destination, int size) => false;

protected override DmdCustomAttributeData[] ReadAssemblyCustomAttributes(uint rid) => ReadCustomAttributesCore(0x20000000 + rid);
protected override DmdCustomAttributeData[] ReadModuleCustomAttributes(uint rid) => ReadCustomAttributesCore(0x00000000 + rid);
protected override DmdCustomAttributeData[] ReadTypeDefCustomAttributes(uint rid) => ReadCustomAttributesCore(0x02000000 + rid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ internal void SetModule(DmdModuleImpl module) {
public override void GetPEKind(out DmdPortableExecutableKinds peKind, out DmdImageFileMachine machine) => MetadataReader.GetPEKind(out peKind, out machine);
public override DmdReadOnlyAssemblyName GetName() => MetadataReader.GetName();
public override DmdReadOnlyAssemblyName[] GetReferencedAssemblies() => MetadataReader.GetReferencedAssemblies();
public override unsafe bool ReadMemory(uint rva, void* destination, int size) => MetadataReader.ReadMemory(rva, destination, size);
public override DmdCustomAttributeData[] ReadCustomAttributes(int metadataToken) => MetadataReader.ReadCustomAttributes(metadataToken);
public override DmdCustomAttributeData[] ReadSecurityAttributes(int metadataToken) => MetadataReader.ReadSecurityAttributes(metadataToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ abstract class DmdMetadataReader {
public abstract void GetPEKind(out DmdPortableExecutableKinds peKind, out DmdImageFileMachine machine);
public abstract DmdReadOnlyAssemblyName GetName();
public abstract DmdReadOnlyAssemblyName[] GetReferencedAssemblies();
public abstract unsafe bool ReadMemory(uint rva, void* destination, int size);
public abstract DmdCustomAttributeData[] ReadCustomAttributes(int metadataToken);
public abstract DmdCustomAttributeData[] ReadSecurityAttributes(int metadataToken);
public abstract event EventHandler<DmdTypesUpdatedEventArgs> TypesUpdated;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public DmdModuleImpl(DmdAssemblyImpl assembly, DmdMetadataReader metadataReader,
public override string ResolveString(int metadataToken) => metadataReader.ResolveString(metadataToken);
public override void GetPEKind(out DmdPortableExecutableKinds peKind, out DmdImageFileMachine machine) => metadataReader.GetPEKind(out peKind, out machine);
public override DmdReadOnlyAssemblyName[] GetReferencedAssemblies() => metadataReader.GetReferencedAssemblies();
public override unsafe bool ReadMemory(uint rva, void* destination, int size) => metadataReader.ReadMemory(rva, destination, size);

sealed class TypeDefResolver : ITypeDefResolver {
readonly DmdModuleImpl module;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public override void GetPEKind(out DmdPortableExecutableKinds peKind, out DmdIma
}
public override DmdReadOnlyAssemblyName GetName() => new DmdReadOnlyAssemblyName("NullAssembly");
public override DmdReadOnlyAssemblyName[] GetReferencedAssemblies() => Array.Empty<DmdReadOnlyAssemblyName>();
public override unsafe bool ReadMemory(uint rva, void* destination, int size) => false;
protected override DmdCustomAttributeData[] ReadAssemblyCustomAttributes(uint rid) => Array.Empty<DmdCustomAttributeData>();
protected override DmdCustomAttributeData[] ReadModuleCustomAttributes(uint rid) => Array.Empty<DmdCustomAttributeData>();
protected override DmdCustomAttributeData[] ReadTypeDefCustomAttributes(uint rid) => Array.Empty<DmdCustomAttributeData>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ You should have received a copy of the GNU General Public License
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using dnlib.DotNet;
using dnlib.DotNet.MD;
using dnlib.PE;
Expand Down Expand Up @@ -578,6 +579,20 @@ internal DmdReadOnlyAssemblyName ReadAssemblyName(uint rid) {
return new DmdReadOnlyAssemblyName(name, version, cultureName, flags, publicKeyOrToken, DmdAssemblyHashAlgorithm.None);
}

public override unsafe bool ReadMemory(uint rva, void* destination, int size) {
if (destination == null)
throw new ArgumentNullException(nameof(destination));
if (size < 0)
throw new ArgumentOutOfRangeException(nameof(size));
using (var stream = Metadata.PEImage.CreateStream((RVA)rva, size)) {
if (stream.Length < size)
return false;
var bytes = stream.ReadBytes(size);
Marshal.Copy(bytes, 0, new IntPtr(destination), size);
return true;
}
}

protected override DmdCustomAttributeData[] ReadAssemblyCustomAttributes(uint rid) => ReadCustomAttributesCore(Table.Assembly, rid);
protected override DmdCustomAttributeData[] ReadModuleCustomAttributes(uint rid) => ReadCustomAttributesCore(Table.Module, rid);
protected override DmdCustomAttributeData[] ReadTypeDefCustomAttributes(uint rid) => ReadCustomAttributesCore(Table.TypeDef, rid);
Expand Down
20 changes: 11 additions & 9 deletions Extensions/dnSpy.Debugger/dnSpy.Debugger/Impl/DbgProcessImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,10 @@ public unsafe override void ReadMemory(ulong address, byte[] destination, int de
ReadMemory(address, p, size);
}

public override void ReadMemory(ulong address, byte* destination, int size) {
public override void ReadMemory(ulong address, void* destination, int size) {
var dest = (byte*)destination;
if (hProcess.IsClosed || (Bitness == 32 && address > uint.MaxValue)) {
Clear(destination, size);
Clear(dest, size);
return;
}

Expand All @@ -288,20 +289,20 @@ public override void ReadMemory(ulong address, byte* destination, int size) {
if ((ulong)len > pageSizeLeft)
len = (int)pageSizeLeft;

bool b = NativeMethods.ReadProcessMemory(hProcessLocal, (void*)address, destination, new IntPtr(len), out var sizeRead);
bool b = NativeMethods.ReadProcessMemory(hProcessLocal, (void*)address, dest, new IntPtr(len), out var sizeRead);

int read = !b ? 0 : (int)sizeRead.ToInt64();
Debug.Assert(read <= len);
Debug.Assert(read == 0 || read == len);
if (read != len)
Clear(destination + read, len - read);
Clear(dest + read, len - read);

address += (ulong)len;
count -= (uint)len;
destination += len;
dest += len;

if (address == endAddr) {
Clear(destination, (int)count);
Clear(dest, (int)count);
break;
}
}
Expand All @@ -324,7 +325,8 @@ public unsafe override void WriteMemory(ulong address, byte[] source, int source
WriteMemory(address, p, size);
}

public override void WriteMemory(ulong address, byte* source, int size) {
public override void WriteMemory(ulong address, void* source, int size) {
var src = (byte*)source;
if (hProcess.IsClosed || (Bitness == 32 && address > uint.MaxValue))
return;

Expand All @@ -341,13 +343,13 @@ public override void WriteMemory(ulong address, byte* source, int size) {
len = (int)pageSizeLeft;

bool restoreOldProtect = NativeMethods.VirtualProtectEx(hProcessLocal, (void*)address, new IntPtr(len), NativeMethods.PAGE_EXECUTE_READWRITE, out uint oldProtect);
NativeMethods.WriteProcessMemory(hProcessLocal, (void*)address, source, new IntPtr(len), out var sizeWritten);
NativeMethods.WriteProcessMemory(hProcessLocal, (void*)address, src, new IntPtr(len), out var sizeWritten);
if (restoreOldProtect)
NativeMethods.VirtualProtectEx(hProcessLocal, (void*)address, new IntPtr(len), oldProtect, out oldProtect);

address += (ulong)len;
count -= (uint)len;
source += len;
src += len;

if (address == endAddr)
break;
Expand Down
4 changes: 2 additions & 2 deletions dnSpy/dnSpy.Contracts.Debugger/DbgProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public abstract class DbgProcess : DbgObject, INotifyPropertyChanged {
/// <param name="destination">Destination address</param>
/// <param name="size">Number of bytes to read</param>
/// <returns></returns>
public unsafe abstract void ReadMemory(ulong address, byte* destination, int size);
public unsafe abstract void ReadMemory(ulong address, void* destination, int size);

/// <summary>
/// Reads memory. Unreadable memory is returned as 0s.
Expand All @@ -137,7 +137,7 @@ public abstract class DbgProcess : DbgObject, INotifyPropertyChanged {
/// <param name="source">Source address</param>
/// <param name="size">Number of bytes to write</param>
/// <returns></returns>
public unsafe abstract void WriteMemory(ulong address, byte* source, int size);
public unsafe abstract void WriteMemory(ulong address, void* source, int size);

/// <summary>
/// Writes memory.
Expand Down

0 comments on commit 2678850

Please sign in to comment.