-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathLldbDebugger.cpp
135 lines (114 loc) · 3.65 KB
/
LldbDebugger.cpp
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
#include "LldbDebugger.h"
#include <cassert>
namespace visual_lldb {
using namespace lldb;
const std::string &CodeLocation::getDirectory() const { return directory; }
const std::string &CodeLocation::getFileName() const { return fileName; }
size_t CodeLocation::getLine() const { return lineNumber; }
LldbDebugger::LldbDebugger(const std::string &targetPath) {
SBError error = SBDebugger::InitializeWithErrorHandling();
assert(!error.Fail());
debugger = SBDebugger::Create();
assert(debugger);
target = debugger.CreateTarget(targetPath.c_str());
assert(target);
}
LldbDebugger::~LldbDebugger() {
SBDebugger::Destroy(debugger);
SBDebugger::Terminate();
}
void LldbDebugger::run() {
// Restart the run.
if (process)
process.Destroy();
process = target.LaunchSimple(nullptr, nullptr, ".");
assert(process);
waitForStop();
}
void LldbDebugger::resume() {
assert(process);
process.Continue();
waitForStop();
}
void LldbDebugger::next() {
assert(process);
auto thread = process.GetSelectedThread();
thread.StepOver();
waitForStop();
}
void LldbDebugger::stepDown() {
assert(process);
auto thread = process.GetSelectedThread();
thread.StepInto();
waitForStop();
}
void LldbDebugger::stepUp() {
assert(process);
auto thread = process.GetSelectedThread();
thread.StepOut();
waitForStop();
}
void LldbDebugger::toggleBreakpoint(const std::string &fileName,
size_t lineNumber) {
for (auto it = bps.begin(); it != bps.end(); ++it) {
auto &bp = *it;
auto lineEntry = bp.GetLocationAtIndex(0).GetAddress().GetLineEntry();
auto fileSpec = lineEntry.GetFileSpec();
auto bpFileName =
std::string(fileSpec.GetDirectory()) + '/' + fileSpec.GetFilename();
// The breakpoint exists. Delete it.
if (fileName == bpFileName && lineEntry.GetLine() == lineNumber) {
const break_id_t bpId = bp.GetID();
target.BreakpointDelete(bpId);
bps.erase(it);
return;
}
}
// The breakpoint doesn't exist, add it.
auto bp = target.BreakpointCreateByLocation(fileName.c_str(), lineNumber);
assert(bp);
bps.push_back(std::move(bp));
}
CodeLocation LldbDebugger::getLocation() const {
assert(process);
SBLineEntry lineEntry =
process.GetSelectedThread().GetSelectedFrame().GetLineEntry();
SBFileSpec fileSpec = lineEntry.GetFileSpec();
return CodeLocation(fileSpec.GetDirectory(), fileSpec.GetFilename(),
lineEntry.GetLine());
}
std::vector<SBBreakpoint> &LldbDebugger::getBreakpoints() { return bps; }
SBValueList LldbDebugger::getFrameVariables() {
assert(process);
return process.GetSelectedThread().GetSelectedFrame().GetVariables(
true, true, true, true, DynamicValueType::eNoDynamicValues);
}
bool LldbDebugger::isActive() {
return process && process.GetState() == eStateStopped;
}
bool LldbDebugger::isStopped() {
return process.GetState() == eStateStopped ||
process.GetState() == eStateExited;
}
void LldbDebugger::waitForStop() {
SBListener listener = debugger.GetListener();
process.GetBroadcaster().AddListener(listener,
SBProcess::eBroadcastBitStateChanged);
while (1) {
SBEvent event;
if (listener.WaitForEvent(6, event)) {
if (!event.IsValid())
break;
const uint32_t eventType = event.GetType();
if (!SBProcess::EventIsProcessEvent(event))
continue;
if (eventType != SBProcess::eBroadcastBitStateChanged)
continue;
const StateType state = SBProcess::GetStateFromEvent(event);
if (state == eStateStopped || state == eStateExited)
break;
}
}
assert(isStopped());
}
} // namespace visual_lldb