diff --git a/Function/BNGetMemoryRegions.cs b/Function/BNGetMemoryRegions.cs
index cf0a1d3..9e4c1ba 100644
--- a/Function/BNGetMemoryRegions.cs
+++ b/Function/BNGetMemoryRegions.cs
@@ -22,7 +22,7 @@ internal static extern IntPtr BNGetMemoryRegions(
IntPtr view ,
// size_t* count
- IntPtr count
+ out UIntPtr count
);
}
}
diff --git a/Function/BNGetResolvedMemoryRanges.cs b/Function/BNGetResolvedMemoryRanges.cs
index 2321c32..d83215e 100644
--- a/Function/BNGetResolvedMemoryRanges.cs
+++ b/Function/BNGetResolvedMemoryRanges.cs
@@ -22,7 +22,7 @@ internal static extern IntPtr BNGetResolvedMemoryRanges(
IntPtr view ,
// size_t* count
- IntPtr count
+ out UIntPtr count
);
}
}
diff --git a/Handle/BNBinaryView.cs b/Handle/BNBinaryView.cs
index eb22495..640b497 100644
--- a/Handle/BNBinaryView.cs
+++ b/Handle/BNBinaryView.cs
@@ -5884,6 +5884,11 @@ public bool MemoryMapActivated
}
}
+ public MemoryMap MemoryMap
+ {
+ get { return new MemoryMap(this); }
+ }
+
public bool AddMemoryRegion(
string name,
ulong start,
diff --git a/Handle/BNMemoryMap.cs b/Handle/BNMemoryMap.cs
new file mode 100644
index 0000000..312a1f5
--- /dev/null
+++ b/Handle/BNMemoryMap.cs
@@ -0,0 +1,371 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BinaryNinja
+{
+ /// Live proxy for a binary view's configured and resolved memory map.
+ public sealed class MemoryMap
+ {
+ private readonly BinaryView view;
+
+ internal MemoryMap(BinaryView view)
+ {
+ this.view = view;
+ }
+
+ public bool IsActivated
+ {
+ get { return NativeMethods.BNIsMemoryMapActivated(this.view.DangerousGetHandle()); }
+ }
+
+ public MemoryRegionInfo[] Regions
+ {
+ get { return this.GetMemoryRegions(); }
+ }
+
+ public ResolvedMemoryRange[] Ranges
+ {
+ get { return this.GetResolvedRanges(); }
+ }
+
+ public ResolvedMemoryRange[] ResolvedRanges
+ {
+ get { return this.GetResolvedRanges(); }
+ }
+
+ public string Description
+ {
+ get { return this.view.MemoryMapDescription; }
+ }
+
+ public string BaseDescription
+ {
+ get { return this.view.BaseMemoryMapDescription; }
+ }
+
+ public void SetLogicalMemoryMapEnabled(bool enabled)
+ {
+ NativeMethods.BNSetLogicalMemoryMapEnabled(this.view.DangerousGetHandle(), enabled);
+ }
+
+ public bool AddBinaryMemoryRegion(
+ string name,
+ ulong start,
+ BinaryView source,
+ uint flags = 0
+ )
+ {
+ return this.view.AddMemoryRegion(name, start, source, flags);
+ }
+
+ public bool AddMemoryRegion(
+ string name,
+ ulong start,
+ BinaryView source,
+ uint flags = 0
+ )
+ {
+ return this.AddBinaryMemoryRegion(name, start, source, flags);
+ }
+
+ public bool AddDataMemoryRegion(
+ string name,
+ ulong start,
+ DataBuffer source,
+ uint flags = 0
+ )
+ {
+ return this.view.AddMemoryRegion(name, start, source, flags);
+ }
+
+ public bool AddMemoryRegion(
+ string name,
+ ulong start,
+ DataBuffer source,
+ uint flags = 0
+ )
+ {
+ return this.AddDataMemoryRegion(name, start, source, flags);
+ }
+
+ public bool AddRemoteMemoryRegion(
+ string name,
+ ulong start,
+ FileAccessor source,
+ uint flags = 0
+ )
+ {
+ return this.view.AddMemoryRegion(name, start, source, flags);
+ }
+
+ public bool AddMemoryRegion(
+ string name,
+ ulong start,
+ FileAccessor source,
+ uint flags = 0
+ )
+ {
+ return this.AddRemoteMemoryRegion(name, start, source, flags);
+ }
+
+ public bool AddUnbackedMemoryRegion(
+ string name,
+ ulong start,
+ ulong length,
+ uint flags = 0,
+ byte fill = 0
+ )
+ {
+ return this.view.AddMemoryRegion(name, start, length, flags, fill);
+ }
+
+ public bool AddMemoryRegion(
+ string name,
+ ulong start,
+ ulong length,
+ uint flags = 0,
+ byte fill = 0
+ )
+ {
+ return this.AddUnbackedMemoryRegion(name, start, length, flags, fill);
+ }
+
+ public bool RemoveMemoryRegion(string name)
+ {
+ return this.view.RemoveMemoryRegion(name);
+ }
+
+ public string GetActiveMemoryRegionAt(ulong address)
+ {
+ return this.view.GetActiveMemoryRegionAt(address);
+ }
+
+ public uint GetMemoryRegionFlags(string name)
+ {
+ return this.view.GetMemoryRegionFlags(name);
+ }
+
+ public bool SetMemoryRegionFlags(string name, uint flags)
+ {
+ return this.view.SetMemoryRegionFlags(name, flags);
+ }
+
+ public bool IsMemoryRegionEnabled(string name)
+ {
+ return this.view.IsMemoryRegionEnabled(name);
+ }
+
+ public bool SetMemoryRegionEnabled(string name, bool enabled)
+ {
+ return this.view.SetMemoryRegionEnabled(name, enabled);
+ }
+
+ public bool IsMemoryRegionRebaseable(string name)
+ {
+ return this.view.IsMemoryRegionRebaseable(name);
+ }
+
+ public bool SetMemoryRegionRebaseable(string name, bool rebaseable)
+ {
+ return this.view.SetMemoryRegionRebaseable(name, rebaseable);
+ }
+
+ public byte GetMemoryRegionFill(string name)
+ {
+ return this.view.GetMemoryRegionFill(name);
+ }
+
+ public bool SetMemoryRegionFill(string name, byte fill)
+ {
+ return this.view.SetMemoryRegionFill(name, fill);
+ }
+
+ public bool IsMemoryRegionLocal(string name)
+ {
+ return this.view.IsMemoryRegionLocal(name);
+ }
+
+ public string GetMemoryRegionDisplayName(string name)
+ {
+ return UnsafeUtils.TakeUtf8String(
+ NativeMethods.BNGetMemoryRegionDisplayName(this.view.DangerousGetHandle(), name)
+ );
+ }
+
+ public bool SetMemoryRegionDisplayName(string name, string displayName)
+ {
+ return NativeMethods.BNSetMemoryRegionDisplayName(
+ this.view.DangerousGetHandle(),
+ name,
+ displayName
+ );
+ }
+
+ public MemoryRegionInfo? GetMemoryRegionInfo(string name)
+ {
+ using (ScopedAllocator allocator = new ScopedAllocator())
+ {
+ IntPtr result = allocator.AllocHGlobal(Marshal.SizeOf());
+ if (!NativeMethods.BNGetMemoryRegionInfo(
+ this.view.DangerousGetHandle(),
+ name,
+ result
+ ))
+ {
+ return null;
+ }
+
+ try
+ {
+ return MemoryRegionInfo.FromNative(
+ Marshal.PtrToStructure(result)
+ );
+ }
+ finally
+ {
+ NativeMethods.BNFreeMemoryRegionInfo(result);
+ }
+ }
+ }
+
+ public MemoryRegionInfo? GetRegion(string name)
+ {
+ return this.GetMemoryRegionInfo(name);
+ }
+
+ public MemoryRegionInfo? GetActiveMemoryRegionInfoAt(ulong address)
+ {
+ using (ScopedAllocator allocator = new ScopedAllocator())
+ {
+ IntPtr result = allocator.AllocHGlobal(Marshal.SizeOf());
+ if (!NativeMethods.BNGetActiveMemoryRegionInfoAt(
+ this.view.DangerousGetHandle(),
+ address,
+ result
+ ))
+ {
+ return null;
+ }
+
+ try
+ {
+ return MemoryRegionInfo.FromNative(
+ Marshal.PtrToStructure(result)
+ );
+ }
+ finally
+ {
+ NativeMethods.BNFreeMemoryRegionInfo(result);
+ }
+ }
+ }
+
+ public MemoryRegionInfo? GetActiveRegionAt(ulong address)
+ {
+ return this.GetActiveMemoryRegionInfoAt(address);
+ }
+
+ public ResolvedMemoryRange? GetResolvedMemoryRangeAt(ulong address)
+ {
+ using (ScopedAllocator allocator = new ScopedAllocator())
+ {
+ IntPtr result = allocator.AllocHGlobal(Marshal.SizeOf());
+ if (!NativeMethods.BNGetResolvedMemoryRangeAt(
+ this.view.DangerousGetHandle(),
+ address,
+ result
+ ))
+ {
+ return null;
+ }
+
+ try
+ {
+ return ResolvedMemoryRange.FromNative(
+ Marshal.PtrToStructure(result)
+ );
+ }
+ finally
+ {
+ NativeMethods.BNFreeResolvedMemoryRange(result);
+ }
+ }
+ }
+
+ public ResolvedMemoryRange? GetResolvedRangeAt(ulong address)
+ {
+ return this.GetResolvedMemoryRangeAt(address);
+ }
+
+ public MemoryRegionInfo[] GetMemoryRegions()
+ {
+ IntPtr regions = NativeMethods.BNGetMemoryRegions(
+ this.view.DangerousGetHandle(),
+ out UIntPtr countValue
+ );
+ ulong count = countValue.ToUInt64();
+ if (IntPtr.Zero == regions)
+ {
+ return Array.Empty();
+ }
+
+ try
+ {
+ MemoryRegionInfo[] result = new MemoryRegionInfo[checked((int)count)];
+ int nativeSize = Marshal.SizeOf();
+ for (ulong i = 0; i < count; i++)
+ {
+ int offset = checked((int)(i * (ulong)nativeSize));
+ BNMemoryRegionInfo item = Marshal.PtrToStructure(
+ IntPtr.Add(regions, offset)
+ );
+ result[checked((int)i)] = MemoryRegionInfo.FromNative(item);
+ }
+
+ return result;
+ }
+ finally
+ {
+ NativeMethods.BNFreeMemoryRegions(regions, countValue);
+ }
+ }
+
+ public ResolvedMemoryRange[] GetResolvedRanges()
+ {
+ IntPtr ranges = NativeMethods.BNGetResolvedMemoryRanges(
+ this.view.DangerousGetHandle(),
+ out UIntPtr countValue
+ );
+ ulong count = countValue.ToUInt64();
+ if (IntPtr.Zero == ranges)
+ {
+ return Array.Empty();
+ }
+
+ try
+ {
+ ResolvedMemoryRange[] result = new ResolvedMemoryRange[checked((int)count)];
+ int nativeSize = Marshal.SizeOf();
+ for (ulong i = 0; i < count; i++)
+ {
+ int offset = checked((int)(i * (ulong)nativeSize));
+ BNResolvedMemoryRange item = Marshal.PtrToStructure(
+ IntPtr.Add(ranges, offset)
+ );
+ result[checked((int)i)] = ResolvedMemoryRange.FromNative(item);
+ }
+
+ return result;
+ }
+ finally
+ {
+ NativeMethods.BNFreeResolvedMemoryRanges(ranges, countValue);
+ }
+ }
+
+ public void Reset()
+ {
+ this.view.ResetMemoryMap();
+ }
+ }
+}
diff --git a/Struct/BNMemoryRegionInfo.cs b/Struct/BNMemoryRegionInfo.cs
new file mode 100644
index 0000000..a65ee59
--- /dev/null
+++ b/Struct/BNMemoryRegionInfo.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BinaryNinja
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct BNMemoryRegionInfo
+ {
+ internal IntPtr name;
+ internal IntPtr displayName;
+ internal ulong start;
+ internal ulong length;
+ internal uint flags;
+ [MarshalAs(UnmanagedType.I1)] internal bool enabled;
+ [MarshalAs(UnmanagedType.I1)] internal bool rebaseable;
+ internal byte fill;
+ [MarshalAs(UnmanagedType.I1)] internal bool hasTarget;
+ [MarshalAs(UnmanagedType.I1)] internal bool absoluteAddressMode;
+ [MarshalAs(UnmanagedType.I1)] internal bool local;
+ }
+
+ /// Immutable snapshot of a configured memory region.
+ public sealed class MemoryRegionInfo
+ {
+ public string Name { get; }
+ public string DisplayName { get; }
+ public ulong Start { get; }
+ public ulong Length { get; }
+ public ulong End { get { return checked(this.Start + this.Length); } }
+ public SegmentFlag Flags { get; }
+ public bool Enabled { get; }
+ public bool Rebaseable { get; }
+ public byte Fill { get; }
+ public bool HasTarget { get; }
+ public bool AbsoluteAddressMode { get; }
+ public bool Local { get; }
+
+ internal MemoryRegionInfo(
+ string name,
+ string displayName,
+ ulong start,
+ ulong length,
+ SegmentFlag flags,
+ bool enabled,
+ bool rebaseable,
+ byte fill,
+ bool hasTarget,
+ bool absoluteAddressMode,
+ bool local
+ )
+ {
+ this.Name = name;
+ this.DisplayName = displayName;
+ this.Start = start;
+ this.Length = length;
+ this.Flags = flags;
+ this.Enabled = enabled;
+ this.Rebaseable = rebaseable;
+ this.Fill = fill;
+ this.HasTarget = hasTarget;
+ this.AbsoluteAddressMode = absoluteAddressMode;
+ this.Local = local;
+ }
+
+ internal static MemoryRegionInfo FromNative(BNMemoryRegionInfo native)
+ {
+ return new MemoryRegionInfo(
+ UnsafeUtils.ReadUtf8String(native.name),
+ UnsafeUtils.ReadUtf8String(native.displayName),
+ native.start,
+ native.length,
+ (SegmentFlag)native.flags,
+ native.enabled,
+ native.rebaseable,
+ native.fill,
+ native.hasTarget,
+ native.absoluteAddressMode,
+ native.local
+ );
+ }
+ }
+}
diff --git a/Struct/BNResolvedMemoryRange.cs b/Struct/BNResolvedMemoryRange.cs
new file mode 100644
index 0000000..5143fd9
--- /dev/null
+++ b/Struct/BNResolvedMemoryRange.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BinaryNinja
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct BNResolvedMemoryRange
+ {
+ internal ulong start;
+ internal ulong length;
+ internal IntPtr regions;
+ internal UIntPtr regionCount;
+ }
+
+ /// Immutable non-overlapping interval in the resolved memory map.
+ public sealed class ResolvedMemoryRange
+ {
+ public ulong Start { get; }
+ public ulong Length { get; }
+ public ulong End { get { return checked(this.Start + this.Length); } }
+ public MemoryRegionInfo[] Regions { get; }
+
+ public MemoryRegionInfo? ActiveRegion
+ {
+ get { return 0 == this.Regions.Length ? null : this.Regions[0]; }
+ }
+
+ public string? Name
+ {
+ get
+ {
+ MemoryRegionInfo? active = this.ActiveRegion;
+ return null == active ? null : active.Name;
+ }
+ }
+
+ public SegmentFlag Flags
+ {
+ get
+ {
+ MemoryRegionInfo? active = this.ActiveRegion;
+ return null == active ? (SegmentFlag)0 : active.Flags;
+ }
+ }
+
+ internal ResolvedMemoryRange(
+ ulong start,
+ ulong length,
+ MemoryRegionInfo[] regions
+ )
+ {
+ this.Start = start;
+ this.Length = length;
+ this.Regions = regions;
+ }
+
+ internal static ResolvedMemoryRange FromNative(BNResolvedMemoryRange native)
+ {
+ ulong count = native.regionCount.ToUInt64();
+ MemoryRegionInfo[] regions = new MemoryRegionInfo[checked((int)count)];
+ int nativeSize = Marshal.SizeOf();
+
+ for (ulong i = 0; i < count; i++)
+ {
+ int offset = checked((int)(i * (ulong)nativeSize));
+ BNMemoryRegionInfo item = Marshal.PtrToStructure(
+ IntPtr.Add(native.regions, offset)
+ );
+ regions[checked((int)i)] = MemoryRegionInfo.FromNative(item);
+ }
+
+ return new ResolvedMemoryRange(native.start, native.length, regions);
+ }
+ }
+}