summaryrefslogtreecommitdiff
path: root/view/sharedcache/api
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-03-10 11:05:40 -0400
committerMason Reed <mason@vector35.com>2025-04-02 05:36:54 -0400
commit25cc02431b61097b2adfc2fbc493b648b0300c3b (patch)
treea79d9c4f4f67234d3bf9bda413e8608f479a4cc8 /view/sharedcache/api
parentfa85bf28502286c4821427c5d0ed91a7ed46f8f6 (diff)
[SharedCache] Refactor Shared Cache
In absence of a better name, this commit refactors the shared cache code.
Diffstat (limited to 'view/sharedcache/api')
-rw-r--r--view/sharedcache/api/python/sharedcache.py580
-rw-r--r--view/sharedcache/api/python/sharedcache_enums.py44
-rw-r--r--view/sharedcache/api/sharedcache.cpp485
-rw-r--r--view/sharedcache/api/sharedcacheapi.h490
-rw-r--r--view/sharedcache/api/sharedcachecore.h202
5 files changed, 927 insertions, 874 deletions
diff --git a/view/sharedcache/api/python/sharedcache.py b/view/sharedcache/api/python/sharedcache.py
index dab5583e..83be388b 100644
--- a/view/sharedcache/api/python/sharedcache.py
+++ b/view/sharedcache/api/python/sharedcache.py
@@ -1,389 +1,293 @@
-import os
import ctypes
import dataclasses
-import traceback
+from typing import Optional
import binaryninja
+from binaryninja import BinaryView
from binaryninja._binaryninjacore import BNFreeStringList, BNAllocString, BNFreeString
from . import _sharedcachecore as sccore
from .sharedcache_enums import *
-
-@dataclasses.dataclass
-class DSCMemoryMapping:
- name: str
- vmAddress: int
- size: int
-
- def __str__(self):
- return repr(self)
-
- def __repr__(self):
- return f"<DSCMemoryMapping '{self.name}': {self.vmAddress:x}+{self.size:x}>"
-
-
@dataclasses.dataclass
-class LoadedRegion:
- name: str
- headerAddress: int
- mappings: list[DSCMemoryMapping]
-
- def __str__(self):
- return repr(self)
-
- def __repr__(self):
- return f"<LoadedRegion {self.name} @ {self.headerAddress:x}>"
-
-
-@dataclasses.dataclass
-class DSCBackingCacheMapping:
- vmAddress: int
- size: int
- fileOffset: int
-
- def __str__(self):
- return repr(self)
+class CacheRegion:
+ region_type: SharedCacheRegionType
+ name: str
+ start: int
+ size: int
+ image_start: int
+ # TODO: Might want to make this use the BN segment flag enum?
+ flags: sccore.SegmentFlagEnum
- def __repr__(self):
- return f"<DSCBackingCacheMapping {self.vmAddress:x}+{self.size:x} @ {self.fileOffset:x}"
+ def __str__(self):
+ return repr(self)
+ def __repr__(self):
+ return f"<CacheRegion '{self.name}': 0x{self.start:x} + {self.size:x}>"
@dataclasses.dataclass
-class DSCBackingCache:
- path: str
- cacheType: BackingCacheType
- mappings: list[DSCBackingCacheMapping]
-
- def __str__(self):
- return repr(self)
-
- def __repr__(self):
- cache_type_str = 'Unknown'
- if self.cacheType == BackingCacheType.BackingCacheTypePrimary:
- cache_type_str = 'Primary'
- elif self.cacheType == BackingCacheType.BackingCacheTypeSecondary:
- cache_type_str = 'Secondary'
- elif self.cacheType == BackingCacheType.BackingCacheTypeSymbols:
- cache_type_str = 'Symbols'
- return f"<DSCBackingCache {self.path} {cache_type_str} | {len(self.mappings)} mappings>"
-
-
-@dataclasses.dataclass
-class DSCImageMemoryMapping:
- filePath: str
- name: str
- vmAddress: int
- size: int
- loaded: bool
- rawViewOffset: int
-
- def __str__(self):
- return repr(self)
-
- def __repr__(self):
- return f"<DSCImageMemoryMapping '{self.name}' {os.path.basename(self.filePath)} raw<{self.rawViewOffset:x}>: {self.vmAddress:x}+{self.size:x}>"
-
-
-@dataclasses.dataclass
-class DSCImage:
- name: str
- headerAddress: int
- mappings: list[DSCImageMemoryMapping]
-
- def __str__(self):
- return repr(self)
+class CacheImage:
+ name: str
+ header_address: int
+ region_starts: [int]
- def __repr__(self):
- return f"<DSCImage {self.name} @ {self.headerAddress:x}>"
+ def __str__(self):
+ return repr(self)
+ def __repr__(self):
+ return f"<CacheImage '{self.name}': 0x{self.header_address:x}>"
@dataclasses.dataclass
-class DSCSymbol:
- name: str
- image: str
- address: int
-
- def __str__(self):
- return repr(self)
-
- def __repr__(self):
- return f"<DSCSymbol {self.name} @ {self.address:x} ({self.image}>"
-
-
-class SharedCache:
- """
- SharedCache is the primary class for interacting with the shared cache processor and DSCView metadata.
-
- You can create a SharedCache object from a BinaryView object by calling `SharedCache(bv)`, where `bv` is the BinaryView.
-
- By default `bv` in the console will return the instance of the BinaryView that is currently open, \
- so in the UI, you can use `dsc = SharedCache(bv)` to create a SharedCache object in the scripting console.
-
- Methods and attributes in this class have documentation which can be viewed by typing `SharedCache.method_or_attribute_name?` in the console.
- """
- def __init__(self, view):
- self.handle = sccore.BNGetSharedCache(view.handle)
-
- def load_image_with_install_name(self, install_name, skip_loading_objective_c = False) -> bool:
- """
- Locate an image with the provided install name and load it into the shared cache view
-
- :param install_name: Install name of the image
- :param skip_loading_objective_c: Whether to skip process Objective-C information for this image. Default false.
- :return:
- """
- return sccore.BNDSCViewLoadImageWithInstallName(self.handle, install_name, skip_loading_objective_c)
-
- def load_section_at_address(self, addr) -> bool:
- """
- Load a singular section at the provided address into the shared cache view.
-
- This will partial-load the image, only mapping the requested segment containing this section.
-
- Image info will still be processed, but will only be applied to mapped regions.
-
- :param addr: Address within the section
- :return:
- """
- return sccore.BNDSCViewLoadSectionAtAddress(self.handle, addr)
-
- def load_image_containing_address(self, addr, skip_loading_objective_c = False) -> bool:
- """
- Load the image containing the provided address into the shared cache view.
-
- :param addr: Address within the image to load
- :param skip_loading_objective_c: Whether to skip processing Objective-C information for this image. Default false.
- :return:
- """
- return sccore.BNDSCViewLoadImageContainingAddress(self.handle, addr, skip_loading_objective_c)
-
- def process_objc_sections_for_image_with_install_name(self, install_name) -> bool:
- """
- Process Objective-C information for the image with the provided install name.
-
- :param install_name: Install name of the image
- :return:
- """
- return sccore.BNDSCViewProcessObjCSectionsForImageWithInstallName(self.handle, install_name, False)
-
- def process_all_objc_sections(self) -> bool:
- """
- Process Objective-C information for all images in the shared cache view.
-
- :return:
- """
- return sccore.BNDSCViewProcessAllObjCSections(self.handle)
-
- @property
- def caches(self) -> list[DSCBackingCache]:
- """
- Get all backing caches in the shared cache.
- :return:
- """
- count = ctypes.c_ulonglong()
- value = sccore.BNDSCViewGetBackingCaches(self.handle, count)
- if value is None:
- return []
-
- result = []
- for i in range(count.value):
- mappings = []
- for j in range(value[i].mappingCount):
- mapping = DSCBackingCacheMapping(
- value[i].mappings[j].vmAddress,
- value[i].mappings[j].size,
- value[i].mappings[j].fileOffset
- )
- mappings.append(mapping)
- result.append(DSCBackingCache(
- value[i].path,
- value[i].cacheType,
- mappings
- ))
-
- sccore.BNDSCViewFreeBackingCaches(value, count)
- return result
-
- @property
- def images(self) -> list[DSCImage]:
- """
- Get all images in the shared cache
- :return:
- """
- count = ctypes.c_ulonglong()
- value = sccore.BNDSCViewGetAllImages(self.handle, count)
- if value is None:
- return []
+class CacheSymbol:
+ symbol_type: sccore.SymbolTypeEnum
+ address: int
+ name: str
- result = []
- for i in range(count.value):
- mappings = []
- for j in range(value[i].mappingCount):
- mapping = DSCImageMemoryMapping(
- value[i].mappings[j].filePath,
- value[i].mappings[j].name,
- value[i].mappings[j].vmAddress,
- value[i].mappings[j].size,
- value[i].mappings[j].loaded,
- value[i].mappings[j].rawViewOffset
- )
- mappings.append(mapping)
- result.append(DSCImage(
- value[i].name,
- value[i].headerAddress,
- mappings
- ))
+ def __str__(self):
+ return repr(self)
- sccore.BNDSCViewFreeAllImages(value, count)
- return result
+ def __repr__(self):
+ return f"<CacheSymbol '{self.name}': 0x{self.address:x}>"
- @property
- def loaded_regions(self) -> list[LoadedRegion]:
- """
- Get all loaded regions in the shared cache
+def region_from_api(region: sccore.BNSharedCacheRegion) -> CacheRegion:
+ return CacheRegion(
+ region_type=SharedCacheRegionType(region.regionType),
+ name=region.name,
+ start=region.vmAddress,
+ size=region.size,
+ image_start=region.imageStart,
+ flags=region.flags
+ )
- The internal logic for loading images treats a region as 'loaded' whenever
- that region has been mapped into memory, and, if it's located within an image, header information has been applied to that region.
+def region_to_api(region: CacheRegion) -> sccore.BNSharedCacheRegion:
+ return sccore.BNSharedCacheRegion(
+ regionType=region.region_type,
+ _name=BNAllocString(region.name),
+ vmAddress=region.start,
+ size=region.size,
+ imageStart=region.image_start,
+ flags=region.flags
+ )
- Individual segments within an image can be loaded independently of the image itself.
+def image_from_api(image: sccore.BNSharedCacheImage) -> CacheImage:
+ region_starts = []
+ for i in range(image.regionStartCount):
+ region_starts.append(image.regionStarts[i])
+ return CacheImage(
+ name=image.name,
+ header_address=image.headerAddress,
+ region_starts=region_starts
+ )
- Only once all regions of an image are loaded will the header processor refuse to run on that region.
- :return:
- """
- count = ctypes.c_ulonglong()
- value = sccore.BNDSCViewGetLoadedRegions(self.handle, count)
- if value is None:
- return []
+def image_to_api(image: CacheImage) -> sccore.BNSharedCacheImage:
+ region_start_array = (ctypes.c_ulonglong * len(image.region_starts))()
+ for i, region_start in enumerate(image.region_starts):
+ region_start_array[i] = region_start
+ core_region_starts = sccore.BNSharedCacheAllocRegionList(region_start_array, len(region_start_array))
+ return sccore.BNSharedCacheImage(
+ _name=BNAllocString(image.name),
+ headerAddress=image.header_address,
+ regionStartCount=len(region_start_array),
+ regionStarts=core_region_starts
+ )
- result = []
- for i in range(count.value):
- mapping = DSCMemoryMapping(
- value[i].name,
- value[i].vmAddress,
- value[i].size,
- )
- result.append(mapping)
- sccore.BNDSCViewFreeLoadedRegions(value, count)
- return result
+def symbol_from_api(symbol: sccore.BNSharedCacheSymbol) -> CacheSymbol:
+ return CacheSymbol(
+ symbol_type=symbol.symbolType,
+ address=symbol.address,
+ name=symbol.name
+ )
- def load_all_symbols_and_wait(self) -> list[DSCSymbol]:
- """
- Load all symbols in the shared cache. This will block on the current thread waiting for processing to finish.
+def symbol_to_api(symbol: CacheSymbol) -> sccore.BNSharedCacheSymbol:
+ return sccore.BNSharedCacheSymbol(
+ symbolType=symbol.symbol_type,
+ address=symbol.address,
+ _name=BNAllocString(symbol.name)
+ )
- While all functions in this API are synchronous, this function can be particularly slow due to the large number
- of symbols in the shared cache. "and_wait" is appended to the function name to indicate that this function
- will block until processing is complete, and for performant applications, you should consider calling this
- function in a separate thread and waiting on its return. An example of this is provided in the shared cache
- triage view.
+class SharedCacheController:
+ def __init__(self, view: BinaryView):
+ """
+ Retrieve the shared cache controller for a given view.
+ Call `is_valid` to check if the controller is valid.
+ """
+ self.handle = sccore.BNGetSharedCacheController(view.handle)
- This may take several seconds if this is the first time this function is called. Subsequent calls will be faster.
+ def __del__(self):
+ if self.handle is not None:
+ sccore.BNFreeSharedCacheControllerReference(self.handle)
- In UI-based API usage, it is likely that the triage view will have already performed this operation, and calls
- to this function will be much faster.
+ def __str__(self):
+ return repr(self)
- :return: A list of all symbols in the shared cache
- """
- count = ctypes.c_ulonglong()
- value = sccore.BNDSCViewLoadAllSymbolsAndWait(self.handle, count)
- if value is None:
- return []
- result = []
- for i in range(count.value):
- sym = DSCSymbol(
- value[i].name,
- value[i].image,
- value[i].address
- )
- result.append(sym)
+ def __repr__(self):
+ return f"<SharedCacheController: {len(self.images)} images, {len(self.regions)} regions>"
- sccore.BNDSCViewFreeSymbols(value, count)
- return result
+ def is_valid(self) -> bool:
+ return self.handle is not None
- @property
- def image_names(self) -> list[str]:
- """
- Get all image names in the shared cache
- :return:
- """
- count = ctypes.c_ulonglong()
- value = sccore.BNDSCViewGetInstallNames(self.handle, count)
- if value is None:
- return []
+ def apply_region(self, view: BinaryView, region: CacheRegion) -> bool:
+ api_region: sccore.BNSharedCacheRegion = region_to_api(region)
+ result = sccore.BNSharedCacheControllerApplyRegion(self.handle, view.handle, api_region)
+ sccore.BNSharedCacheFreeRegion(api_region)
+ return result
- result = []
- for i in range(count.value):
- result.append(value[i].decode('utf-8'))
+ def apply_image(self, view: BinaryView, image: CacheImage) -> bool:
+ api_image: sccore.BNSharedCacheImage = image_to_api(image)
+ result = sccore.BNSharedCacheControllerApplyImage(self.handle, view.handle, api_image)
+ sccore.BNSharedCacheFreeImage(api_image)
+ return result
- BNFreeStringList(value, count)
- return result
+ def is_region_loaded(self, region: CacheRegion) -> bool:
+ api_region: sccore.BNSharedCacheRegion = region_to_api(region)
+ result = sccore.BNSharedCacheControllerIsRegionLoaded(self.handle, api_region)
+ sccore.BNSharedCacheFreeRegion(api_region)
+ return result
- @property
- def state(self) -> DSCViewState:
- """
- Get the current image state of the shared cache view. Useful for checking if images have been loaded yet or not.
- :return:
- """
- return DSCViewState(sccore.BNDSCViewGetState(self.handle))
+ def is_image_loaded(self, image: CacheImage) -> bool:
+ api_image: sccore.BNSharedCacheImage = image_to_api(image)
+ result = sccore.BNSharedCacheControllerIsImageLoaded(self.handle, api_image)
+ sccore.BNSharedCacheFreeImage(api_image)
+ return result
- def get_name_for_address(self, address) -> str:
- """
- Get the "name" for the provided address. Specifically, the name of the memory region this address lies in.
+ def get_region_at(self, address: int) -> Optional[CacheRegion]:
+ api_region = sccore.BNSharedCacheRegion()
+ if not sccore.BNSharedCacheControllerGetRegionAt(self.handle, address, api_region):
+ return None
+ region = region_from_api(api_region)
+ sccore.BNSharedCacheFreeRegion(api_region)
+ return region
- If this lies within an image segment, this will be in the format image_name + "::" + segment_name.
+ def get_region_containing(self, address: int) -> Optional[CacheRegion]:
+ api_region = sccore.BNSharedCacheRegion()
+ if not sccore.BNSharedCacheControllerGetRegionContaining(self.handle, address, api_region):
+ return None
+ region = region_from_api(api_region)
+ sccore.BNSharedCacheFreeRegion(api_region)
+ return region
- It may also be the name of a branch pool or other non-image region.
+ def get_image_at(self, address: int) -> Optional[CacheImage]:
+ api_image = sccore.BNSharedCacheImage()
+ if not sccore.BNSharedCacheControllerGetImageAt(self.handle, address, api_image):
+ return None
+ image = image_from_api(api_image)
+ sccore.BNSharedCacheFreeImage(api_image)
+ return image
- This is the API call utilized on the first dynamic entry in the right-click context menu.
+ def get_image_containing(self, address: int) -> Optional[CacheImage]:
+ api_image = sccore.BNSharedCacheImage()
+ if not sccore.BNSharedCacheControllerGetImageContaining(self.handle, address, api_image):
+ return None
+ image = image_from_api(api_image)
+ sccore.BNSharedCacheFreeImage(api_image)
+ return image
- :param address: address to check
- :return:
- """
- name = sccore.BNDSCViewGetNameForAddress(self.handle, address)
- if name is None:
- return ""
- result = name
- return result
+ def get_image_with_name(self, name: str) -> Optional[CacheImage]:
+ api_image = sccore.BNSharedCacheImage()
+ if not sccore.BNSharedCacheControllerGetImageWithName(self.handle, name, api_image):
+ return None
+ image = image_from_api(api_image)
+ sccore.BNSharedCacheFreeImage(api_image)
+ return image
- def get_image_name_for_address(self, address) -> str:
- """
- Return the install name for the image containing the provided address.
+ def get_image_dependencies(self, image: CacheImage) -> [str]:
+ """
+ Returns a list of image names that this image depends on.
+ """
+ count = ctypes.c_ulonglong()
+ api_image: sccore.BNSharedCacheImage = image_to_api(image)
+ value = sccore.BNSharedCacheControllerGetImageDependencies(self.handle, api_image, count)
+ sccore.BNSharedCacheFreeImage(api_image)
+ if value is None:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(value[i].decode("utf-8"))
+ BNFreeStringList(value, count)
+ return result
- If the address is not within an image, this will return an empty string.
+ @property
+ def regions(self) -> [CacheRegion]:
+ count = ctypes.c_ulonglong()
+ value = sccore.BNSharedCacheControllerGetRegions(self.handle, count)
+ if value is None:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(region_from_api(value[i]))
+ sccore.BNSharedCacheFreeRegionList(value, count)
+ return result
- This is the API call used in the second dynamic entry in the right-click context menu.
+ @property
+ def loaded_regions(self) -> [CacheRegion]:
+ """
+ Get a list of regions that are currently loaded in the view.
+ """
+ count = ctypes.c_ulonglong()
+ value = sccore.BNSharedCacheControllerGetLoadedRegions(self.handle, count)
+ if value is None:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(region_from_api(value[i]))
+ sccore.BNSharedCacheFreeRegionList(value, count)
+ return result
- :param address: address to check
- :return:
- """
- name = sccore.BNDSCViewGetImageNameForAddress(self.handle, address)
- if name is None:
- return ""
- result = name
- return result
+ @property
+ def images(self) -> [CacheImage]:
+ count = ctypes.c_ulonglong()
+ value = sccore.BNSharedCacheControllerGetImages(self.handle, count)
+ if value is None:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(image_from_api(value[i]))
+ sccore.BNSharedCacheFreeImageList(value, count)
+ return result
- def find_symbol_at_addr_and_apply_to_addr(self, symbol_address, target_address, trigger_reanalysis) -> None:
- """
- This is primarily a function utilized for automated backwards symbol propagation for stubs in the workflow, however
- it is passed through here as well in the event you need to use it to do something similar, or want to create
- your own version of the workflow.
+ @property
+ def loaded_images(self) -> [CacheImage]:
+ """
+ Get a list of images that are currently loaded in the view.
+ """
+ count = ctypes.c_ulonglong()
+ value = sccore.BNSharedCacheControllerGetLoadedImages(self.handle, count)
+ if value is None:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(image_from_api(value[i]))
+ sccore.BNSharedCacheFreeImageList(value, count)
+ return result
- This is currently a blocking function.
+ @property
+ def symbols(self) -> [CacheSymbol]:
+ count = ctypes.c_ulonglong()
+ value = sccore.BNSharedCacheControllerGetSymbols(self.handle, count)
+ if value is None:
+ return []
+ result = []
+ for i in range(count.value):
+ result.append(symbol_from_api(value[i]))
+ sccore.BNSharedCacheFreeSymbolList(value, count)
+ return result
- This will check the cache for a symbol located at symbol_address, and apply it to target_address, appending a
- `j_` to the front of the symbol name copy at `target_address`.
- It will additionally backwards-propagate type information that was specifically applied via TypeLibrary to the stub.
+def _get_shared_cache(instance: binaryninja.PythonScriptingInstance):
+ if instance.interpreter.active_view is None:
+ return None
+ controller = SharedCacheController(instance.interpreter.active_view)
+ if not controller.is_valid():
+ return None
+ return controller
- This includes calling conventions and can be seen in stubs pointing to objc_release_x[register] functions.
- This check will not run if:
- - The symbol address and target address are the same
- - The target address has already been given a name by this function
+binaryninja.PythonScriptingProvider.register_magic_variable(
+ "dsc",
+ _get_shared_cache
+)
- :param symbol_address: Symbol address to check
- :param target_address: Target address to apply symbol name and type to
- :param trigger_reanalysis: Whether to reanalyze the function at target_address if the function already existed.
- :return: None
- """
- sccore.BNDSCFindSymbolAtAddressAndApplyToAddress(self.handle, symbol_address, target_address, trigger_reanalysis)
+binaryninja.PythonScriptingProvider.register_magic_variable(
+ "shared_cache",
+ _get_shared_cache
+)
diff --git a/view/sharedcache/api/python/sharedcache_enums.py b/view/sharedcache/api/python/sharedcache_enums.py
index ea86b5c6..9a98eba4 100644
--- a/view/sharedcache/api/python/sharedcache_enums.py
+++ b/view/sharedcache/api/python/sharedcache_enums.py
@@ -1,20 +1,38 @@
import enum
-class BackingCacheType(enum.IntEnum):
- BackingCacheTypePrimary = 0
- BackingCacheTypeSecondary = 1
- BackingCacheTypeSymbols = 2
+class SegmentFlag(enum.IntEnum):
+ SegmentExecutable = 1
+ SegmentWritable = 2
+ SegmentReadable = 4
+ SegmentContainsData = 8
+ SegmentContainsCode = 16
+ SegmentDenyWrite = 32
+ SegmentDenyExecute = 64
-class DSCViewLoadProgress(enum.IntEnum):
- LoadProgressNotStarted = 0
- LoadProgressLoadingCaches = 1
- LoadProgressLoadingImages = 2
- LoadProgressFinished = 3
+class SharedCacheEntryType(enum.IntEnum):
+ SharedCacheEntryTypePrimary = 0
+ SharedCacheEntryTypeSecondary = 1
+ SharedCacheEntryTypeSymbols = 2
+ SharedCacheEntryTypeDyldData = 3
+ SharedCacheEntryTypeStub = 4
-class DSCViewState(enum.IntEnum):
- Unloaded = 0
- Loaded = 1
- LoadedWithImages = 2
+class SharedCacheRegionType(enum.IntEnum):
+ SharedCacheRegionTypeImage = 0
+ SharedCacheRegionTypeStubIsland = 1
+ SharedCacheRegionTypeDyldData = 2
+ SharedCacheRegionTypeNonImage = 3
+
+
+class SymbolType(enum.IntEnum):
+ FunctionSymbol = 0
+ ImportAddressSymbol = 1
+ ImportedFunctionSymbol = 2
+ DataSymbol = 3
+ ImportedDataSymbol = 4
+ ExternalSymbol = 5
+ LibraryFunctionSymbol = 6
+ SymbolicFunctionSymbol = 7
+ LocalLabelSymbol = 8
diff --git a/view/sharedcache/api/sharedcache.cpp b/view/sharedcache/api/sharedcache.cpp
index d9838057..6d552f0d 100644
--- a/view/sharedcache/api/sharedcache.cpp
+++ b/view/sharedcache/api/sharedcache.cpp
@@ -4,231 +4,324 @@
#include "sharedcacheapi.h"
-namespace SharedCacheAPI {
+using namespace BinaryNinja;
+using namespace SharedCacheAPI;
- SharedCache::SharedCache(Ref<BinaryView> view) {
- m_object = BNGetSharedCache(view->GetObject());
- }
+BNSharedCacheImage ImageToApi(CacheImage image)
+{
+ BNSharedCacheImage apiImage;
+ apiImage.name = BNAllocString(image.name.c_str());
+ apiImage.headerAddress = image.headerAddress;
+ apiImage.regionStartCount = image.regionStarts.size();
+ // TODO: If we alloc then core cannot delete
+ uint64_t *regionStarts = new uint64_t[image.regionStarts.size()];
+ for (size_t i = 0; i < image.regionStarts.size(); i++)
+ regionStarts[i] = image.regionStarts[i];
+ apiImage.regionStarts = regionStarts;
+ return apiImage;
+}
- BNDSCViewLoadProgress SharedCache::GetLoadProgress(Ref<BinaryView> view)
- {
- return BNDSCViewGetLoadProgress(view->GetFile()->GetSessionId());
- }
+CacheImage ImageFromApi(BNSharedCacheImage image)
+{
+ CacheImage apiImage;
+ apiImage.name = image.name;
+ apiImage.headerAddress = image.headerAddress;
+ apiImage.regionStarts.reserve(image.regionStartCount);
+ for (size_t i = 0; i < image.regionStartCount; i++)
+ apiImage.regionStarts.push_back(image.regionStarts[i]);
+ return apiImage;
+}
- uint64_t SharedCache::FastGetBackingCacheCount(Ref<BinaryView> view)
- {
- return BNDSCViewFastGetBackingCacheCount(view->GetObject());
- }
+BNSharedCacheRegion RegionToApi(const CacheRegion &region)
+{
+ BNSharedCacheRegion apiRegion;
+ apiRegion.vmAddress = region.start;
+ apiRegion.name = BNAllocString(region.name.c_str());
+ apiRegion.size = region.size;
+ apiRegion.flags = region.flags;
+ apiRegion.regionType = region.type;
+ // If not associated with image this will be zeroed.
+ apiRegion.imageStart = region.imageStart.value_or(0);
+ return apiRegion;
+}
- bool SharedCache::LoadImageWithInstallName(std::string installName, bool skipObjC)
- {
- char* str = BNAllocString(installName.c_str());
- return BNDSCViewLoadImageWithInstallName(m_object, str, skipObjC);
- }
+CacheRegion RegionFromApi(BNSharedCacheRegion apiRegion)
+{
+ CacheRegion region;
+ region.start = apiRegion.vmAddress;
+ region.name = apiRegion.name;
+ region.size = apiRegion.size;
+ region.flags = apiRegion.flags;
+ region.type = apiRegion.regionType;
+ return region;
+}
- bool SharedCache::LoadSectionAtAddress(uint64_t addr)
- {
- return BNDSCViewLoadSectionAtAddress(m_object, addr);
- }
+BNSharedCacheMappingInfo MappingToApi(const CacheMappingInfo &mapping)
+{
+ BNSharedCacheMappingInfo apiMapping;
+ apiMapping.vmAddress = mapping.vmAddress;
+ apiMapping.size = mapping.size;
+ apiMapping.fileOffset = mapping.fileOffset;
+ return apiMapping;
+}
- bool SharedCache::LoadImageContainingAddress(uint64_t addr, bool skipObjC)
- {
- return BNDSCViewLoadImageContainingAddress(m_object, addr, skipObjC);
- }
+CacheMappingInfo MappingFromApi(BNSharedCacheMappingInfo apiMapping)
+{
+ CacheMappingInfo mapping;
+ mapping.vmAddress = apiMapping.vmAddress;
+ mapping.size = apiMapping.size;
+ mapping.fileOffset = apiMapping.fileOffset;
+ return mapping;
+}
- std::vector<std::string> SharedCache::GetAvailableImages()
- {
- size_t count;
- char** value = BNDSCViewGetInstallNames(m_object, &count);
- if (value == nullptr)
- {
- return {};
- }
+BNSharedCacheEntry EntryToApi(const CacheEntry &entry)
+{
+ BNSharedCacheEntry apiEntry;
+ apiEntry.path = BNAllocString(entry.path.c_str());
+ apiEntry.entryType = entry.entryType;
+ const auto &mappings = entry.mappings;
+ apiEntry.mappingCount = mappings.size();
+ // TODO: If we alloc then the core cannot delete.
+ apiEntry.mappings = new BNSharedCacheMappingInfo[mappings.size()];
+ for (size_t i = 0; i < mappings.size(); i++)
+ apiEntry.mappings[i] = MappingToApi(mappings[i]);
+ return apiEntry;
+}
- std::vector<std::string> result;
- for (size_t i = 0; i < count; i++)
- {
- result.push_back(value[i]);
- }
+CacheEntry EntryFromApi(BNSharedCacheEntry apiEntry)
+{
+ CacheEntry entry;
+ entry.path = apiEntry.path;
+ entry.entryType = apiEntry.entryType;
+ entry.mappings.reserve(apiEntry.mappingCount);
+ for (size_t i = 0; i < apiEntry.mappingCount; i++)
+ entry.mappings.push_back(MappingFromApi(apiEntry.mappings[i]));
+ return entry;
+}
- BNFreeStringList(value, count);
- return result;
- }
+CacheSymbol SymbolFromApi(BNSharedCacheSymbol apiSymbol)
+{
+ CacheSymbol symbol;
+ symbol.name = apiSymbol.name;
+ symbol.address = apiSymbol.address;
+ symbol.type = apiSymbol.symbolType;
+ return symbol;
+}
- void SharedCache::ProcessObjCSectionsForImageWithInstallName(std::string installName)
+std::string SharedCacheAPI::GetRegionTypeAsString(const BNSharedCacheRegionType &type)
+{
+ switch (type)
{
- char* str = BNAllocString(installName.c_str());
- BNDSCViewProcessObjCSectionsForImageWithInstallName(m_object, str, true);
+ case SharedCacheRegionTypeImage:
+ return "Image";
+ case SharedCacheRegionTypeStubIsland:
+ return "StubIsland";
+ case SharedCacheRegionTypeDyldData:
+ return "DyldData";
+ case SharedCacheRegionTypeNonImage:
+ return "NonImage";
+ default:
+ return "Unknown";
}
+}
- void SharedCache::ProcessAllObjCSections()
- {
- BNDSCViewProcessAllObjCSections(m_object);
- }
+SharedCacheController::SharedCacheController(BNSharedCacheController *controller)
+{
+ m_object = controller;
+}
- std::vector<DSCMemoryRegion> SharedCache::GetLoadedMemoryRegions()
- {
- size_t count;
- BNDSCMappedMemoryRegion* value = BNDSCViewGetLoadedRegions(m_object, &count);
- if (value == nullptr)
- {
- return {};
- }
+DSCRef<SharedCacheController> SharedCacheController::GetController(BinaryView &view)
+{
+ BNSharedCacheController *controller = BNGetSharedCacheController(view.GetObject());
+ if (controller == nullptr)
+ return nullptr;
+ return new SharedCacheController(controller);
+}
- std::vector<DSCMemoryRegion> result;
- for (size_t i = 0; i < count; i++)
- {
- DSCMemoryRegion region;
- region.vmAddress = value[i].vmAddress;
- region.size = value[i].size;
- region.prettyName = value[i].name;
- result.push_back(region);
- }
+bool SharedCacheController::ApplyRegion(BinaryView &view, const CacheRegion &region)
+{
+ auto apiRegion = RegionToApi(region);
+ bool result = BNSharedCacheControllerApplyRegion(m_object, view.GetObject(), &apiRegion);
+ BNSharedCacheFreeRegion(apiRegion);
+ return result;
+}
- BNDSCViewFreeLoadedRegions(value, count);
- return result;
- }
- std::vector<BackingCache> SharedCache::GetBackingCaches()
- {
- size_t count;
- BNDSCBackingCache* value = BNDSCViewGetBackingCaches(m_object, &count);
- if (value == nullptr)
- {
- return {};
- }
+bool SharedCacheController::ApplyImage(BinaryView &view, const CacheImage &image)
+{
+ auto apiImage = ImageToApi(image);
+ bool result = BNSharedCacheControllerApplyImage(m_object, view.GetObject(), &apiImage);
+ BNSharedCacheFreeImage(apiImage);
+ return result;
+}
- std::vector<BackingCache> result;
- for (size_t i = 0; i < count; i++)
- {
- BackingCache cache;
- cache.path = value[i].path;
- cache.cacheType = value[i].cacheType;
- for (size_t j = 0; j < value[i].mappingCount; j++)
- {
- BackingCacheMapping mapping;
- mapping.vmAddress = value[i].mappings[j].vmAddress;
- mapping.size = value[i].mappings[j].size;
- mapping.fileOffset = value[i].mappings[j].fileOffset;
- cache.mappings.push_back(mapping);
- }
- result.push_back(cache);
- }
+bool SharedCacheController::IsRegionLoaded(const CacheRegion &region) const
+{
+ auto apiRegion = RegionToApi(region);
+ bool result = BNSharedCacheControllerIsRegionLoaded(m_object, &apiRegion);
+ BNSharedCacheFreeRegion(apiRegion);
+ return result;
+}
- BNDSCViewFreeBackingCaches(value, count);
- return result;
- }
+bool SharedCacheController::IsImageLoaded(const CacheImage &image) const
+{
+ auto apiImage = ImageToApi(image);
+ bool result = BNSharedCacheControllerIsImageLoaded(m_object, &apiImage);
+ BNSharedCacheFreeImage(apiImage);
+ return result;
+}
- std::vector<DSCImage> SharedCache::GetImages()
- {
- size_t count;
- BNDSCImage* value = BNDSCViewGetAllImages(m_object, &count);
- if (value == nullptr)
- {
- return {};
- }
+std::optional<CacheRegion> SharedCacheController::GetRegionAt(uint64_t address) const
+{
+ BNSharedCacheRegion apiRegion;
+ if (!BNSharedCacheControllerGetRegionAt(m_object, address, &apiRegion))
+ return std::nullopt;
+ CacheRegion region = RegionFromApi(apiRegion);
+ BNSharedCacheFreeRegion(apiRegion);
+ return region;
+}
- std::vector<DSCImage> result;
- for (size_t i = 0; i < count; i++)
- {
- DSCImage img;
- img.name = value[i].name;
- img.headerAddress = value[i].headerAddress;
- for (size_t j = 0; j < value[i].mappingCount; j++)
- {
- DSCImageMemoryMapping mapping;
- mapping.filePath = value[i].mappings[j].filePath;
- mapping.name = value[i].mappings[j].name;
- mapping.vmAddress = value[i].mappings[j].vmAddress;
- mapping.rawViewOffset = value[i].mappings[j].rawViewOffset;
- mapping.size = value[i].mappings[j].size;
- mapping.loaded = value[i].mappings[j].loaded;
- img.mappings.push_back(mapping);
- }
- result.push_back(img);
- }
+std::optional<CacheRegion> SharedCacheController::GetRegionContaining(uint64_t address) const
+{
+ BNSharedCacheRegion apiRegion;
+ if (!BNSharedCacheControllerGetRegionContaining(m_object, address, &apiRegion))
+ return std::nullopt;
+ CacheRegion region = RegionFromApi(apiRegion);
+ BNSharedCacheFreeRegion(apiRegion);
+ return region;
+}
- BNDSCViewFreeAllImages(value, count);
- return result;
- }
+std::optional<CacheImage> SharedCacheController::GetImageAt(uint64_t address) const
+{
+ BNSharedCacheImage apiImage;
+ if (!BNSharedCacheControllerGetImageAt(m_object, address, &apiImage))
+ return std::nullopt;
+ CacheImage image = ImageFromApi(apiImage);
+ BNSharedCacheFreeImage(apiImage);
+ return image;
+}
- std::vector<DSCSymbol> SharedCache::LoadAllSymbolsAndWait()
- {
- size_t count;
- BNDSCSymbolRep* value = BNDSCViewLoadAllSymbolsAndWait(m_object, &count);
- if (value == nullptr)
- {
- return {};
- }
+std::optional<CacheImage> SharedCacheController::GetImageContaining(uint64_t address) const
+{
+ BNSharedCacheImage apiImage;
+ if (!BNSharedCacheControllerGetImageContaining(m_object, address, &apiImage))
+ return std::nullopt;
+ CacheImage image = ImageFromApi(apiImage);
+ BNSharedCacheFreeImage(apiImage);
+ return image;
+}
- std::vector<DSCSymbol> result;
- result.reserve(count);
- for (size_t i = 0; i < count; i++)
- {
- DSCSymbol sym;
- sym.address = value[i].address;
- sym.name = StringRef(BNDuplicateStringRef(value[i].name));
- sym.image = value[i].image;
- result.push_back(sym);
- }
+std::optional<CacheImage> SharedCacheController::GetImageWithName(const std::string &name) const
+{
+ BNSharedCacheImage apiImage;
+ if (!BNSharedCacheControllerGetImageWithName(m_object, name.c_str(), &apiImage))
+ return std::nullopt;
+ CacheImage image = ImageFromApi(apiImage);
+ BNSharedCacheFreeImage(apiImage);
+ return image;
+}
- BNDSCViewFreeSymbols(value, count);
- return result;
- }
+std::vector<std::string> SharedCacheController::GetImageDependencies(const CacheImage &image) const
+{
+ size_t count;
+ BNSharedCacheImage apiImage = ImageToApi(image);
+ char **dependencies = BNSharedCacheControllerGetImageDependencies(m_object, &apiImage, &count);
+ BNSharedCacheFreeImage(apiImage);
+ std::vector<std::string> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(dependencies[i]);
+ BNFreeStringList(dependencies, count);
+ return result;
+}
- std::string SharedCache::GetNameForAddress(uint64_t address)
- {
- char* name = BNDSCViewGetNameForAddress(m_object, address);
- if (name == nullptr)
- return {};
- std::string result = name;
- BNFreeString(name);
- return result;
- }
+std::optional<CacheSymbol> SharedCacheController::GetSymbolAt(uint64_t address) const
+{
+ BNSharedCacheSymbol apiSymbol;
+ if (!BNSharedCacheControllerGetSymbolAt(m_object, address, &apiSymbol))
+ return std::nullopt;
+ CacheSymbol symbol = SymbolFromApi(apiSymbol);
+ BNSharedCacheFreeSymbol(apiSymbol);
+ return symbol;
+}
- std::string SharedCache::GetImageNameForAddress(uint64_t address)
- {
- char* name = BNDSCViewGetImageNameForAddress(m_object, address);
- if (name == nullptr)
- return {};
- std::string result = name;
- BNFreeString(name);
- return result;
- }
+std::optional<CacheSymbol> SharedCacheController::GetSymbolWithName(const std::string &name) const
+{
+ BNSharedCacheSymbol apiSymbol;
+ if (!BNSharedCacheControllerGetSymbolWithName(m_object, name.c_str(), &apiSymbol))
+ return std::nullopt;
+ CacheSymbol symbol = SymbolFromApi(apiSymbol);
+ BNSharedCacheFreeSymbol(apiSymbol);
+ return symbol;
+}
- std::optional<SharedCacheMachOHeader> SharedCache::GetMachOHeaderForImage(std::string name)
- {
- char* str = BNAllocString(name.c_str());
- char* outputStr = BNDSCViewGetImageHeaderForName(m_object, str);
- if (outputStr == nullptr)
- return {};
- std::string output = outputStr;
- BNFreeString(outputStr);
- if (output.empty())
- return {};
+std::vector<CacheEntry> SharedCacheController::GetEntries() const
+{
+ size_t count;
+ BNSharedCacheEntry *entries = BNSharedCacheControllerGetEntries(m_object, &count);
+ std::vector<CacheEntry> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(EntryFromApi(entries[i]));
+ BNSharedCacheFreeEntryList(entries, count);
+ return result;
+}
- return SharedCacheMachOHeader::LoadFromString(output);
- }
+std::vector<CacheRegion> SharedCacheController::GetLoadedRegions() const
+{
+ size_t count;
+ BNSharedCacheRegion *regions = BNSharedCacheControllerGetLoadedRegions(m_object, &count);
+ std::vector<CacheRegion> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(RegionFromApi(regions[i]));
+ BNSharedCacheFreeRegionList(regions, count);
+ return result;
+}
- std::optional<SharedCacheMachOHeader> SharedCache::GetMachOHeaderForAddress(uint64_t address)
- {
- char* outputStr = BNDSCViewGetImageHeaderForAddress(m_object, address);
- if (outputStr == nullptr)
- return {};
- std::string output = outputStr;
- BNFreeString(outputStr);
- if (output.empty())
- return {};
- return SharedCacheMachOHeader::LoadFromString(output);
- }
+std::vector<CacheRegion> SharedCacheController::GetRegions() const
+{
+ size_t count;
+ BNSharedCacheRegion *regions = BNSharedCacheControllerGetRegions(m_object, &count);
+ std::vector<CacheRegion> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(RegionFromApi(regions[i]));
+ BNSharedCacheFreeRegionList(regions, count);
+ return result;
+}
- BNDSCViewState SharedCache::GetState()
- {
- return BNDSCViewGetState(m_object);
- }
+std::vector<CacheImage> SharedCacheController::GetImages() const
+{
+ size_t count;
+ BNSharedCacheImage *images = BNSharedCacheControllerGetImages(m_object, &count);
+ std::vector<CacheImage> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(ImageFromApi(images[i]));
+ BNSharedCacheFreeImageList(images, count);
+ return result;
+}
- void SharedCache::FindSymbolAtAddrAndApplyToAddr(uint64_t symbolLocation, uint64_t targetLocation, bool triggerReanalysis) const
- {
- BNDSCFindSymbolAtAddressAndApplyToAddress(m_object, symbolLocation, targetLocation, triggerReanalysis);
- }
+std::vector<CacheImage> SharedCacheController::GetLoadedImages() const
+{
+ size_t count;
+ BNSharedCacheImage *images = BNSharedCacheControllerGetLoadedImages(m_object, &count);
+ std::vector<CacheImage> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(ImageFromApi(images[i]));
+ BNSharedCacheFreeImageList(images, count);
+ return result;
+}
-} // namespace SharedCacheAPI
+std::vector<CacheSymbol> SharedCacheController::GetSymbols() const
+{
+ size_t count;
+ BNSharedCacheSymbol *symbols = BNSharedCacheControllerGetSymbols(m_object, &count);
+ std::vector<CacheSymbol> result;
+ result.reserve(count);
+ for (size_t i = 0; i < count; i++)
+ result.emplace_back(SymbolFromApi(symbols[i]));
+ BNSharedCacheFreeSymbolList(symbols, count);
+ return result;
+}
diff --git a/view/sharedcache/api/sharedcacheapi.h b/view/sharedcache/api/sharedcacheapi.h
index 5c50e283..e12582f2 100644
--- a/view/sharedcache/api/sharedcacheapi.h
+++ b/view/sharedcache/api/sharedcacheapi.h
@@ -1,285 +1,327 @@
#pragma once
#include <binaryninjaapi.h>
-#include "../core/MetadataSerializable.hpp"
-#include "view/macho/machoview.h"
#include "sharedcachecore.h"
-namespace SharedCacheAPI {
- template<class T>
- class SCRefCountObject {
- void AddRefInternal() { m_refs.fetch_add(1); }
+template<class T>
+class DSCRefCountObject {
+ void AddRefInternal() { m_refs.fetch_add(1); }
- void ReleaseInternal() {
- if (m_refs.fetch_sub(1) == 1)
- delete this;
- }
+ void ReleaseInternal() {
+ if (m_refs.fetch_sub(1) == 1)
+ delete this;
+ }
- public:
- std::atomic<int> m_refs;
- T *m_object;
+public:
+ std::atomic<int> m_refs;
+ T *m_object;
- SCRefCountObject() : m_refs(0), m_object(nullptr) {}
+ DSCRefCountObject() : m_refs(0), m_object(nullptr) {}
- virtual ~SCRefCountObject() {}
+ virtual ~DSCRefCountObject() = default;
- T *GetObject() const { return m_object; }
+ T *GetObject() const { return m_object; }
- static T *GetObject(SCRefCountObject *obj) {
- if (!obj)
- return nullptr;
- return obj->GetObject();
- }
+ static T *GetObject(DSCRefCountObject *obj) {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
- void AddRef() { AddRefInternal(); }
+ void AddRef() { AddRefInternal(); }
- void Release() { ReleaseInternal(); }
+ void Release() { ReleaseInternal(); }
- void AddRefForRegistration() { AddRefInternal(); }
- };
+ void AddRefForRegistration() { AddRefInternal(); }
+};
- template<class T, T *(*AddObjectReference)(T *), void (*FreeObjectReference)(T *)>
- class SCCoreRefCountObject {
- void AddRefInternal() { m_refs.fetch_add(1); }
+template<class T, T *(*AddObjectReference)(T *), void (*FreeObjectReference)(T *)>
+class DSCCoreRefCountObject {
+ void AddRefInternal() { m_refs.fetch_add(1); }
- void ReleaseInternal() {
- if (m_refs.fetch_sub(1) == 1) {
- if (!m_registeredRef)
- delete this;
- }
+ void ReleaseInternal() {
+ if (m_refs.fetch_sub(1) == 1) {
+ if (!m_registeredRef)
+ delete this;
}
+ }
- public:
- std::atomic<int> m_refs;
- bool m_registeredRef = false;
- T *m_object;
+public:
+ std::atomic<int> m_refs;
+ bool m_registeredRef = false;
+ T *m_object;
+
+ DSCCoreRefCountObject() : m_refs(0), m_object(nullptr) {}
+
+ virtual ~DSCCoreRefCountObject() = default;
+
+ T *GetObject() const { return m_object; }
+
+ static T *GetObject(DSCCoreRefCountObject *obj) {
+ if (!obj)
+ return nullptr;
+ return obj->GetObject();
+ }
+
+ void AddRef() {
+ if (m_object && (m_refs != 0))
+ AddObjectReference(m_object);
+ AddRefInternal();
+ }
+
+ void Release() {
+ if (m_object)
+ FreeObjectReference(m_object);
+ ReleaseInternal();
+ }
- SCCoreRefCountObject() : m_refs(0), m_object(nullptr) {}
+ void AddRefForRegistration() { m_registeredRef = true; }
- virtual ~SCCoreRefCountObject() {}
+ void ReleaseForRegistration() {
+ m_object = nullptr;
+ m_registeredRef = false;
+ if (m_refs == 0)
+ delete this;
+ }
+};
- T *GetObject() const { return m_object; }
+template <class T>
+class DSCRef
+{
+ T* m_obj;
+#ifdef BN_REF_COUNT_DEBUG
+ void* m_assignmentTrace = nullptr;
+#endif
- static T *GetObject(SCCoreRefCountObject *obj) {
- if (!obj)
- return nullptr;
- return obj->GetObject();
+public:
+ DSCRef() : m_obj(NULL) {}
+
+ DSCRef(T* obj) : m_obj(obj)
+ {
+ if (m_obj)
+ {
+ m_obj->AddRef();
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
}
+ }
- void AddRef() {
- if (m_object && (m_refs != 0))
- AddObjectReference(m_object);
- AddRefInternal();
+ DSCRef(const DSCRef<T>& obj) : m_obj(obj.m_obj)
+ {
+ if (m_obj)
+ {
+ m_obj->AddRef();
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
}
+ }
+
+ DSCRef(DSCRef<T>&& other) : m_obj(other.m_obj)
+ {
+ other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
+ }
- void Release() {
- if (m_object)
- FreeObjectReference(m_object);
- ReleaseInternal();
+ ~DSCRef()
+ {
+ if (m_obj)
+ {
+ m_obj->Release();
+#ifdef BN_REF_COUNT_DEBUG
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+#endif
}
+ }
- void AddRefForRegistration() { m_registeredRef = true; }
+ DSCRef<T>& operator=(const BinaryNinja::Ref<T>& obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ if (m_obj)
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+ if (obj.m_obj)
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ T* oldObj = m_obj;
+ m_obj = obj.m_obj;
+ if (m_obj)
+ m_obj->AddRef();
+ if (oldObj)
+ oldObj->Release();
+ return *this;
+ }
- void ReleaseForRegistration() {
- m_object = nullptr;
- m_registeredRef = false;
- if (m_refs == 0)
- delete this;
+ DSCRef<T>& operator=(DSCRef<T>&& other)
+ {
+ if (m_obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+#endif
+ m_obj->Release();
}
- };
+ m_obj = other.m_obj;
+ other.m_obj = 0;
+#ifdef BN_REF_COUNT_DEBUG
+ m_assignmentTrace = other.m_assignmentTrace;
+#endif
+ return *this;
+ }
- struct DSCMemoryRegion {
- uint64_t vmAddress;
- uint64_t size;
- std::string prettyName;
- };
+ DSCRef<T>& operator=(T* obj)
+ {
+#ifdef BN_REF_COUNT_DEBUG
+ if (m_obj)
+ BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
+ if (obj)
+ m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
+#endif
+ T* oldObj = m_obj;
+ m_obj = obj;
+ if (m_obj)
+ m_obj->AddRef();
+ if (oldObj)
+ oldObj->Release();
+ return *this;
+ }
- struct BackingCacheMapping {
- uint64_t vmAddress;
- uint64_t size;
- uint64_t fileOffset;
- };
+ operator T*() const
+ {
+ return m_obj;
+ }
- struct BackingCache {
- std::string path;
- BNBackingCacheType cacheType;
- std::vector<BackingCacheMapping> mappings;
- };
+ T* operator->() const
+ {
+ return m_obj;
+ }
- struct DSCImageMemoryMapping {
- std::string filePath;
- std::string name;
- uint64_t vmAddress;
- uint64_t size;
- bool loaded;
- uint64_t rawViewOffset;
- };
+ T& operator*() const
+ {
+ return *m_obj;
+ }
- struct DSCImage {
- std::string name;
- uint64_t headerAddress;
- std::vector<DSCImageMemoryMapping> mappings;
- };
+ bool operator!() const
+ {
+ return m_obj == NULL;
+ }
- struct DSCSymbol {
- uint64_t address;
- BinaryNinja::StringRef name;
- std::string image;
- };
+ bool operator==(const T* obj) const
+ {
+ return T::GetObject(m_obj) == T::GetObject(obj);
+ }
- struct SharedCacheMachOHeader : public SharedCacheCore::MetadataSerializable<SharedCacheMachOHeader> {
- uint64_t textBase = 0;
- uint64_t loadCommandOffset = 0;
- mach_header_64 ident;
- std::string identifierPrefix;
- std::string installName;
+ bool operator==(const DSCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) == T::GetObject(obj.m_obj);
+ }
- std::vector<std::pair<uint64_t, bool>> entryPoints;
- std::vector<uint64_t> m_entryPoints; // list of entrypoints
+ bool operator!=(const T* obj) const
+ {
+ return T::GetObject(m_obj) != T::GetObject(obj);
+ }
- symtab_command symtab;
- dysymtab_command dysymtab;
- dyld_info_command dyldInfo;
- routines_command_64 routines64;
- function_starts_command functionStarts;
- std::vector<section_64> moduleInitSections;
- linkedit_data_command exportTrie;
- linkedit_data_command chainedFixups {};
+ bool operator!=(const DSCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) != T::GetObject(obj.m_obj);
+ }
- uint64_t relocationBase;
- // Section and program headers, internally use 64-bit form as it is a superset of 32-bit
- std::vector<segment_command_64> segments; // only three types of sections __TEXT, __DATA, __IMPORT
- segment_command_64 linkeditSegment;
- std::vector<section_64> sections;
- std::vector<std::string> sectionNames;
+ bool operator<(const T* obj) const
+ {
+ return T::GetObject(m_obj) < T::GetObject(obj);
+ }
- std::vector<section_64> symbolStubSections;
- std::vector<section_64> symbolPointerSections;
+ bool operator<(const DSCRef<T>& obj) const
+ {
+ return T::GetObject(m_obj) < T::GetObject(obj.m_obj);
+ }
- std::vector<std::string> dylibs;
+ T* GetPtr() const
+ {
+ return m_obj;
+ }
+};
- build_version_command buildVersion;
- std::vector<build_tool_version> buildToolVersions;
- std::string exportTriePath;
- bool linkeditPresent = false;
- bool dysymPresent = false;
- bool dyldInfoPresent = false;
- bool exportTriePresent = false;
- bool chainedFixupsPresent = false;
- bool routinesPresent = false;
- bool functionStartsPresent = false;
- bool relocatable = false;
+// TODO: replace namespace?
+namespace SharedCacheAPI {
+ struct CacheRegion
+ {
+ BNSharedCacheRegionType type;
+ std::string name;
+ uint64_t start;
+ uint64_t size;
+ std::optional<uint64_t> imageStart;
+ BNSegmentFlag flags;
+ };
- void Store(SharedCacheCore::SerializationContext& context) const {
- MSS(textBase);
- MSS(loadCommandOffset);
- MSS_SUBCLASS(ident);
- MSS(identifierPrefix);
- MSS(installName);
- MSS(entryPoints);
- MSS(m_entryPoints);
- MSS_SUBCLASS(symtab);
- MSS_SUBCLASS(dysymtab);
- MSS_SUBCLASS(dyldInfo);
- MSS_SUBCLASS(routines64);
- MSS_SUBCLASS(functionStarts);
- MSS_SUBCLASS(moduleInitSections);
- MSS_SUBCLASS(exportTrie);
- MSS_SUBCLASS(chainedFixups);
- MSS(relocationBase);
- MSS_SUBCLASS(segments);
- MSS_SUBCLASS(linkeditSegment);
- MSS_SUBCLASS(sections);
- MSS(sectionNames);
- MSS_SUBCLASS(symbolStubSections);
- MSS_SUBCLASS(symbolPointerSections);
- MSS(dylibs);
- MSS_SUBCLASS(buildVersion);
- MSS_SUBCLASS(buildToolVersions);
- MSS(exportTriePath);
- MSS(linkeditPresent);
- MSS(dysymPresent);
- MSS(dyldInfoPresent);
- MSS(exportTriePresent);
- MSS(chainedFixupsPresent);
- MSS(routinesPresent);
- MSS(functionStartsPresent);
- MSS(relocatable);
- }
+ std::string GetRegionTypeAsString(const BNSharedCacheRegionType& type);
- static SharedCacheMachOHeader Load(SharedCacheCore::DeserializationContext& context) {
- SharedCacheMachOHeader header;
- header.MSL(textBase);
- header.MSL(loadCommandOffset);
- header.MSL(ident);
- header.MSL(identifierPrefix);
- header.MSL(installName);
- header.MSL(entryPoints);
- header.MSL(m_entryPoints);
- header.MSL(symtab);
- header.MSL(dysymtab);
- header.MSL(dyldInfo);
- header.MSL(routines64);
- header.MSL(functionStarts);
- header.MSL(moduleInitSections);
- header.MSL(exportTrie);
- header.MSL(chainedFixups);
- header.MSL(relocationBase);
- header.MSL(segments);
- header.MSL(linkeditSegment);
- header.MSL(sections);
- header.MSL(sectionNames);
- header.MSL(symbolStubSections);
- header.MSL(symbolPointerSections);
- header.MSL(dylibs);
- header.MSL(buildVersion);
- header.MSL(buildToolVersions);
- header.MSL(exportTriePath);
- header.MSL(linkeditPresent);
- header.MSL(dysymPresent);
- header.MSL(dyldInfoPresent);
- header.MSL(exportTriePresent);
- header.MSL(chainedFixupsPresent);
- header.MSL(routinesPresent);
- header.MSL(functionStartsPresent);
- header.MSL(relocatable);
- return header;
- }
+ struct CacheMappingInfo
+ {
+ uint64_t vmAddress;
+ uint64_t size;
+ uint64_t fileOffset;
+ };
+
+ struct CacheImage
+ {
+ uint64_t headerAddress;
+ std::string name;
+ std::vector<uint64_t> regionStarts;
};
+ struct CacheEntry
+ {
+ std::string path;
+ BNSharedCacheEntryType entryType;
+ std::vector<CacheMappingInfo> mappings;
+ };
+
+ struct CacheSymbol
+ {
+ BNSymbolType type;
+ uint64_t address;
+ std::string name;
+ };
- class SharedCache : public SCCoreRefCountObject<BNSharedCache, BNNewSharedCacheReference, BNFreeSharedCacheReference> {
+ class SharedCacheController : public DSCCoreRefCountObject<BNSharedCacheController, BNNewSharedCacheControllerReference, BNFreeSharedCacheControllerReference> {
public:
- SharedCache(Ref<BinaryView> view);
+ explicit SharedCacheController(BNSharedCacheController* controller);
+ static DSCRef<SharedCacheController> GetController(BinaryNinja::BinaryView& view);
- BNDSCViewState GetState();
- static BNDSCViewLoadProgress GetLoadProgress(Ref<BinaryView> view);
- static uint64_t FastGetBackingCacheCount(Ref<BinaryView> view);
+ bool ApplyRegion(BinaryNinja::BinaryView& view, const CacheRegion& region);
- bool LoadImageWithInstallName(std::string installName, bool skipObjC = false);
- bool LoadSectionAtAddress(uint64_t addr);
- bool LoadImageContainingAddress(uint64_t addr, bool skipObjC = false);
- std::vector<std::string> GetAvailableImages();
-
- void ProcessObjCSectionsForImageWithInstallName(std::string installName);
- void ProcessAllObjCSections();
+ // Attempt to load the given image into the view.
+ //
+ // It is the callers responsibility to run linear sweep and update analysis, as you might want to add
+ // multiple images at a time.
+ bool ApplyImage(BinaryNinja::BinaryView& view, const CacheImage& image);
- std::vector<DSCSymbol> LoadAllSymbolsAndWait();
+ bool IsRegionLoaded(const CacheRegion& region) const;
+ bool IsImageLoaded(const CacheImage& image) const;
- std::string GetNameForAddress(uint64_t address);
- std::string GetImageNameForAddress(uint64_t address);
+ std::optional<CacheRegion> GetRegionAt(uint64_t address) const;
+ std::optional<CacheRegion> GetRegionContaining(uint64_t address) const;
- std::vector<BackingCache> GetBackingCaches();
- std::vector<DSCImage> GetImages();
+ std::optional<CacheImage> GetImageAt(uint64_t address) const;
+ std::optional<CacheImage> GetImageContaining(uint64_t address) const;
+ std::optional<CacheImage> GetImageWithName(const std::string& name) const;
- std::optional<SharedCacheMachOHeader> GetMachOHeaderForImage(std::string name);
- std::optional<SharedCacheMachOHeader> GetMachOHeaderForAddress(uint64_t address);
+ std::vector<std::string> GetImageDependencies(const CacheImage& image) const;
- std::vector<DSCMemoryRegion> GetLoadedMemoryRegions();
+ std::optional<CacheSymbol> GetSymbolAt(uint64_t address) const;
+ std::optional<CacheSymbol> GetSymbolWithName(const std::string& name) const;
- void FindSymbolAtAddrAndApplyToAddr(uint64_t symbolLocation, uint64_t targetLocation, bool triggerReanalysis = true) const;
+ std::vector<CacheEntry> GetEntries() const;
+ std::vector<CacheRegion> GetRegions() const;
+ std::vector<CacheRegion> GetLoadedRegions() const;
+ std::vector<CacheImage> GetImages() const;
+ std::vector<CacheImage> GetLoadedImages() const;
+ std::vector<CacheSymbol> GetSymbols() const;
};
-} \ No newline at end of file
+}
diff --git a/view/sharedcache/api/sharedcachecore.h b/view/sharedcache/api/sharedcachecore.h
index 54899919..ab2acb60 100644
--- a/view/sharedcache/api/sharedcachecore.h
+++ b/view/sharedcache/api/sharedcachecore.h
@@ -1,11 +1,5 @@
#pragma once
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
#ifdef __GNUC__
#ifdef SHAREDCACHE_LIBRARY
#define SHAREDCACHE_FFI_API __attribute__((visibility("default")))
@@ -28,137 +22,139 @@ extern "C"
#endif // _MSC_VER
#endif // __GNUC__C
-#define CORE_ALLOCATED_STRUCT(T)
-
-#define CORE_ALLOCATED_CLASS(T) \
- public: \
- CORE_ALLOCATED_STRUCT(T) \
- private:
-
-#define DECLARE_SHAREDCACHE_API_OBJECT_INTERNAL(handle, cls, ns) \
- namespace ns { class cls; } struct handle { ns::cls* object; }
-
-#define DECLARE_SHAREDCACHE_API_OBJECT(handle, cls) DECLARE_SHAREDCACHE_API_OBJECT_INTERNAL(handle, cls, SharedCacheCore)
-
-#define IMPLEMENT_SHAREDCACHE_API_OBJECT(handle) \
- CORE_ALLOCATED_CLASS(handle) \
- private: \
- handle m_apiObject; \
- public: \
- typedef handle* APIHandle; \
- handle* GetAPIObject() { return &m_apiObject; } \
- private:
-#define INIT_SHAREDCACHE_API_OBJECT() \
- m_apiObject.object = this;
-
- typedef enum BNDSCViewState {
- Unloaded,
- Loaded,
- LoadedWithImages,
- } BNDSCViewState;
+#ifdef __cplusplus
+extern "C"
+{
+#endif
- typedef enum BNDSCViewLoadProgress {
- LoadProgressNotStarted,
- LoadProgressLoadingCaches,
- LoadProgressLoadingImages,
- LoadProgressFinished,
- } BNDSCViewLoadProgress;
+ // binaryninjacore.h is not included so we must duplicate enum types here.
+#ifdef BN_TYPE_PARSER
+ typedef enum BNSegmentFlag
+ {
+ SegmentExecutable = 1,
+ SegmentWritable = 2,
+ SegmentReadable = 4,
+ SegmentContainsData = 8,
+ SegmentContainsCode = 0x10,
+ SegmentDenyWrite = 0x20,
+ SegmentDenyExecute = 0x40
+ } BNSegmentFlag;
- typedef enum BNBackingCacheType {
- BackingCacheTypePrimary,
- BackingCacheTypeSecondary,
- BackingCacheTypeSymbols,
- } BNBackingCacheType;
+ typedef enum BNSymbolType
+ {
+ FunctionSymbol = 0,
+ ImportAddressSymbol = 1,
+ ImportedFunctionSymbol = 2,
+ DataSymbol = 3,
+ ImportedDataSymbol = 4,
+ ExternalSymbol = 5,
+ LibraryFunctionSymbol = 6,
+ SymbolicFunctionSymbol = 7,
+ LocalLabelSymbol = 8,
+ } BNSymbolType;
+#endif
typedef struct BNBinaryView BNBinaryView;
- typedef struct BNSharedCache BNSharedCache;
- typedef struct BNStringRef BNStringRef;
+ typedef struct BNSharedCacheController BNSharedCacheController;
- typedef struct BNDSCImageMemoryMapping {
- char* filePath;
- char* name;
- uint64_t vmAddress;
- uint64_t size;
- bool loaded;
- uint64_t rawViewOffset;
- } BNDSCImageMemoryMapping;
+ typedef enum BNSharedCacheEntryType {
+ SharedCacheEntryTypePrimary,
+ SharedCacheEntryTypeSecondary,
+ SharedCacheEntryTypeSymbols,
+ SharedCacheEntryTypeDyldData,
+ SharedCacheEntryTypeStub,
+ } BNSharedCacheEntryType;
- typedef struct BNDSCImage {
+ typedef enum BNSharedCacheRegionType {
+ SharedCacheRegionTypeImage,
+ SharedCacheRegionTypeStubIsland,
+ SharedCacheRegionTypeDyldData,
+ SharedCacheRegionTypeNonImage,
+ } BNSharedCacheRegionType;
+
+ typedef struct BNSharedCacheImage {
char* name;
uint64_t headerAddress;
- BNDSCImageMemoryMapping* mappings;
- size_t mappingCount;
- } BNDSCImage;
+ size_t regionStartCount;
+ uint64_t* regionStarts;
+ } BNSharedCacheImage;
- typedef struct BNDSCMappedMemoryRegion {
+ typedef struct BNSharedCacheRegion {
+ BNSharedCacheRegionType regionType;
+ char* name;
uint64_t vmAddress;
uint64_t size;
- char* name;
- } BNDSCMappedMemoryRegion;
+ // NOTE: If not associated with an image this will be zero.
+ uint64_t imageStart;
+ BNSegmentFlag flags;
+ } BNSharedCacheRegion;
- typedef struct BNDSCBackingCacheMapping {
+ typedef struct BNSharedCacheMappingInfo {
uint64_t vmAddress;
uint64_t size;
uint64_t fileOffset;
- } BNDSCBackingCacheMapping;
+ } BNSharedCacheMappingInfo;
- typedef struct BNDSCBackingCache {
+ typedef struct BNSharedCacheEntry {
char* path;
- BNBackingCacheType cacheType;
- BNDSCBackingCacheMapping* mappings;
+ BNSharedCacheEntryType entryType;
size_t mappingCount;
- } BNDSCBackingCache;
-
- typedef struct BNDSCMemoryUsageInfo {
- uint64_t sharedCacheRefs;
- uint64_t mmapRefs;
- } BNDSCMemoryUsageInfo;
+ BNSharedCacheMappingInfo* mappings;
+ } BNSharedCacheEntry;
- typedef struct BNDSCSymbolRep {
+ typedef struct BNSharedCacheSymbol {
+ BNSymbolType symbolType;
uint64_t address;
- BNStringRef* name;
- char* image;
- } BNDSCSymbolRep;
+ char* name;
+ } BNSharedCacheSymbol;
- SHAREDCACHE_FFI_API BNSharedCache* BNGetSharedCache(BNBinaryView* data);
+ SHAREDCACHE_FFI_API BNSharedCacheController* BNGetSharedCacheController(BNBinaryView* data);
- SHAREDCACHE_FFI_API BNSharedCache* BNNewSharedCacheReference(BNSharedCache* cache);
- SHAREDCACHE_FFI_API void BNFreeSharedCacheReference(BNSharedCache* cache);
+ SHAREDCACHE_FFI_API BNSharedCacheController* BNNewSharedCacheControllerReference(BNSharedCacheController* controller);
+ SHAREDCACHE_FFI_API void BNFreeSharedCacheControllerReference(BNSharedCacheController* controller);
- SHAREDCACHE_FFI_API char** BNDSCViewGetInstallNames(BNSharedCache* cache, size_t* count);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerApplyImage(BNSharedCacheController* controller, BNBinaryView* view, BNSharedCacheImage* image);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerApplyRegion(BNSharedCacheController* controller, BNBinaryView* view, BNSharedCacheRegion* region);
- SHAREDCACHE_FFI_API bool BNDSCViewLoadImageWithInstallName(BNSharedCache* cache, char* name, bool skipObjC);
- SHAREDCACHE_FFI_API bool BNDSCViewLoadSectionAtAddress(BNSharedCache* cache, uint64_t name);
- SHAREDCACHE_FFI_API bool BNDSCViewLoadImageContainingAddress(BNSharedCache* cache, uint64_t address, bool skipObjC);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerIsImageLoaded(BNSharedCacheController* controller, BNSharedCacheImage* image);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerIsRegionLoaded(BNSharedCacheController* controller, BNSharedCacheRegion* region);
- SHAREDCACHE_FFI_API void BNDSCViewProcessObjCSectionsForImageWithInstallName(BNSharedCache* cache, char* name, bool deallocName);
- SHAREDCACHE_FFI_API void BNDSCViewProcessAllObjCSections(BNSharedCache* cache);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerGetRegionAt(BNSharedCacheController* controller, uint64_t address, BNSharedCacheRegion* outRegion);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerGetRegionContaining(BNSharedCacheController* controller, uint64_t address, BNSharedCacheRegion* region);
+
+ SHAREDCACHE_FFI_API BNSharedCacheRegion* BNSharedCacheControllerGetRegions(BNSharedCacheController* controller, size_t* count);
+ SHAREDCACHE_FFI_API BNSharedCacheRegion* BNSharedCacheControllerGetLoadedRegions(BNSharedCacheController* controller, size_t* count);
+
+ SHAREDCACHE_FFI_API uint64_t* BNSharedCacheAllocRegionList(uint64_t* list, size_t count);
+
+ SHAREDCACHE_FFI_API void BNSharedCacheFreeRegion(BNSharedCacheRegion region);
+ SHAREDCACHE_FFI_API void BNSharedCacheFreeRegionList(BNSharedCacheRegion* regions, size_t count);
+
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerGetImageAt(BNSharedCacheController* controller, uint64_t address, BNSharedCacheImage* image);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerGetImageContaining(BNSharedCacheController* controller, uint64_t address, BNSharedCacheImage* image);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerGetImageWithName(BNSharedCacheController* controller, const char* name, BNSharedCacheImage* image);
- SHAREDCACHE_FFI_API char* BNDSCViewGetNameForAddress(BNSharedCache* cache, uint64_t address);
- SHAREDCACHE_FFI_API char* BNDSCViewGetImageNameForAddress(BNSharedCache* cache, uint64_t address);
+ SHAREDCACHE_FFI_API char** BNSharedCacheControllerGetImageDependencies(BNSharedCacheController* controller, BNSharedCacheImage* image, size_t* count);
- SHAREDCACHE_FFI_API BNDSCViewState BNDSCViewGetState(BNSharedCache* cache);
- SHAREDCACHE_FFI_API BNDSCViewLoadProgress BNDSCViewGetLoadProgress(uint64_t sessionID);
- SHAREDCACHE_FFI_API uint64_t BNDSCViewFastGetBackingCacheCount(BNBinaryView* view);
+ SHAREDCACHE_FFI_API BNSharedCacheImage* BNSharedCacheControllerGetImages(BNSharedCacheController* controller, size_t* count);
+ SHAREDCACHE_FFI_API BNSharedCacheImage* BNSharedCacheControllerGetLoadedImages(BNSharedCacheController* controller, size_t* count);
- SHAREDCACHE_FFI_API BNDSCSymbolRep* BNDSCViewLoadAllSymbolsAndWait(BNSharedCache* cache, size_t* count);
- SHAREDCACHE_FFI_API void BNDSCViewFreeSymbols(BNDSCSymbolRep* symbols, size_t count);
+ SHAREDCACHE_FFI_API void BNSharedCacheFreeImage(BNSharedCacheImage image);
+ SHAREDCACHE_FFI_API void BNSharedCacheFreeImageList(BNSharedCacheImage* images, size_t count);
- SHAREDCACHE_FFI_API BNDSCMappedMemoryRegion* BNDSCViewGetLoadedRegions(BNSharedCache* cache, size_t* count);
- SHAREDCACHE_FFI_API void BNDSCViewFreeLoadedRegions(BNDSCMappedMemoryRegion* images, size_t count);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerGetSymbolAt(BNSharedCacheController* controller, uint64_t address, BNSharedCacheSymbol* symbol);
+ SHAREDCACHE_FFI_API bool BNSharedCacheControllerGetSymbolWithName(BNSharedCacheController* controller, const char* name, BNSharedCacheSymbol* symbol);
- SHAREDCACHE_FFI_API BNDSCImage* BNDSCViewGetAllImages(BNSharedCache* cache, size_t* count);
- SHAREDCACHE_FFI_API void BNDSCViewFreeAllImages(BNDSCImage* images, size_t count);
+ SHAREDCACHE_FFI_API BNSharedCacheSymbol* BNSharedCacheControllerGetSymbols(BNSharedCacheController* controller, size_t* count);
- SHAREDCACHE_FFI_API BNDSCBackingCache* BNDSCViewGetBackingCaches(BNSharedCache* cache, size_t* count);
- SHAREDCACHE_FFI_API void BNDSCViewFreeBackingCaches(BNDSCBackingCache* caches, size_t count);
+ SHAREDCACHE_FFI_API void BNSharedCacheFreeSymbol(BNSharedCacheSymbol symbol);
+ SHAREDCACHE_FFI_API void BNSharedCacheFreeSymbolList(BNSharedCacheSymbol* symbols, size_t count);
- SHAREDCACHE_FFI_API void BNDSCFindSymbolAtAddressAndApplyToAddress(BNSharedCache* cache, uint64_t symbolLocation, uint64_t targetLocation, bool triggerReanalysis);
+ SHAREDCACHE_FFI_API BNSharedCacheEntry* BNSharedCacheControllerGetEntries(BNSharedCacheController* controller, size_t* count);
- SHAREDCACHE_FFI_API char* BNDSCViewGetImageHeaderForAddress(BNSharedCache* cache, uint64_t address);
- SHAREDCACHE_FFI_API char* BNDSCViewGetImageHeaderForName(BNSharedCache* cache, char* name);
+ SHAREDCACHE_FFI_API void BNSharedCacheFreeEntry(BNSharedCacheEntry entry);
+ SHAREDCACHE_FFI_API void BNSharedCacheFreeEntryList(BNSharedCacheEntry* entries, size_t count);
- [[maybe_unused]] SHAREDCACHE_FFI_API BNDSCMemoryUsageInfo BNDSCViewGetMemoryUsageInfo();
#ifdef __cplusplus
}