Skip to content

Commit

Permalink
Added MemoryMap C++ API.
Browse files Browse the repository at this point in the history
  • Loading branch information
bpotchik committed May 16, 2024
1 parent e824ffd commit 63a4614
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 13 deletions.
57 changes: 57 additions & 0 deletions binaryninjaapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -4241,6 +4241,7 @@ namespace BinaryNinja {
class DebugInfo;
class TypeLibrary;
class TypeArchive;
class MemoryMap;

class QueryMetadataException : public ExceptionWithStackTrace
{
Expand Down Expand Up @@ -4311,6 +4312,8 @@ namespace BinaryNinja {
*/
class BinaryView : public CoreRefCountObject<BNBinaryView, BNNewViewReference, BNFreeBinaryView>
{
std::unique_ptr<MemoryMap> m_memoryMap;

protected:
Ref<FileMetadata> m_file; //!< The underlying file

Expand Down Expand Up @@ -6311,6 +6314,12 @@ namespace BinaryNinja {
bool GetAddressInput(
uint64_t& result, const std::string& prompt, const std::string& title, uint64_t currentAddress);

/*! A mock object that is a placeholder during development of this feature.

\return MemoryMap object
*/
MemoryMap* GetMemoryMap() { return m_memoryMap.get(); }

/*! Add an analysis segment that specifies how data from the raw file is mapped into a virtual address space

\param start Starting virtual address
Expand Down Expand Up @@ -6651,6 +6660,54 @@ namespace BinaryNinja {
std::vector<Ref<ExternalLocation>> GetExternalLocations();
};

class MemoryMap
{
BNBinaryView* m_object;

public:
MemoryMap(BNBinaryView* view): m_object(view) {}
~MemoryMap() = default;

bool AddBinaryMemoryRegion(const std::string& name, uint64_t start, Ref<BinaryView> source)
{
return BNAddBinaryMemoryRegion(m_object, name.c_str(), start, source->GetObject());
}

bool AddDataMemoryRegion(const std::string& name, uint64_t start, const DataBuffer& source)
{
return BNAddDataMemoryRegion(m_object, name.c_str(), start, source.GetBufferObject());
}

bool AddRemoteMemoryRegion(const std::string& name, uint64_t start, FileAccessor* source)
{
return BNAddRemoteMemoryRegion(m_object, name.c_str(), start, source->GetCallbacks());
}

bool RemoveMemoryRegion(const std::string& name)
{
return BNRemoveMemoryRegion(m_object, name.c_str());
}

bool IsMemoryRegionEnabled(const std::string& name, uint64_t start)
{
return BNIsMemoryRegionEnabled(m_object, name.c_str(), start);
}

bool SetMemoryRegionEnabled(const std::string& name, uint64_t start, bool enabled)
{
return BNSetMemoryRegionEnabled(m_object, name.c_str(), start, enabled);
}

bool SetMemoryRegionFill(const std::string& name, uint64_t start, uint8_t fill)
{
return BNSetMemoryRegionFill(m_object, name.c_str(), start, fill);
}

void Reset()
{
BNResetMemoryMap(m_object);
}
};

/*!
\ingroup binaryview
Expand Down
2 changes: 2 additions & 0 deletions binaryview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1249,13 +1249,15 @@ BinaryView::BinaryView(const std::string& typeName, FileMetadata* file, BinaryVi
AddRefForRegistration();
m_object = BNCreateCustomBinaryView(
typeName.c_str(), m_file->GetObject(), parentView ? parentView->GetObject() : nullptr, &view);
m_memoryMap = std::make_unique<MemoryMap>(m_object);
}


BinaryView::BinaryView(BNBinaryView* view)
{
m_object = view;
m_file = new FileMetadata(BNGetFileForView(m_object));
m_memoryMap = std::make_unique<MemoryMap>(m_object);
}


Expand Down
41 changes: 28 additions & 13 deletions python/binaryview.py
Original file line number Diff line number Diff line change
Expand Up @@ -2119,7 +2119,8 @@ class MemoryMap:
BinaryView has a view into the MemoryMap which is described by the Segments defined in that BinaryView. The MemoryMap
object allows for the addition of multiple, arbitrary overlapping regions of memory. Segmenting of the address space is
automatically handled when the MemoryMap is modified and in the case where a portion of the system address space has
multilple defined regions, the default ordering gives priority to the most recently added region.
multilple defined regions, the default ordering gives priority to the most recently added region. This feature is
experimental and under active development.

:Example:

Expand Down Expand Up @@ -2230,19 +2231,33 @@ def __len__(self):
def description(self):
return json.loads(core.BNGetMemoryMapDescription(self.handle))

# // LoadBinary:
# // Loads a file in a loadable binary format.
# // Provides persistence, indicating that the loaded data will persist across sessions.
# // Presumably loads the file into memory according to the virtual and physical load addresses specified in the file itself.
# // LoadFile:
# // Loads a flat file or bytes directly at the specified address.
# // Provides persistence, suggesting that the loaded data will be saved and remain accessible across sessions.
# // Allows for direct loading of files or bytes into memory at a specified location.
# // LoadRemote:
# // Loads data from a remote source or interface.
# // Not persistent, implying that the loaded data is ephemeral and may not be saved across sessions.
# // Supports a target where bytes are provided/generated upon request, indicating a dynamic and potentially transient data source.
def add_memory_region(self, name: str, start: int, source: Union['os.PathLike', str, bytes, bytearray, 'BinaryView', 'databuffer.DataBuffer', 'fileaccessor.FileAccessor']) -> bool:
"""
Adds a memory region into the memory map. There are three types of memory regions that can be added:
- BinaryMemoryRegion(*** Unimplemented ***): Creates a memory region from a loadable binary format and provides persistence across sessions.
- DataMemoryRegion: Creates a memory region from a flat file or bytes and provide persistence across sessions.
- RemoteMemoryRegion: Creates a memory region from a proxy callback interface. This region is ephemeral and not saved across sessions.

The type of memory region added depends on the source parameter:
- `os.PathLike`, `str`, : Treats the source as a file path which is read and loaded into memory as a DataMemoryRegion.
- `bytes`, `bytearray`: Directly loads these byte formats into memory as a DataMemoryRegion.
- `databuffer.DataBuffer`: Directly loads a data buffer into memory as a DataMemoryRegion.
- `fileaccessor.FileAccessor`: Utilizes a file accessor to establish a RemoteMemoryRegion, managing data fetched from a remote source.

Parameters:
name (str): A unique name of the memory region.
start (int): The start address in memory where the region will be loaded.
source (Union[os.PathLike, str, bytes, bytearray, BinaryView, databuffer.DataBuffer, fileaccessor.FileAccessor]): The source from which the memory is loaded.

Returns:
bool: True if the memory region was successfully added, False otherwise.

Raises:
NotImplementedError: If the source type is not supported.

Notes:
If parts of the new memory region do not overlap with existing segments, new segments will be automatically created for each non-overlapping area, each with the SegmentFlag.SegmentReadable flag set.
"""
if isinstance(source, os.PathLike):
source = str(source)
if isinstance(source, bytes) or isinstance(source, bytearray):
Expand Down

0 comments on commit 63a4614

Please sign in to comment.