Skip to content

Commit

Permalink
Update load APIs to take a JSON string for options.
Browse files Browse the repository at this point in the history
  • Loading branch information
bpotchik committed May 27, 2024
1 parent 309d606 commit a348dab
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 51 deletions.
37 changes: 22 additions & 15 deletions binaryninjaapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,7 @@ namespace BinaryNinja {
std::vector<uint8_t> GetRaw() const;
std::vector<Ref<Metadata>> GetArray() const;
std::map<std::string, Ref<Metadata>> GetKeyValueStore() const;
std::string GetJsonString() const;

// For key-value data only
/*! Get a Metadata object by key. Only for if IsKeyValueStore == true
Expand Down Expand Up @@ -1483,15 +1484,12 @@ namespace BinaryNinja {
\param filename Path to filename or BNDB to open.
\param updateAnalysis If true, UpdateAnalysisAndWait() will be called after opening
a BinaryView.
\param options A Json string whose keys are setting identifiers and whose values are the desired settings.
\param progress Optional function to be called with progress updates as the view is
being loaded. If the function returns false, it will cancel Load.
\param options A Json object whose keys are setting identifiers and whose values are
the desired settings.
\return Constructed view, or a nullptr Ref<BinaryView>
*/
Ref<BinaryView> Load(const std::string& filename, bool updateAnalysis = true,
std::function<bool(size_t, size_t)> progress = {}, Ref<Metadata> options = new Metadata(MetadataType::KeyValueDataType));

Ref<BinaryView> Load(const std::string& filename, bool updateAnalysis = true, const std::string& options = "{}", std::function<bool(size_t, size_t)> progress = {});
/*! Open a BinaryView from a raw data buffer, initializing data views and loading settings.

@threadmainonly
Expand All @@ -1502,14 +1500,12 @@ namespace BinaryNinja {
\param rawData Buffer with raw binary data to load (cannot load from bndb)
\param updateAnalysis If true, UpdateAnalysisAndWait() will be called after opening
a BinaryView.
\param options A Json string whose keys are setting identifiers and whose values are the desired settings.
\param progress Optional function to be called with progress updates as the view is
being loaded. If the function returns false, it will cancel Load.
\param options A Json object whose keys are setting identifiers and whose values are
the desired settings.
\return Constructed view, or a nullptr Ref<BinaryView>
*/
Ref<BinaryView> Load(const DataBuffer& rawData, bool updateAnalysis = true,
std::function<bool(size_t, size_t)> progress = {}, Ref<Metadata> options = new Metadata(MetadataType::KeyValueDataType));
Ref<BinaryView> Load(const DataBuffer& rawData, bool updateAnalysis = true, const std::string& options = "{}", std::function<bool(size_t, size_t)> progress = {});


/*! Open a BinaryView from a raw BinaryView, initializing data views and loading settings.
Expand All @@ -1522,16 +1518,27 @@ namespace BinaryNinja {
\param rawData BinaryView with raw binary data to load
\param updateAnalysis If true, UpdateAnalysisAndWait() will be called after opening
a BinaryView.
\param options A Json string whose keys are setting identifiers and whose values are the desired settings.
\param progress Optional function to be called with progress updates as the view is
being loaded. If the function returns false, it will cancel Load.
\param options A Json object whose keys are setting identifiers and whose values are
the desired settings.
\param isDatabase True if the view being loaded is the raw view of an already opened database.
\return Constructed view, or a nullptr Ref<BinaryView>
*/
Ref<BinaryView> Load(Ref<BinaryView> rawData, bool updateAnalysis = true,
std::function<bool(size_t, size_t)> progress = {}, Ref<Metadata> options = new Metadata(MetadataType::KeyValueDataType),
bool isDatabase = false);
Ref<BinaryView> Load(Ref<BinaryView> rawData, bool updateAnalysis = true, const std::string& options = "{}", std::function<bool(size_t, size_t)> progress = {});

/*!
Deprecated. Use non-metadata version.
*/
Ref<BinaryView> Load(const std::string& filename, bool updateAnalysis, std::function<bool(size_t, size_t)> progress, Ref<Metadata> options = new Metadata(MetadataType::KeyValueDataType));

/*!
Deprecated. Use non-metadata version.
*/
Ref<BinaryView> Load(const DataBuffer& rawData, bool updateAnalysis, std::function<bool(size_t, size_t)> progress, Ref<Metadata> options = new Metadata(MetadataType::KeyValueDataType));

/*!
Deprecated. Use non-metadata version.
*/
Ref<BinaryView> Load(Ref<BinaryView> rawData, bool updateAnalysis, std::function<bool(size_t, size_t)> progress, Ref<Metadata> options = new Metadata(MetadataType::KeyValueDataType), bool isDatabase = false);

/*! Demangles using LLVM's demangler

Expand Down
14 changes: 6 additions & 8 deletions binaryninjacore.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
// Current ABI version for linking to the core. This is incremented any time
// there are changes to the API that affect linking, including new functions,
// new types, or modifications to existing functions or types.
#define BN_CURRENT_CORE_ABI_VERSION 64
#define BN_CURRENT_CORE_ABI_VERSION 65

// Minimum ABI version that is supported for loading of plugins. Plugins that
// are linked to an ABI version less than this will not be able to load and
// will require rebuilding. The minimum version is increased when there are
// incompatible changes that break binary compatibility, such as changes to
// existing types or functions.
#define BN_MINIMUM_CORE_ABI_VERSION 64
#define BN_MINIMUM_CORE_ABI_VERSION 65

#ifdef __GNUC__
#ifdef BINARYNINJACORE_LIBRARY
Expand Down Expand Up @@ -6119,12 +6119,9 @@ extern "C"
BINARYNINJACOREAPI bool BNCheckForStringAnnotationType(BNBinaryView* view, uint64_t addr, char** value, BNStringType* strType,
bool allowShortStrings, bool allowLargeStrings, size_t childWidth);

BINARYNINJACOREAPI BNBinaryView* BNLoadFilename(const char* const filename, const bool updateAnalysis,
bool (*progress)(size_t, size_t), const BNMetadata* const options);
BINARYNINJACOREAPI BNBinaryView* BNLoadProjectFile(BNProjectFile* projectFile, const bool updateAnalysis,
bool (*progress)(size_t, size_t), const BNMetadata* const options);
BINARYNINJACOREAPI BNBinaryView* BNLoadBinaryView(BNBinaryView* view, const bool updateAnalysis,
bool (*progress)(size_t, size_t), const BNMetadata* const options, const bool isDatabase);
BINARYNINJACOREAPI BNBinaryView* BNLoadFilename(const char* const filename, const bool updateAnalysis, const char* options, bool (*progress)(size_t, size_t));
BINARYNINJACOREAPI BNBinaryView* BNLoadProjectFile(BNProjectFile* projectFile, const bool updateAnalysis, const char* options, bool (*progress)(size_t, size_t));
BINARYNINJACOREAPI BNBinaryView* BNLoadBinaryView(BNBinaryView* view, const bool updateAnalysis, const char* options, bool (*progress)(size_t, size_t));

BINARYNINJACOREAPI BNExternalLibrary* BNBinaryViewAddExternalLibrary(BNBinaryView* view, const char* name, BNProjectFile* backingFile, bool isAuto);
BINARYNINJACOREAPI void BNBinaryViewRemoveExternalLibrary(BNBinaryView* view, const char* name);
Expand Down Expand Up @@ -6902,6 +6899,7 @@ extern "C"
BINARYNINJACOREAPI uint8_t* BNMetadataGetRaw(BNMetadata* data, size_t* size);
BINARYNINJACOREAPI BNMetadata** BNMetadataGetArray(BNMetadata* data, size_t* size);
BINARYNINJACOREAPI BNMetadataValueStore* BNMetadataGetValueStore(BNMetadata* data);
BINARYNINJACOREAPI char* BNMetadataGetJsonString(BNMetadata* data);

// Query type of Metadata
BINARYNINJACOREAPI BNMetadataType BNMetadataGetType(BNMetadata* data);
Expand Down
32 changes: 25 additions & 7 deletions binaryview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5316,11 +5316,7 @@ Ref<BinaryData> BinaryData::CreateFromFile(FileMetadata* file, FileAccessor* acc
Ref<BinaryView> BinaryNinja::Load(const std::string& filename, bool updateAnalysis,
std::function<bool(size_t, size_t)> progress, Ref<Metadata> options)
{
BNBinaryView* handle = BNLoadFilename(filename.c_str(), updateAnalysis,
(bool (*)(size_t, size_t))progress.target<bool (*)(size_t, size_t)>(), options->m_object);
if (!handle)
return nullptr;
return new BinaryView(handle);
return Load(filename, updateAnalysis, options->GetJsonString(), progress);
}


Expand All @@ -5336,8 +5332,30 @@ Ref<BinaryView> BinaryNinja::Load(
Ref<BinaryView> BinaryNinja::Load(Ref<BinaryView> view, bool updateAnalysis,
std::function<bool(size_t, size_t)> progress, Ref<Metadata> options, bool isDatabase)
{
BNBinaryView* handle = BNLoadBinaryView(view->GetObject(), updateAnalysis,
(bool (*)(size_t, size_t))progress.target<bool (*)(size_t, size_t)>(), options->m_object, isDatabase);
return Load(view, updateAnalysis, options->GetJsonString(), progress);
}


Ref<BinaryView> BinaryNinja::Load(const std::string& filename, bool updateAnalysis, const std::string& options, std::function<bool(size_t, size_t)> progress)
{
BNBinaryView* handle = BNLoadFilename(filename.c_str(), updateAnalysis, options.c_str(), (bool (*)(size_t, size_t))progress.target<bool (*)(size_t, size_t)>());
if (!handle)
return nullptr;
return new BinaryView(handle);
}


Ref<BinaryView> BinaryNinja::Load(const DataBuffer& rawData, bool updateAnalysis, const std::string& options, std::function<bool(size_t, size_t)> progress)
{
Ref<FileMetadata> file = new FileMetadata();
Ref<BinaryView> view = new BinaryData(file, rawData);
return Load(view, updateAnalysis, options, progress);
}


Ref<BinaryView> BinaryNinja::Load(Ref<BinaryView> view, bool updateAnalysis, const std::string& options, std::function<bool(size_t, size_t)> progress)
{
BNBinaryView* handle = BNLoadBinaryView(view->GetObject(), updateAnalysis, options.c_str(), (bool (*)(size_t, size_t))progress.target<bool (*)(size_t, size_t)>());
if (!handle)
return nullptr;
return new BinaryView(handle);
Expand Down
22 changes: 15 additions & 7 deletions metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Metadata::Metadata(bool data)
m_object = BNCreateMetadataBooleanData(data);
}

Metadata::Metadata(const string& data)
Metadata::Metadata(const std::string& data)
{
m_object = BNCreateMetadataStringData(data.c_str());
}
Expand Down Expand Up @@ -163,12 +163,12 @@ Ref<Metadata> Metadata::Get(size_t index)
return new Metadata(result);
}

bool Metadata::SetValueForKey(const string& key, Ref<Metadata> data)
bool Metadata::SetValueForKey(const std::string& key, Ref<Metadata> data)
{
return BNMetadataSetValueForKey(m_object, key.c_str(), data->m_object);
}

void Metadata::RemoveKey(const string& key)
void Metadata::RemoveKey(const std::string& key)
{
return BNMetadataRemoveKey(m_object, key.c_str());
}
Expand All @@ -183,10 +183,10 @@ bool Metadata::GetBoolean() const
return BNMetadataGetBoolean(m_object);
}

string Metadata::GetString() const
std::string Metadata::GetString() const
{
char* str = BNMetadataGetString(m_object);
string result = string(str);
std::string result = std::string(str);
BNFreeString(str);
return result;
}
Expand Down Expand Up @@ -312,17 +312,25 @@ vector<Ref<Metadata>> Metadata::GetArray() const
return result;
}

map<string, Ref<Metadata>> Metadata::GetKeyValueStore() const
map<std::string, Ref<Metadata>> Metadata::GetKeyValueStore() const
{
BNMetadataValueStore* data = BNMetadataGetValueStore(m_object);
map<string, Ref<Metadata>> result;
map<std::string, Ref<Metadata>> result;
for (size_t i = 0; i < data->size; i++)
{
result[data->keys[i]] = new Metadata(data->values[i]);
}
return result;
}

std::string Metadata::GetJsonString() const
{
char* str = BNMetadataGetJsonString(m_object);
std::string result = std::string(str);
BNFreeString(str);
return result;
}

bool Metadata::Append(Ref<Metadata> data)
{
return BNMetadataArrayAppend(m_object, data->m_object);
Expand Down
22 changes: 11 additions & 11 deletions python/binaryview.py
Original file line number Diff line number Diff line change
Expand Up @@ -2136,12 +2136,12 @@ class MemoryMap:
size: 0x4
objects:
'origin<Mapped>' | Mapped<Absolute>
<region: 0xc0000000 - 0xc0001000>
size: 0x1000
objects:
'origin<Mapped>' | Unmapped | FILL<0x0>
<region: 0xc0001000 - 0xc0001014>
size: 0x14
objects:
Expand All @@ -2153,13 +2153,13 @@ class MemoryMap:
size: 0x4
objects:
'origin<Mapped>' | Mapped<Absolute>
<region: 0xc0000000 - 0xc0001000>
size: 0x1000
objects:
'rom' | Mapped
'origin<Mapped>' | Unmapped | FILL<0x0>
<region: 0xc0001000 - 0xc0001014>
size: 0x14
objects:
Expand All @@ -2175,20 +2175,20 @@ class MemoryMap:
size: 0x4
objects:
'origin<Mapped>' | Mapped<Absolute>
<region: 0xc0000000 - 0xc0000008>
size: 0x8
objects:
'pad' | Mapped<Relative>
'rom' | Mapped<Relative>
'origin<Mapped>' | Unmapped | FILL<0x0>
<region: 0xc0000008 - 0xc0001000>
size: 0xff8
objects:
'rom' | Mapped<Relative>
'origin<Mapped>' | Unmapped | FILL<0x0>
<region: 0xc0001000 - 0xc0001014>
size: 0x14
objects:
Expand Down Expand Up @@ -2751,14 +2751,14 @@ def load(source: Union[str, bytes, bytearray, 'databuffer.DataBuffer', 'os.PathL
if isinstance(source, os.PathLike):
source = str(source)
if isinstance(source, BinaryView):
handle = core.BNLoadBinaryView(source.handle, update_analysis, progress_cfunc, metadata.Metadata(options).handle, source.file.has_database)
handle = core.BNLoadBinaryView(source.handle, update_analysis, json.dumps(options), progress_cfunc)
elif isinstance(source, project.ProjectFile):
handle = core.BNLoadProjectFile(source._handle, update_analysis, progress_cfunc, metadata.Metadata(options).handle)
handle = core.BNLoadProjectFile(source._handle, update_analysis, json.dumps(options), progress_cfunc)
elif isinstance(source, str):
handle = core.BNLoadFilename(source, update_analysis, progress_cfunc, metadata.Metadata(options).handle)
handle = core.BNLoadFilename(source, update_analysis, json.dumps(options), progress_cfunc)
elif isinstance(source, bytes) or isinstance(source, bytearray) or isinstance(source, databuffer.DataBuffer):
raw_view = BinaryView.new(source)
handle = core.BNLoadBinaryView(raw_view.handle, update_analysis, progress_cfunc, metadata.Metadata(options).handle, False)
handle = core.BNLoadBinaryView(raw_view.handle, update_analysis, json.dumps(options), progress_cfunc)
else:
raise NotImplementedError
return BinaryView(handle=handle) if handle else None
Expand Down
3 changes: 3 additions & 0 deletions python/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ def get_dict(self):
result[key] = self[key]
return result

def get_json_string(self):
return str(core.BNMetadataGetJsonString(self.handle))

@property
def type(self):
return MetadataType(core.BNMetadataGetType(self.handle))
Expand Down
5 changes: 2 additions & 3 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,13 @@ const BN_INVALID_EXPR: usize = usize::MAX;
/// The main way to open and load files into Binary Ninja. Make sure you've properly initialized the core before calling this function. See [`crate::headless::init()`]
pub fn load<S: BnStrCompatible>(filename: S) -> Option<rc::Ref<binaryview::BinaryView>> {
let filename = filename.into_bytes_with_nul();
let metadata = Metadata::new_of_type(MetadataType::KeyValueDataType);

let handle = unsafe {
binaryninjacore_sys::BNLoadFilename(
filename.as_ref().as_ptr() as *mut _,
true,
std::ptr::null(),
None,
metadata.handle,
)
};

Expand Down Expand Up @@ -245,8 +244,8 @@ pub fn load_with_options<S: BnStrCompatible>(
binaryninjacore_sys::BNLoadFilename(
filename.as_ref().as_ptr() as *mut _,
update_analysis_and_wait,
options_or_default.get_json_string().unwrap().as_ref().as_ptr() as *mut _,
None,
options_or_default.as_ref().handle,
)
};

Expand Down
13 changes: 13 additions & 0 deletions rust/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,19 @@ impl Metadata {
}
}

pub fn get_json_string(&self) -> Result<BnString, ()> {
match self.get_type() {
MetadataType::StringDataType => {
let ptr: *mut c_char = unsafe { BNMetadataGetJsonString(self.handle) };
if ptr.is_null() {
return Err(());
}
Ok(unsafe { BnString::from_raw(ptr) })
}
_ => Err(()),
}
}

pub fn get_raw(&self) -> Result<Vec<u8>, ()> {
match self.get_type() {
MetadataType::RawDataType => {
Expand Down

0 comments on commit a348dab

Please sign in to comment.