forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExceptionInfoRequestHandler.cpp
174 lines (169 loc) · 5.89 KB
/
ExceptionInfoRequestHandler.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
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
//===-- ExceptionInfoRequestHandler.cpp -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DAP.h"
#include "EventHelper.h"
#include "JSONUtils.h"
#include "RequestHandler.h"
#include "lldb/API/SBStream.h"
namespace lldb_dap {
// "ExceptionInfoRequest": {
// "allOf": [ { "$ref": "#/definitions/Request" }, {
// "type": "object",
// "description": "Retrieves the details of the exception that
// caused this event to be raised. Clients should only call this request if
// the corresponding capability `supportsExceptionInfoRequest` is true.",
// "properties": {
// "command": {
// "type": "string",
// "enum": [ "exceptionInfo" ]
// },
// "arguments": {
// "$ref": "#/definitions/ExceptionInfoArguments"
// }
// },
// "required": [ "command", "arguments" ]
// }]
// },
// "ExceptionInfoArguments": {
// "type": "object",
// "description": "Arguments for `exceptionInfo` request.",
// "properties": {
// "threadId": {
// "type": "integer",
// "description": "Thread for which exception information should be
// retrieved."
// }
// },
// "required": [ "threadId" ]
// },
// "ExceptionInfoResponse": {
// "allOf": [ { "$ref": "#/definitions/Response" }, {
// "type": "object",
// "description": "Response to `exceptionInfo` request.",
// "properties": {
// "body": {
// "type": "object",
// "properties": {
// "exceptionId": {
// "type": "string",
// "description": "ID of the exception that was thrown."
// },
// "description": {
// "type": "string",
// "description": "Descriptive text for the exception."
// },
// "breakMode": {
// "$ref": "#/definitions/ExceptionBreakMode",
// "description": "Mode that caused the exception notification to
// be raised."
// },
// "details": {
// "$ref": "#/definitions/ExceptionDetails",
// "description": "Detailed information about the exception."
// }
// },
// "required": [ "exceptionId", "breakMode" ]
// }
// },
// "required": [ "body" ]
// }]
// }
// "ExceptionDetails": {
// "type": "object",
// "description": "Detailed information about an exception that has
// occurred.", "properties": {
// "message": {
// "type": "string",
// "description": "Message contained in the exception."
// },
// "typeName": {
// "type": "string",
// "description": "Short type name of the exception object."
// },
// "fullTypeName": {
// "type": "string",
// "description": "Fully-qualified type name of the exception object."
// },
// "evaluateName": {
// "type": "string",
// "description": "An expression that can be evaluated in the current
// scope to obtain the exception object."
// },
// "stackTrace": {
// "type": "string",
// "description": "Stack trace at the time the exception was thrown."
// },
// "innerException": {
// "type": "array",
// "items": {
// "$ref": "#/definitions/ExceptionDetails"
// },
// "description": "Details of the exception contained by this exception,
// if any."
// }
// }
// },
void ExceptionInfoRequestHandler::operator()(
const llvm::json::Object &request) const {
llvm::json::Object response;
FillResponse(request, response);
const auto *arguments = request.getObject("arguments");
llvm::json::Object body;
lldb::SBThread thread = dap.GetLLDBThread(*arguments);
if (thread.IsValid()) {
auto stopReason = thread.GetStopReason();
if (stopReason == lldb::eStopReasonSignal)
body.try_emplace("exceptionId", "signal");
else if (stopReason == lldb::eStopReasonBreakpoint) {
ExceptionBreakpoint *exc_bp = dap.GetExceptionBPFromStopReason(thread);
if (exc_bp) {
EmplaceSafeString(body, "exceptionId", exc_bp->GetFilter());
EmplaceSafeString(body, "description", exc_bp->GetLabel());
} else {
body.try_emplace("exceptionId", "exception");
}
} else {
body.try_emplace("exceptionId", "exception");
}
if (!ObjectContainsKey(body, "description")) {
char description[1024];
if (thread.GetStopDescription(description, sizeof(description))) {
EmplaceSafeString(body, "description", std::string(description));
}
}
body.try_emplace("breakMode", "always");
auto exception = thread.GetCurrentException();
if (exception.IsValid()) {
llvm::json::Object details;
lldb::SBStream stream;
if (exception.GetDescription(stream)) {
EmplaceSafeString(details, "message", stream.GetData());
}
auto exceptionBacktrace = thread.GetCurrentExceptionBacktrace();
if (exceptionBacktrace.IsValid()) {
lldb::SBStream stream;
exceptionBacktrace.GetDescription(stream);
for (uint32_t i = 0; i < exceptionBacktrace.GetNumFrames(); i++) {
lldb::SBFrame frame = exceptionBacktrace.GetFrameAtIndex(i);
frame.GetDescription(stream);
}
EmplaceSafeString(details, "stackTrace", stream.GetData());
}
body.try_emplace("details", std::move(details));
}
// auto excInfoCount = thread.GetStopReasonDataCount();
// for (auto i=0; i<excInfoCount; ++i) {
// uint64_t exc_data = thread.GetStopReasonDataAtIndex(i);
// }
} else {
response["success"] = llvm::json::Value(false);
}
response.try_emplace("body", std::move(body));
dap.SendJSON(llvm::json::Value(std::move(response)));
}
} // namespace lldb_dap