//===-- 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", 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