Skip to content

Commit 3d7bb5a

Browse files
committed
Add analysis completion event and wait API
1 parent 640a47a commit 3d7bb5a

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

binaryninjaapi.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,20 @@ namespace BinaryNinja
571571
uint64_t addr;
572572
};
573573

574+
class AnalysisCompletionEvent: public CoreRefCountObject<BNAnalysisCompletionEvent,
575+
BNNewAnalysisCompletionEventReference, BNFreeAnalysisCompletionEvent>
576+
{
577+
protected:
578+
std::function<void()> m_callback;
579+
std::recursive_mutex m_mutex;
580+
581+
static void CompletionCallback(void* ctxt);
582+
583+
public:
584+
AnalysisCompletionEvent(BinaryView* view, const std::function<void()>& callback);
585+
void Cancel();
586+
};
587+
574588
class BinaryView: public CoreRefCountObject<BNBinaryView, BNNewViewReference, BNFreeBinaryView>
575589
{
576590
protected:
@@ -740,6 +754,8 @@ namespace BinaryNinja
740754

741755
std::vector<BNStringReference> GetStrings();
742756
std::vector<BNStringReference> GetStrings(uint64_t start, uint64_t len);
757+
758+
Ref<AnalysisCompletionEvent> AddAnalysisCompletionEvent(const std::function<void()>& callback);
743759
};
744760

745761
class BinaryData: public BinaryView

binaryninjacore.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ extern "C"
9595
struct BNEnumeration;
9696
struct BNCallingConvention;
9797
struct BNPlatform;
98+
struct BNAnalysisCompletionEvent;
9899

99100
enum BNLogLevel
100101
{
@@ -1203,6 +1204,12 @@ extern "C"
12031204
uint64_t addr, size_t* count);
12041205
BINARYNINJACOREAPI void BNFreeInstructionTextLines(BNInstructionTextLine* lines, size_t count);
12051206

1207+
BINARYNINJACOREAPI BNAnalysisCompletionEvent* BNAddAnalysisCompletionEvent(BNBinaryView* view, void* ctxt,
1208+
void (*callback)(void* ctxt));
1209+
BINARYNINJACOREAPI BNAnalysisCompletionEvent* BNNewAnalysisCompletionEventReference(BNAnalysisCompletionEvent* event);
1210+
BINARYNINJACOREAPI void BNFreeAnalysisCompletionEvent(BNAnalysisCompletionEvent* event);
1211+
BINARYNINJACOREAPI void BNCancelAnalysisCompletionEvent(BNAnalysisCompletionEvent* event);
1212+
12061213
// Function graph
12071214
BINARYNINJACOREAPI BNFunctionGraph* BNCreateFunctionGraph(BNFunction* func);
12081215
BINARYNINJACOREAPI BNFunctionGraph* BNNewFunctionGraphReference(BNFunctionGraph* graph);

binaryview.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,30 @@ Ref<Symbol> Symbol::ImportedFunctionFromImportAddressSymbol(Symbol* sym, uint64_
180180
}
181181

182182

183+
AnalysisCompletionEvent::AnalysisCompletionEvent(BinaryView* view, const std::function<void()>& callback):
184+
m_callback(callback)
185+
{
186+
m_object = BNAddAnalysisCompletionEvent(view->GetObject(), this, CompletionCallback);
187+
}
188+
189+
190+
void AnalysisCompletionEvent::CompletionCallback(void* ctxt)
191+
{
192+
AnalysisCompletionEvent* event = (AnalysisCompletionEvent*)ctxt;
193+
194+
unique_lock<recursive_mutex> lock(event->m_mutex);
195+
event->m_callback();
196+
event->m_callback = []() {};
197+
}
198+
199+
200+
void AnalysisCompletionEvent::Cancel()
201+
{
202+
unique_lock<recursive_mutex> lock(m_mutex);
203+
m_callback = []() {};
204+
}
205+
206+
183207
BinaryView::BinaryView(const std::string& typeName, FileMetadata* file)
184208
{
185209
BNCustomBinaryView view;
@@ -1064,6 +1088,12 @@ vector<BNStringReference> BinaryView::GetStrings(uint64_t start, uint64_t len)
10641088
}
10651089

10661090

1091+
Ref<AnalysisCompletionEvent> BinaryView::AddAnalysisCompletionEvent(const function<void()>& callback)
1092+
{
1093+
return new AnalysisCompletionEvent(this, callback);
1094+
}
1095+
1096+
10671097
BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject()))
10681098
{
10691099
}

python/__init__.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,29 @@ def __setattr__(self, name, value):
627627
except AttributeError:
628628
raise AttributeError, "attribute '%s' is read only" % name
629629

630+
class AnalysisCompletionEvent(object):
631+
def __init__(self, view, callback):
632+
self.view = view
633+
self.callback = callback
634+
self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._notify)
635+
self.handle = core.BNAddAnalysisCompletionEvent(self.view.handle, None, self._cb)
636+
637+
def __del__(self):
638+
core.BNFreeAnalysisCompletionEvent(self.handle)
639+
640+
def _notify(self, ctxt):
641+
try:
642+
self.callback()
643+
except:
644+
log_error(traceback.format_exc())
645+
646+
def _empty_callback(self):
647+
pass
648+
649+
def cancel(self):
650+
self.callback = self._empty_callback
651+
core.BNCancelAnalysisCompletionEvent(self.handle)
652+
630653
class BinaryView(object):
631654
name = None
632655
"""Binary View name"""
@@ -1252,6 +1275,29 @@ def create_user_function(self, platform, addr):
12521275
def update_analysis(self):
12531276
core.BNUpdateAnalysis(self.handle)
12541277

1278+
def update_analysis_and_wait(self):
1279+
class WaitEvent:
1280+
def __init__(self):
1281+
self.cond = threading.Condition()
1282+
self.done = False
1283+
1284+
def complete(self):
1285+
self.cond.acquire()
1286+
self.done = True
1287+
self.cond.notify()
1288+
self.cond.release()
1289+
1290+
def wait(self):
1291+
self.cond.acquire()
1292+
while not self.done:
1293+
self.cond.wait()
1294+
self.cond.release()
1295+
1296+
wait = WaitEvent()
1297+
event = AnalysisCompletionEvent(self, lambda: wait.complete())
1298+
core.BNUpdateAnalysis(self.handle)
1299+
wait.wait()
1300+
12551301
def abort_analysis(self):
12561302
core.BNAbortAnalysis(self.handle)
12571303

@@ -1428,6 +1474,9 @@ def get_strings(self, start = None, length = None):
14281474
core.BNFreeStringList(strings)
14291475
return result
14301476

1477+
def add_analysis_completion_event(self, callback):
1478+
return AnalysisCompletionEvent(self, callback)
1479+
14311480
def __setattr__(self, name, value):
14321481
try:
14331482
object.__setattr__(self,name,value)

0 commit comments

Comments
 (0)