Skip to content

Commit 8509005

Browse files
committed
DBO: Expose GetChild/GetChildNames/FindChild
1 parent 8678623 commit 8509005

4 files changed

Lines changed: 74 additions & 1 deletion

File tree

binaryninjaapi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22410,6 +22410,9 @@ namespace BinaryNinja {
2241022410
Ref<Metadata> GetMetadata() const;
2241122411
Ref<DatabaseObject> GetParent() const;
2241222412
std::unordered_map<std::string, Ref<DatabaseObject>> GetChildren();
22413+
std::vector<std::string> GetChildNames();
22414+
std::optional<Ref<DatabaseObject>> GetChild(const std::string& key);
22415+
std::optional<Ref<DatabaseObject>> FindChild(const std::vector<std::string>& path);
2241322416
std::vector<std::string> GetDependencies() const;
2241422417
};
2241522418

binaryninjacore.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9131,6 +9131,9 @@ extern "C"
91319131
BINARYNINJACOREAPI BNMetadata* BNGetDatabaseObjectMetadata(BNDatabaseObject* object);
91329132
BINARYNINJACOREAPI BNDatabaseObject* BNGetDatabaseObjectParent(BNDatabaseObject* object);
91339133
BINARYNINJACOREAPI size_t BNGetDatabaseObjectChildren(BNDatabaseObject* object, char*** names, BNDatabaseObject*** objects);
9134+
BINARYNINJACOREAPI char** BNGetDatabaseObjectChildNames(BNDatabaseObject* object, size_t* count);
9135+
BINARYNINJACOREAPI BNDatabaseObject* BNGetDatabaseObjectChild(BNDatabaseObject* object, const char* key);
9136+
BINARYNINJACOREAPI BNDatabaseObject* BNFindDatabaseObjectChild(BNDatabaseObject* object, const char** path, size_t pathLength);
91349137
BINARYNINJACOREAPI char** BNGetDatabaseObjectDependencies(BNDatabaseObject* object, size_t* count);
91359138

91369139
BINARYNINJACOREAPI BNDiffState* BNNewDiffStateReference(BNDiffState* state);

merge.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,43 @@ std::unordered_map<std::string, Ref<DatabaseObject>> DatabaseObject::GetChildren
8787
}
8888

8989

90-
// todo: expose GetChild() and friends
90+
std::vector<std::string> DatabaseObject::GetChildNames()
91+
{
92+
size_t count = 0;
93+
char** names = BNGetDatabaseObjectChildNames(m_object, &count);
94+
std::vector<std::string> result = ParseStringList(names, count);
95+
BNFreeStringList(names, count);
96+
return result;
97+
}
98+
99+
100+
std::optional<Ref<DatabaseObject>> DatabaseObject::GetChild(const std::string& key)
101+
{
102+
BNDatabaseObject* child = BNGetDatabaseObjectChild(m_object, key.c_str());
103+
if (child)
104+
{
105+
return new DatabaseObject(child);
106+
}
107+
return std::nullopt;
108+
}
109+
110+
111+
std::optional<Ref<DatabaseObject>> DatabaseObject::FindChild(const std::vector<std::string>& path)
112+
{
113+
std::vector<const char*> pathCStrs;
114+
pathCStrs.reserve(path.size());
115+
for (const auto& item : path)
116+
{
117+
pathCStrs.push_back(item.c_str());
118+
}
119+
120+
BNDatabaseObject* child = BNFindDatabaseObjectChild(m_object, pathCStrs.data(), pathCStrs.size());
121+
if (child)
122+
{
123+
return new DatabaseObject(child);
124+
}
125+
return std::nullopt;
126+
}
91127

92128

93129
std::vector<std::string> DatabaseObject::GetDependencies() const

python/database.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,37 @@ def _generate_children(self) -> Dict[str, 'DatabaseObject']:
431431
core.BNFreeDatabaseObjectList(objects, count)
432432
core.BNFreeStringList(names, count)
433433

434+
@property
435+
def child_names(self) -> List[str]:
436+
"""Get list of child object names (read-only)"""
437+
count = ctypes.c_size_t()
438+
names = core.BNGetDatabaseObjectChildNames(self.handle, ctypes.byref(count))
439+
try:
440+
result = []
441+
for i in range(0, count.value):
442+
result.append(core.pyNativeStr(names[i]))
443+
return result
444+
finally:
445+
core.BNFreeStringList(names, count.value)
446+
447+
def get_child(self, key: str) -> Optional['DatabaseObject']:
448+
"""Get a single child object by key"""
449+
handle = core.BNGetDatabaseObjectChild(self.handle, key)
450+
if handle is None:
451+
return None
452+
return DatabaseObject(handle=handle)
453+
454+
def find_child(self, path: List[str]) -> Optional['DatabaseObject']:
455+
"""Find a child object by following a path"""
456+
path_array = (ctypes.c_char_p * len(path))()
457+
for i, item in enumerate(path):
458+
path_array[i] = item.encode('utf-8')
459+
460+
handle = core.BNFindDatabaseObjectChild(self.handle, path_array, len(path))
461+
if handle is None:
462+
return None
463+
return DatabaseObject(handle=handle)
464+
434465
@property
435466
def dependencies(self) -> List[str]:
436467
"""Get list of dependencies for this database object (read-only)"""

0 commit comments

Comments
 (0)