#ifndef LLDB_TOOLS_LLDB_DAP_DAP_H
#define LLDB_TOOLS_LLDB_DAP_DAP_H
#include "llvm/Config/llvm-config.h"
#include <atomic>
#include <condition_variable>
#include <cstdio>
#include <future>
#include <iosfwd>
#include <map>
#include <optional>
#include <set>
#include <thread>
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
#include "lldb/API/SBAttachInfo.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBBreakpointLocation.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBCommunication.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFormat.h"
#include "lldb/API/SBHostOS.h"
#include "lldb/API/SBInstruction.h"
#include "lldb/API/SBInstructionList.h"
#include "lldb/API/SBLanguageRuntime.h"
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBLineEntry.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "ExceptionBreakpoint.h"
#include "FunctionBreakpoint.h"
#include "IOStream.h"
#include "ProgressEvent.h"
#include "RunInTerminal.h"
#include "SourceBreakpoint.h"
#define VARREF_LOCALS (int64_t)1
#define VARREF_GLOBALS (int64_t)2
#define VARREF_REGS (int64_t)3
#define VARREF_FIRST_VAR_IDX (int64_t)4
#define NO_TYPENAME "<no-type>"
namespace lldb_dap {
typedef llvm::DenseMap<uint32_t, SourceBreakpoint> SourceBreakpointMap;
typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
enum class OutputType { Console, Stdout, Stderr, Telemetry };
enum DAPBroadcasterBits {
eBroadcastBitStopEventThread = 1u << 0,
eBroadcastBitStopProgressThread = 1u << 1
};
typedef void (*RequestCallback)(const llvm::json::Object &command);
typedef void (*ResponseCallback)(llvm::Expected<llvm::json::Value> value);
enum class PacketStatus {
Success = 0,
EndOfFile,
JSONMalformed,
JSONNotObject
};
enum class ReplMode { Variable = 0, Command, Auto };
enum class ExpressionContext {
Variable = 0,
Command,
};
struct Variables {
static constexpr int64_t PermanentVariableStartIndex = (1ll << 32);
lldb::SBValueList locals;
lldb::SBValueList globals;
lldb::SBValueList registers;
int64_t next_temporary_var_ref{VARREF_FIRST_VAR_IDX};
int64_t next_permanent_var_ref{PermanentVariableStartIndex};
llvm::DenseMap<int64_t, lldb::SBValue> expandable_variables;
llvm::DenseMap<int64_t, lldb::SBValue> expandable_permanent_variables;
static bool IsPermanentVariableReference(int64_t var_ref);
int64_t GetNewVariableReference(bool is_permanent);
lldb::SBValue GetVariable(int64_t var_ref) const;
int64_t InsertExpandableVariable(lldb::SBValue variable, bool is_permanent);
void Clear();
};
struct StartDebuggingRequestHandler : public lldb::SBCommandPluginInterface {
bool DoExecute(lldb::SBDebugger debugger, char **command,
lldb::SBCommandReturnObject &result) override;
};
struct ReplModeRequestHandler : public lldb::SBCommandPluginInterface {
bool DoExecute(lldb::SBDebugger debugger, char **command,
lldb::SBCommandReturnObject &result) override;
};
struct DAP {
std::string debug_adaptor_path;
InputStream input;
OutputStream output;
lldb::SBDebugger debugger;
lldb::SBTarget target;
Variables variables;
lldb::SBBroadcaster broadcaster;
std::thread event_thread;
std::thread progress_event_thread;
std::unique_ptr<std::ofstream> log;
llvm::StringMap<SourceBreakpointMap> source_breakpoints;
FunctionBreakpointMap function_breakpoints;
std::optional<std::vector<ExceptionBreakpoint>> exception_breakpoints;
llvm::once_flag init_exception_breakpoints_flag;
std::vector<std::string> pre_init_commands;
std::vector<std::string> init_commands;
std::vector<std::string> pre_run_commands;
std::vector<std::string> post_run_commands;
std::vector<std::string> exit_commands;
std::vector<std::string> stop_commands;
std::vector<std::string> terminate_commands;
llvm::DenseMap<lldb::addr_t, std::string> step_in_targets;
std::optional<llvm::json::Object> last_launch_or_attach_request;
lldb::tid_t focus_tid;
bool disconnecting = false;
llvm::once_flag terminated_event_flag;
bool stop_at_entry;
bool is_attach;
bool enable_auto_variable_summaries;
bool enable_synthetic_child_debugging;
lldb::pid_t restarting_process_id;
bool configuration_done_sent;
std::map<std::string, RequestCallback> request_handlers;
bool waiting_for_run_in_terminal;
ProgressEventReporter progress_event_reporter;
llvm::DenseSet<lldb::tid_t> thread_ids;
uint32_t reverse_request_seq;
std::mutex call_mutex;
std::map<int , ResponseCallback >
inflight_reverse_requests;
StartDebuggingRequestHandler start_debugging_request_handler;
ReplModeRequestHandler repl_mode_request_handler;
ReplMode repl_mode;
std::string command_escape_prefix = "`";
lldb::SBFormat frame_format;
lldb::SBFormat thread_format;
DAP();
~DAP();
DAP(const DAP &rhs) = delete;
void operator=(const DAP &rhs) = delete;
ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
void SendJSON(const llvm::json::Value &json);
std::string ReadJSON();
void SendOutput(OutputType o, const llvm::StringRef output);
void SendProgressEvent(uint64_t progress_id, const char *message,
uint64_t completed, uint64_t total);
void __attribute__((format(printf, 3, 4)))
SendFormattedOutput(OutputType o, const char *format, ...);
static int64_t GetNextSourceReference();
ExceptionBreakpoint *GetExceptionBPFromStopReason(lldb::SBThread &thread);
lldb::SBThread GetLLDBThread(const llvm::json::Object &arguments);
lldb::SBFrame GetLLDBFrame(const llvm::json::Object &arguments);
llvm::json::Value CreateTopLevelScopes();
void PopulateExceptionBreakpoints();
ExpressionContext DetectExpressionContext(lldb::SBFrame frame,
std::string &expression);
bool RunLLDBCommands(llvm::StringRef prefix,
llvm::ArrayRef<std::string> commands);
llvm::Error RunAttachCommands(llvm::ArrayRef<std::string> attach_commands);
llvm::Error RunLaunchCommands(llvm::ArrayRef<std::string> launch_commands);
llvm::Error RunPreInitCommands();
llvm::Error RunInitCommands();
llvm::Error RunPreRunCommands();
void RunPostRunCommands();
void RunStopCommands();
void RunExitCommands();
void RunTerminateCommands();
lldb::SBTarget CreateTargetFromArguments(const llvm::json::Object &arguments,
lldb::SBError &error);
void SetTarget(const lldb::SBTarget target);
const std::map<std::string, RequestCallback> &GetRequestHandlers();
PacketStatus GetNextObject(llvm::json::Object &object);
bool HandleObject(const llvm::json::Object &object);
llvm::Error Loop();
void SendReverseRequest(llvm::StringRef command, llvm::json::Value arguments,
ResponseCallback callback);
void RegisterRequestCallback(std::string request, RequestCallback callback);
void WillContinue() { variables.Clear(); }
lldb::SBError WaitForProcessToStop(uint32_t seconds);
void SetFrameFormat(llvm::StringRef format);
void SetThreadFormat(llvm::StringRef format);
private:
void SendJSON(const std::string &json_str);
};
extern DAP g_dap;
}
#endif