-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathdebuggerapi.h
More file actions
930 lines (760 loc) · 27.7 KB
/
debuggerapi.h
File metadata and controls
930 lines (760 loc) · 27.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
/*
Copyright 2020-2026 Vector 35 Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include "binaryninjaapi.h"
#include "ffi.h"
#include "../vendor/intx/intx.hpp"
#include <optional>
#include <functional>
using namespace BinaryNinja;
namespace BinaryNinjaDebuggerAPI {
template <class T>
class DbgRefCountObject
{
void AddRefInternal() { m_refs.fetch_add(1); }
void ReleaseInternal()
{
if (m_refs.fetch_sub(1) == 1)
delete this;
}
public:
std::atomic<int> m_refs;
T* m_object;
DbgRefCountObject() : m_refs(0), m_object(nullptr) {}
virtual ~DbgRefCountObject() {}
T* GetObject() const { return m_object; }
static T* GetObject(DbgRefCountObject* obj)
{
if (!obj)
return nullptr;
return obj->GetObject();
}
void AddRef() { AddRefInternal(); }
void Release() { ReleaseInternal(); }
void AddRefForRegistration() { AddRefInternal(); }
};
template <class T, T* (*AddObjectReference)(T*), void (*FreeObjectReference)(T*)>
class DbgCoreRefCountObject
{
void AddRefInternal() { m_refs.fetch_add(1); }
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;
DbgCoreRefCountObject() : m_refs(0), m_object(nullptr) {}
virtual ~DbgCoreRefCountObject() {}
T* GetObject() const { return m_object; }
static T* GetObject(DbgCoreRefCountObject* 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();
}
void AddRefForRegistration() { m_registeredRef = true; }
void ReleaseForRegistration()
{
m_object = nullptr;
m_registeredRef = false;
if (m_refs == 0)
delete this;
}
};
template <class T>
class DbgRef
{
T* m_obj;
#ifdef BN_REF_COUNT_DEBUG
void* m_assignmentTrace = nullptr;
#endif
public:
DbgRef() : m_obj(NULL) {}
DbgRef(T* obj) : m_obj(obj)
{
if (m_obj)
{
m_obj->AddRef();
#ifdef BN_REF_COUNT_DEBUG
m_assignmentTrace = BNRegisterObjectRefDebugTrace(typeid(T).name());
#endif
}
}
DbgRef(const DbgRef<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
}
}
DbgRef(DbgRef<T>&& other) : m_obj(other.m_obj)
{
other.m_obj = 0;
#ifdef BN_REF_COUNT_DEBUG
m_assignmentTrace = other.m_assignmentTrace;
#endif
}
~DbgRef()
{
if (m_obj)
{
m_obj->Release();
#ifdef BN_REF_COUNT_DEBUG
BNUnregisterObjectRefDebugTrace(typeid(T).name(), m_assignmentTrace);
#endif
}
}
DbgRef<T>& operator=(const 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;
}
DbgRef<T>& operator=(DbgRef<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;
}
DbgRef<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;
}
operator T*() const
{
return m_obj;
}
T* operator->() const
{
return m_obj;
}
T& operator*() const
{
return *m_obj;
}
bool operator!() const
{
return m_obj == NULL;
}
bool operator==(const T* obj) const
{
return T::GetObject(m_obj) == T::GetObject(obj);
}
bool operator==(const DbgRef<T>& obj) const
{
return T::GetObject(m_obj) == T::GetObject(obj.m_obj);
}
bool operator!=(const T* obj) const
{
return T::GetObject(m_obj) != T::GetObject(obj);
}
bool operator!=(const DbgRef<T>& obj) const
{
return T::GetObject(m_obj) != T::GetObject(obj.m_obj);
}
bool operator<(const T* obj) const
{
return T::GetObject(m_obj) < T::GetObject(obj);
}
bool operator<(const DbgRef<T>& obj) const
{
return T::GetObject(m_obj) < T::GetObject(obj.m_obj);
}
T* GetPtr() const
{
return m_obj;
}
};
struct DebugProcess
{
std::uint32_t m_pid {};
std::string m_processName {};
std::string m_commandLine {};
DebugProcess() {}
DebugProcess(std::uint32_t pid) : m_pid(pid) {}
DebugProcess(std::uint32_t pid, std::string name) : m_pid(pid), m_processName(name) {}
DebugProcess(std::uint32_t pid, std::string name, std::string commandLine) :
m_pid(pid), m_processName(name), m_commandLine(commandLine) {}
bool operator==(const DebugProcess& rhs) const
{
return (m_pid == rhs.m_pid) && (m_processName == rhs.m_processName);
}
bool operator!=(const DebugProcess& rhs) const { return !(*this == rhs); }
};
struct DebugThread
{
std::uint32_t m_tid {};
std::uintptr_t m_rip {};
bool m_isFrozen {};
DebugThread() {}
DebugThread(std::uint32_t tid) : m_tid(tid) {}
DebugThread(std::uint32_t tid, std::uintptr_t rip) : m_tid(tid), m_rip(rip) {}
bool operator==(const DebugThread& rhs) const { return (m_tid == rhs.m_tid) && (m_rip == rhs.m_rip); }
bool operator!=(const DebugThread& rhs) const { return !(*this == rhs); }
};
struct DebugFrame
{
size_t m_index;
uint64_t m_pc;
uint64_t m_sp;
uint64_t m_fp;
std::string m_functionName;
uint64_t m_functionStart;
std::string m_module;
DebugFrame() = default;
DebugFrame(size_t index, uint64_t pc, uint64_t sp, uint64_t fp, const std::string& functionName,
uint64_t functionStart, const std::string& module) :
m_index(index),
m_pc(pc), m_sp(sp), m_fp(fp), m_functionName(functionName), m_functionStart(functionStart), m_module(module)
{}
};
struct DebugModule
{
std::string m_name {}, m_short_name {};
std::uintptr_t m_address {};
std::size_t m_size {};
bool m_loaded {};
// These are useful for remote debugging. Paths can be different on the host and guest systems, e.g.,
// /usr/bin/ls, and C:\Users\user\Desktop\ls. So we must compare the base file name, rather than the full path.
bool IsSameBaseModule(const DebugModule& other) const;
bool IsSameBaseModule(const std::string& name) const;
static bool IsSameBaseModule(const std::string& module, const std::string& module2);
static std::string GetPathBaseName(const std::string& path);
};
struct DebugRegister
{
std::string m_name {};
intx::uint512 m_value {};
std::size_t m_width {}, m_registerIndex {};
std::string m_hint {};
};
// Breakpoint types - used to specify the type of breakpoint to set
enum DebugBreakpointType
{
SoftwareBreakpoint = 0, // Default software breakpoint
HardwareExecuteBreakpoint = 1, // Hardware execution breakpoint
HardwareReadBreakpoint = 2, // Hardware read watchpoint
HardwareWriteBreakpoint = 3, // Hardware write watchpoint
HardwareAccessBreakpoint = 4 // Hardware read/write watchpoint
};
struct DebugBreakpoint
{
std::string module;
uint64_t offset;
uint64_t address;
bool enabled;
std::string condition;
DebugBreakpointType type = SoftwareBreakpoint;
size_t size = 1; // Size in bytes for hardware breakpoints/watchpoints (1, 2, 4, 8)
};
struct ModuleNameAndOffset
{
std::string module;
uint64_t offset;
bool operator==(const ModuleNameAndOffset& other) const
{
return (module == other.module) && (offset == other.offset);
}
bool operator!=(const ModuleNameAndOffset& other) const { return !(*this == other); }
bool operator<(const ModuleNameAndOffset& other) const
{
if (module < other.module)
return true;
if (module > other.module)
return false;
return offset < other.offset;
}
bool operator>(const ModuleNameAndOffset& other) const
{
if (module > other.module)
return true;
if (module < other.module)
return false;
return offset > other.offset;
}
};
typedef BNDebuggerEventType DebuggerEventType;
typedef BNDebugStopReason DebugStopReason;
struct TargetStoppedEventData
{
DebugStopReason reason;
std::uint32_t lastActiveThread;
size_t exitCode;
void* data;
};
struct ErrorEventData
{
std::string error;
std::string shortError;
void* data;
};
struct TargetExitedEventData
{
uint64_t exitCode;
};
struct StdoutMessageEventData
{
std::string message;
};
// This should really be a union, but gcc complains...
struct DebuggerEventData
{
TargetStoppedEventData targetStoppedData;
ErrorEventData errorData;
uint64_t absoluteAddress;
ModuleNameAndOffset relativeAddress;
TargetExitedEventData exitData;
StdoutMessageEventData messageData;
};
struct DebuggerEvent
{
DebuggerEventType type;
DebuggerEventData data;
};
struct DebuggerUICallbacks
{
std::function<void(uint64_t base)> rebaseBinaryViewImpl;
BNDebuggerUICallbacks m_callbacks;
BNDebuggerUICallbacks* GetCallbacks() { return &m_callbacks; }
DebuggerUICallbacks();
};
// TTD (Time Travel Debugging) structures
enum TTDMemoryAccessType
{
TTDMemoryRead = 1,
TTDMemoryWrite = 2,
TTDMemoryExecute = 4
};
struct TTDPosition
{
uint64_t sequence;
uint64_t step;
TTDPosition() : sequence(0), step(0) {}
TTDPosition(uint64_t seq, uint64_t st) : sequence(seq), step(st) {}
bool operator==(const TTDPosition& other) const
{
return sequence == other.sequence && step == other.step;
}
bool operator<(const TTDPosition& other) const
{
if (sequence < other.sequence)
return true;
if (sequence > other.sequence)
return false;
return step < other.step;
}
};
struct TTDMemoryEvent
{
std::string eventType; // Event type (e.g., "MemoryAccess")
uint32_t threadId; // Thread ID that performed the access
uint32_t uniqueThreadId; // Unique thread identifier
TTDPosition timeStart; // Position when event started
TTDPosition timeEnd; // Position when event ended
TTDMemoryAccessType accessType; // Type of memory access (parsed from object)
uint64_t address; // Memory address accessed
uint64_t size; // Size of memory access
uint64_t memoryAddress; // Memory address (may be same as address)
uint64_t instructionAddress; // IP - Address of instruction that caused the access
uint64_t value; // Value that was read/written/executed
TTDMemoryEvent() : threadId(0), uniqueThreadId(0), accessType(TTDMemoryRead), address(0), size(0), memoryAddress(0), instructionAddress(0), value(0) {}
};
struct TTDPositionRangeIndexedMemoryEvent{
TTDPosition position; // Position of the memory event
uint32_t threadId; // Thread ID that performed the access
uint32_t uniqueThreadId; // Unique thread ID that performed the access
uint64_t address; // Memory address accessed
uint64_t instructionAddress; // Instruction pointer at time of access
uint64_t size; // Size of memory access
TTDMemoryAccessType accessType; // Type of memory access (parsed from object)
uint64_t value; // Value that was read/written/executed
uint8_t data[8]; // The next 8 bytes of data at the memory address
TTDPositionRangeIndexedMemoryEvent() : threadId(0), uniqueThreadId(0), address(0), instructionAddress(0), size(0), accessType(TTDMemoryRead), value(0)
{
memset(data, 0, sizeof(data));
}
};
struct TTDCallEvent
{
std::string eventType; // Event type (always "Call" for TTD.Calls objects)
uint32_t threadId; // OS thread ID of thread that made the call
uint32_t uniqueThreadId; // Unique ID for the thread across the trace
std::string function; // Symbolic name of the function
uint64_t functionAddress; // Function's address in memory
uint64_t returnAddress; // Instruction to return to after the call
uint64_t returnValue; // Return value of the function (if not void)
bool hasReturnValue; // Whether the function has a return value
std::vector<std::string> parameters; // Array containing parameters passed to the function
TTDPosition timeStart; // Position when call started
TTDPosition timeEnd; // Position when call ended
TTDCallEvent() : threadId(0), uniqueThreadId(0), functionAddress(0), returnAddress(0), returnValue(0), hasReturnValue(false) {}
};
// TTD Event Types - bitfield flags for filtering events
enum TTDEventType
{
TTDEventNone = 0,
TTDEventThreadCreated = 1,
TTDEventThreadTerminated = 2,
TTDEventModuleLoaded = 4,
TTDEventModuleUnloaded = 8,
TTDEventException = 16,
TTDEventAll = TTDEventThreadCreated | TTDEventThreadTerminated | TTDEventModuleLoaded | TTDEventModuleUnloaded | TTDEventException
};
// TTD Module - information about modules that were loaded/unloaded during trace
struct TTDModule
{
std::string name; // Name and path of the module
uint64_t address; // Address where the module was loaded
uint64_t size; // Size of the module in bytes
uint32_t checksum; // Checksum of the module
uint32_t timestamp; // Timestamp of the module
TTDModule() : address(0), size(0), checksum(0), timestamp(0) {}
};
// TTD Thread - information about threads and their lifetime during trace
struct TTDThread
{
uint32_t uniqueId; // Unique ID for the thread across the trace
uint32_t id; // TID of the thread
TTDPosition lifetimeStart; // Lifetime start position
TTDPosition lifetimeEnd; // Lifetime end position
TTDPosition activeTimeStart; // Active time start position
TTDPosition activeTimeEnd; // Active time end position
TTDThread() : uniqueId(0), id(0) {}
};
// TTD Exception Types
enum TTDExceptionType
{
TTDExceptionSoftware,
TTDExceptionHardware
};
// TTD Exception - information about exceptions that occurred during trace
struct TTDException
{
TTDExceptionType type; // Type of exception (Software/Hardware)
uint64_t programCounter; // Instruction where exception was thrown
uint32_t code; // Exception code
uint32_t flags; // Exception flags
uint64_t recordAddress; // Where in memory the exception record is found
TTDPosition position; // Position where exception occurred
TTDException() : type(TTDExceptionSoftware), programCounter(0), code(0), flags(0), recordAddress(0) {}
};
// TTD Event - represents important events that happened during trace
struct TTDEvent
{
TTDEventType type; // Type of event
TTDPosition position; // Position where event occurred
// Optional child objects - existence depends on event type
std::optional<TTDModule> module; // For ModuleLoaded/ModuleUnloaded events
std::optional<TTDThread> thread; // For ThreadCreated/ThreadTerminated events
std::optional<TTDException> exception; // For Exception events
TTDEvent() : type(TTDEventThreadCreated) {}
TTDEvent(TTDEventType eventType) : type(eventType) {}
};
struct TTDBookmark
{
TTDPosition position;
uint64_t viewAddress;
std::string note;
TTDBookmark() : viewAddress(0) {}
TTDBookmark(const TTDPosition& pos, const std::string& n = "", uint64_t addr = 0)
: position(pos), viewAddress(addr), note(n) {}
};
struct TTDStringEntry
{
uint64_t id;
std::string data;
uint64_t address;
uint64_t size;
TTDPosition firstAccess;
TTDPosition lastAccess;
std::string encoding;
TTDStringEntry() : id(0), address(0), size(0) {}
};
typedef BNDebugAdapterConnectionStatus DebugAdapterConnectionStatus;
typedef BNDebugAdapterTargetStatus DebugAdapterTargetStatus;
class DebuggerController :
public DbgCoreRefCountObject<BNDebuggerController, BNDebuggerNewControllerReference, BNDebuggerFreeController>
{
struct DebuggerEventCallbackObject
{
std::function<void(const DebuggerEvent&)> action;
};
// Map callback indices to their respective objects
std::unordered_map<size_t, DebuggerEventCallbackObject*> m_callbackObjects;
public:
DebuggerController(BNDebuggerController* controller);
~DebuggerController();
static DbgRef<DebuggerController> GetController(Ref<BinaryNinja::BinaryView> data);
static bool ControllerExists(Ref<BinaryNinja::BinaryView> data);
static DbgRef<DebuggerController> GetController(Ref<BinaryNinja::FileMetadata> file);
static bool ControllerExists(Ref<BinaryNinja::FileMetadata> file);
void Destroy();
Ref<BinaryView> GetData();
void SetData(const Ref<BinaryView>& data);
Ref<Architecture> GetRemoteArchitecture();
bool IsConnected();
bool IsConnectedToDebugServer();
bool IsRunning();
uint64_t StackPointer();
DataBuffer ReadMemory(std::uintptr_t address, std::size_t size);
bool WriteMemory(std::uintptr_t address, const DataBuffer& buffer);
std::vector<DebugProcess> GetProcessList();
std::uint32_t GetActivePID();
std::vector<DebugThread> GetThreads();
DebugThread GetActiveThread();
void SetActiveThread(const DebugThread& thread);
std::vector<DebugFrame> GetFramesOfThread(uint32_t tid);
bool SuspendThread(std::uint32_t tid);
bool ResumeThread(std::uint32_t tid);
std::vector<DebugModule> GetModules();
std::vector<DebugRegister> GetRegisters();
intx::uint512 GetRegisterValue(const std::string& name);
bool SetRegisterValue(const std::string& name, const intx::uint512& value);
// target control
bool Launch();
BNDebugStopReason LaunchAndWait();
bool Execute();
void Restart();
void Quit();
void QuitAndWait();
bool Connect();
DebugStopReason ConnectAndWait();
bool ConnectToDebugServer();
bool DisconnectDebugServer();
void Detach();
// Convenience function, either launch the target process or connect to a remote, depending on the selected
// adapter
void LaunchOrConnect();
bool Attach();
DebugStopReason AttachAndWait();
bool Go();
bool GoReverse();
bool StepInto(BNFunctionGraphType il = NormalFunctionGraph);
bool StepIntoReverse(BNFunctionGraphType il = NormalFunctionGraph);
bool StepOver(BNFunctionGraphType il = NormalFunctionGraph);
bool StepOverReverse(BNFunctionGraphType il = NormalFunctionGraph);
bool StepReturn();
bool StepReturnReverse();
bool RunTo(uint64_t remoteAddresses);
bool RunTo(const std::vector<uint64_t>& remoteAddresses);
bool RunToReverse(uint64_t remoteAddresses);
bool RunToReverse(const std::vector<uint64_t>& remoteAddresses);
void Pause();
DebugStopReason GoAndWait();
DebugStopReason GoReverseAndWait();
DebugStopReason StepIntoAndWait(BNFunctionGraphType il = NormalFunctionGraph);
DebugStopReason StepIntoReverseAndWait(BNFunctionGraphType il = NormalFunctionGraph);
DebugStopReason StepOverAndWait(BNFunctionGraphType il = NormalFunctionGraph);
DebugStopReason StepOverReverseAndWait(BNFunctionGraphType il);
DebugStopReason StepReturnAndWait();
DebugStopReason StepReturnReverseAndWait();
DebugStopReason RunToAndWait(uint64_t remoteAddresses);
DebugStopReason RunToAndWait(const std::vector<uint64_t>& remoteAddresses);
DebugStopReason RunToReverseAndWait(uint64_t remoteAddresses);
DebugStopReason RunToReverseAndWait(const std::vector<uint64_t>& remoteAddresses);
DebugStopReason PauseAndWait();
DebugStopReason RestartAndWait();
std::string GetAdapterType();
void SetAdapterType(const std::string& adapter);
DebugAdapterConnectionStatus GetConnectionStatus();
DebugAdapterTargetStatus GetTargetStatus();
std::string GetRemoteHost();
uint32_t GetRemotePort();
std::string GetInputFile();
std::string GetExecutablePath();
std::string GetWorkingDirectory();
bool GetRequestTerminalEmulator();
std::string GetCommandLineArguments();
int32_t GetPIDAttach();
void SetInputFile(const std::string& path);
void SetExecutablePath(const std::string& path);
void SetWorkingDirectory(const std::string& directory);
void SetCommandLineArguments(const std::string& arguments);
void SetRemoteHost(const std::string& host);
void SetRemotePort(uint32_t port);
void SetRequestTerminalEmulator(bool requested);
void SetPIDAttach(int32_t pid);
std::vector<DebugBreakpoint> GetBreakpoints();
void DeleteBreakpoint(uint64_t address);
void DeleteBreakpoint(const ModuleNameAndOffset& breakpoint);
void AddBreakpoint(uint64_t address);
void AddBreakpoint(const ModuleNameAndOffset& breakpoint);
void EnableBreakpoint(uint64_t address);
void EnableBreakpoint(const ModuleNameAndOffset& breakpoint);
void DisableBreakpoint(uint64_t address);
void DisableBreakpoint(const ModuleNameAndOffset& breakpoint);
bool ContainsBreakpoint(uint64_t address);
bool ContainsBreakpoint(const ModuleNameAndOffset& breakpoint);
bool SetBreakpointCondition(uint64_t address, const std::string& condition);
bool SetBreakpointCondition(const ModuleNameAndOffset& address, const std::string& condition);
std::string GetBreakpointCondition(uint64_t address);
std::string GetBreakpointCondition(const ModuleNameAndOffset& address);
// Hardware breakpoint and watchpoint support - absolute address
bool AddHardwareBreakpoint(uint64_t address, DebugBreakpointType type, size_t size = 1);
bool RemoveHardwareBreakpoint(uint64_t address, DebugBreakpointType type, size_t size = 1);
bool EnableHardwareBreakpoint(uint64_t address, DebugBreakpointType type, size_t size = 1);
bool DisableHardwareBreakpoint(uint64_t address, DebugBreakpointType type, size_t size = 1);
// Hardware breakpoint and watchpoint support - module+offset (ASLR-safe)
bool AddHardwareBreakpoint(const ModuleNameAndOffset& location, DebugBreakpointType type, size_t size = 1);
bool RemoveHardwareBreakpoint(const ModuleNameAndOffset& location, DebugBreakpointType type, size_t size = 1);
bool EnableHardwareBreakpoint(const ModuleNameAndOffset& location, DebugBreakpointType type, size_t size = 1);
bool DisableHardwareBreakpoint(const ModuleNameAndOffset& location, DebugBreakpointType type, size_t size = 1);
uint64_t IP();
uint64_t GetLastIP();
bool SetIP(uint64_t address);
uint32_t GetExitCode();
uint64_t RelativeAddressToAbsolute(const ModuleNameAndOffset& address);
ModuleNameAndOffset AbsoluteAddressToRelative(uint64_t address);
// rebasing
bool RebaseToRemoteBase();
bool RebaseToAddress(uint64_t address);
bool GetRemoteBase(uint64_t& address);
size_t RegisterEventCallback(
std::function<void(const DebuggerEvent& event)> callback, const std::string& name = "");
void RecordTrace();
static void DebuggerEventCallback(void* ctxt, BNDebuggerEvent* view);
void RemoveEventCallback(size_t index);
void SetDebuggerUICallbacks(DebuggerUICallbacks* cb);
void WriteStdin(const std::string& msg);
std::string InvokeBackendCommand(const std::string& command);
static std::string GetDebugStopReasonString(DebugStopReason reason);
DebugStopReason StopReason();
BinaryNinja::Ref<Metadata> GetAdapterProperty(const std::string& name);
bool SetAdapterProperty(const std::string& name, const BinaryNinja::Ref<Metadata>& value);
bool ActivateDebugAdapter();
std::string GetAddressInformation(intx::uint512 address);
bool IsFirstLaunch();
bool IsFirstConnect();
bool IsFirstConnectToDebugServer();
bool IsFirstAttach();
bool IsTTD();
// TTD Memory Analysis Methods
std::vector<TTDMemoryEvent> GetTTDMemoryAccessForAddress(uint64_t address, uint64_t endAddress, TTDMemoryAccessType accessType = TTDMemoryRead);
std::vector<TTDPositionRangeIndexedMemoryEvent> GetTTDMemoryAccessForPositionRange(uint64_t startAddress, uint64_t endAddress, TTDMemoryAccessType accessType, const TTDPosition startTime, const TTDPosition endTime);
std::vector<TTDCallEvent> GetTTDCallsForSymbols(const std::string& symbols, uint64_t startReturnAddress = 0, uint64_t endReturnAddress = 0);
std::vector<TTDEvent> GetTTDEvents(TTDEventType eventType);
std::vector<TTDEvent> GetAllTTDEvents();
TTDPosition GetCurrentTTDPosition();
bool SetTTDPosition(const TTDPosition& position);
std::pair<bool, TTDMemoryEvent> GetTTDNextMemoryAccess(uint64_t address, uint64_t size, TTDMemoryAccessType accessType);
std::pair<bool, TTDMemoryEvent> GetTTDPrevMemoryAccess(uint64_t address, uint64_t size, TTDMemoryAccessType accessType);
std::vector<TTDStringEntry> GetTTDStrings(const std::string& pattern = "", uint64_t maxResults = 0);
// TTD Position History Navigation
bool TTDNavigateBack();
bool TTDNavigateForward();
bool CanTTDNavigateBack();
bool CanTTDNavigateForward();
void ClearTTDPositionHistory();
// TTD Bookmark Methods
std::vector<TTDBookmark> GetTTDBookmarks();
bool AddTTDBookmark(const TTDPosition& position, const std::string& note = "", uint64_t viewAddress = 0);
bool RemoveTTDBookmark(const TTDPosition& position);
bool UpdateTTDBookmark(const TTDPosition& position, const std::string& note, uint64_t viewAddress);
void ClearTTDBookmarks();
// TTD Code Coverage Analysis Methods
bool IsInstructionExecuted(uint64_t address);
bool RunCodeCoverageAnalysis(uint64_t startAddress, uint64_t endAddress, TTDPosition startTime, TTDPosition endTime);
size_t GetInstructionExecutionCount(uint64_t address);
size_t GetExecutedInstructionCount() const;
bool SaveCodeCoverageToFile(const std::string& filePath) const;
bool LoadCodeCoverageFromFile(const std::string& filePath);
void PostDebuggerEvent(const DebuggerEvent& event);
bool RemoveDebuggerMemoryRegion();
bool ReAddDebuggerMemoryRegion();
uint64_t GetViewFileSegmentsStart();
bool ComputeExprValue(const Ref<LowLevelILFunction>& func, const LowLevelILInstruction& expr,
intx::uint512 & value);
bool ComputeExprValue(const Ref<MediumLevelILFunction>& func, const MediumLevelILInstruction& expr,
intx::uint512 & value);
bool ComputeExprValue(const Ref<HighLevelILFunction>& func, const HighLevelILInstruction& expr,
intx::uint512 & value);
bool GetVariableValue(Variable& var, uint64_t address, size_t size, intx::uint512& value);
Ref<Settings> GetAdapterSettings();
bool FunctionExistsInOldView(uint64_t address);
};
class DebugAdapterType : public DbgRefCountObject<BNDebugAdapterType>
{
public:
DebugAdapterType(BNDebugAdapterType* adapterType);
static DebugAdapterType* GetByName(const std::string& name);
bool CanExecute(Ref<BinaryView> data);
bool CanConnect(Ref<BinaryView> data);
static std::vector<std::string> GetAvailableAdapters(Ref<BinaryView> data);
};
// WinDbg Installer API (Windows only, stubs on other platforms)
struct InstallResult
{
bool success;
std::string errorMessage; // Empty if success, otherwise describes the error
InstallResult() : success(false) {}
InstallResult(bool s, const std::string& err = "") : success(s), errorMessage(err) {}
};
InstallResult InstallWinDbg(const std::string& installPath = "", bool isUpdate = false);
bool IsWinDbgInstalled(const std::string& installPath = "");
std::string GetWinDbgInstallerPath();
std::string GetWinDbgInstalledVersion(const std::string& installPath = "");
std::string GetWinDbgLatestVersion();
}; // namespace BinaryNinjaDebuggerAPI