@@ -51,23 +51,24 @@ namespace xcpp
51
51
, m_lldb_host(" 127.0.0.1" )
52
52
, m_lldb_port(" " )
53
53
, m_debugger_config(debugger_config)
54
- , m_is_running(false )
55
54
{
56
55
// Register request handlers
57
56
register_request_handler (
58
57
" inspectVariables" ,
59
58
std::bind (&debugger::inspect_variables_request, this , _1),
60
59
false
61
60
);
62
- register_request_handler (" stackTrace" , std::bind (&debugger::stack_trace_request, this , _1), false );
63
61
register_request_handler (" attach" , std::bind (&debugger::attach_request, this , _1), true );
64
62
register_request_handler (
65
63
" configurationDone" ,
66
64
std::bind (&debugger::configuration_done_request, this , _1),
67
65
true
68
66
);
67
+ register_request_handler (" richInspectVariables" , std::bind (&debugger::rich_inspect_variables_request, this , _1), true );
69
68
register_request_handler (" setBreakpoints" , std::bind (&debugger::set_breakpoints_request, this , _1), true );
70
69
register_request_handler (" dumpCell" , std::bind (&debugger::dump_cell_request, this , _1), true );
70
+ register_request_handler (" copyToGlobals" , std::bind (&debugger::copy_to_globals_request, this , _1), true );
71
+ register_request_handler (" stackTrace" , std::bind (&debugger::stack_trace_request, this , _1), true );
71
72
72
73
m_interpreter = reinterpret_cast <xcpp::interpreter*>(
73
74
debugger_config[" interpreter_ptr" ].get <std::uintptr_t >()
@@ -98,7 +99,12 @@ namespace xcpp
98
99
log << m_debugger_config.dump (4 ) << ' \n ' ;
99
100
}
100
101
101
- std::vector<std::string> lldb_args = {" lldb-dap" , " --port" , m_lldb_port};
102
+ // std::vector<std::string> lldb_args = {"/Users/abhinavkumar/Desktop/Coding/CERN_HSF_COMPILER_RESEARCH/llvm-project-lldb/build/bin/lldb-dap", "--connection", "listen://localhost:" + m_lldb_port};
103
+ std::vector<std::string> lldb_args = {
104
+ " lldb-dap" ,
105
+ " --port" ,
106
+ m_lldb_port
107
+ };
102
108
103
109
std::string log_dir = xeus::get_temp_directory_path () + " /xcpp_debug_logs_"
104
110
+ std::to_string (xeus::get_current_pid ());
@@ -148,6 +154,7 @@ namespace xcpp
148
154
return false ;
149
155
}
150
156
m_is_running = true ;
157
+ m_copy_to_globals_available = true ;
151
158
return true ;
152
159
}
153
160
else
@@ -173,7 +180,7 @@ namespace xcpp
173
180
174
181
std::string lldb_endpoint = " tcp://" + m_lldb_host + " :" + m_lldb_port;
175
182
std::thread client (
176
- &xdebuglldb_client ::start_debugger,
183
+ &xdap_tcp_client ::start_debugger,
177
184
p_debuglldb_client,
178
185
lldb_endpoint,
179
186
publisher_end_point,
@@ -198,15 +205,21 @@ namespace xcpp
198
205
{" type" , " request" },
199
206
{" command" , " attach" },
200
207
{" arguments" ,
201
- {{" pid" , jit_process_pid}, {" initCommands" , {" settings set plugin.jit-loader.gdb.enable on" }}}}
208
+ {
209
+ {" pid" , jit_process_pid},
210
+ {" stopOnEntry" , true },
211
+ {" initCommands" , {" settings set plugin.jit-loader.gdb.enable on" }}
212
+ }
213
+ }
202
214
};
215
+ log_debug (" [debugger::attach_request] Attach request sent:\n " + attach_request.dump (4 ));
203
216
nl::json reply = forward_message (attach_request);
204
217
return reply;
205
218
}
206
219
207
220
nl::json debugger::inspect_variables_request (const nl::json& message)
208
221
{
209
- log_debug (" [debugger] Inspect variable not implemented." );
222
+ log_debug (" [debugger::inspect_variables_request ] Inspect variable not implemented." );
210
223
nl::json inspect_request = {
211
224
{" seq" , message[" seq" ]},
212
225
{" type" , " request" },
@@ -227,37 +240,99 @@ namespace xcpp
227
240
m_breakpoint_list.insert (std::make_pair (std::move (source), std::move (bp_list)));
228
241
nl::json mod_message = message;
229
242
mod_message[" arguments" ][" source" ][" path" ] = sequential_source;
230
- log_debug (" Set breakpoints request received :\n " + mod_message.dump (4 ));
243
+ log_debug (" [debugger::set_breakpoints_request] Set breakpoints request sent :\n " + mod_message.dump (4 ));
231
244
nl::json breakpoint_reply = forward_message (mod_message);
232
- log_debug (" Set breakpoints reply sent:\n " + breakpoint_reply.dump (4 ));
245
+ if (breakpoint_reply.contains (" body" ) && breakpoint_reply[" body" ].contains (" breakpoints" ))
246
+ {
247
+ for (auto & bp : breakpoint_reply[" body" ][" breakpoints" ])
248
+ {
249
+ if (bp.contains (" source" ) && bp[" source" ].contains (" path" ))
250
+ {
251
+ std::string seq_path = bp[" source" ][" path" ].get <std::string>();
252
+ if (m_sequential_to_hash.find (seq_path) != m_sequential_to_hash.end ())
253
+ {
254
+ bp[" source" ][" path" ] = m_sequential_to_hash[seq_path];
255
+ }
256
+ }
257
+ }
258
+ }
259
+ log_debug (" [debugger::set_breakpoints_request] Set breakpoints reply received:\n " + breakpoint_reply.dump (4 ));
233
260
return breakpoint_reply;
234
261
}
235
262
236
- nl::json debugger::stack_trace_request (const nl::json& message)
263
+ // nl::json debugger::stack_trace_request(const nl::json& message)
264
+ // {
265
+ // log_debug("Stack trace request received:\n" + message.dump(4));
266
+ // nl::json reply = {
267
+ // {"type", "response"},
268
+ // {"request_seq", message["seq"]},
269
+ // {"success", false},
270
+ // {"command", message["command"]},
271
+ // {"message", "stackTrace not implemented"},
272
+ // {"body", {{"stackFrames", {}}}}
273
+ // };
274
+ // return reply;
275
+ // }
276
+
277
+ nl::json debugger::copy_to_globals_request (const nl::json& message)
237
278
{
238
- log_debug (" Stack trace request received:\n " + message.dump (4 ));
239
- nl::json reply = {
240
- {" type" , " response" },
241
- {" request_seq" , message[" seq" ]},
242
- {" success" , false },
243
- {" command" , message[" command" ]},
244
- {" message" , " stackTrace not implemented" },
245
- {" body" , {{" stackFrames" , {}}}}
279
+ // This request cannot be processed if the version of debugpy is lower than 1.6.5.
280
+ log_debug (" [debugger::copy_to_globals_request] Copy to globals request received:\n " + message.dump (4 ));
281
+ if (!m_copy_to_globals_available)
282
+ {
283
+ nl::json reply = {
284
+ {" type" , " response" },
285
+ {" request_seq" , message[" seq" ]},
286
+ {" success" , false },
287
+ {" command" , message[" command" ]},
288
+ {" body" , " The debugpy version must be greater than or equal 1.6.5 to allow copying a variable to the global scope." }
289
+ };
290
+ return reply;
291
+ }
292
+
293
+ std::string src_var_name = message[" arguments" ][" srcVariableName" ].get <std::string>();
294
+ std::string dst_var_name = message[" arguments" ][" dstVariableName" ].get <std::string>();
295
+ int src_frame_id = message[" arguments" ][" srcFrameId" ].get <int >();
296
+
297
+ // It basically runs a setExpression in the globals dictionary of Python.
298
+ int seq = message[" seq" ].get <int >();
299
+ std::string expression = " globals()['" + dst_var_name + " ']" ;
300
+ nl::json request = {
301
+ {" type" , " request" },
302
+ {" command" , " setExpression" },
303
+ {" seq" , seq+1 },
304
+ {" arguments" , {
305
+ {" expression" , expression},
306
+ {" value" , src_var_name},
307
+ {" frameId" , src_frame_id}
308
+ }}
246
309
};
247
- return reply ;
310
+ return forward_message (request) ;
248
311
}
249
312
313
+
250
314
nl::json debugger::configuration_done_request (const nl::json& message)
251
315
{
252
- log_debug (" Configuration done request received:\n " + message.dump (4 ));
316
+ log_debug (" [debugger::configuration_done_request] Configuration done request received:\n " + message.dump (4 ));
253
317
nl::json reply = forward_message (message);
254
- log_debug (" Configuration done reply sent:\n " + reply.dump (4 ));
318
+ log_debug (" [debugger::configuration_done_request] Configuration done reply sent:\n " + reply.dump (4 ));
319
+ // send continue reauest on thread that is stopped
320
+ auto stopped_threads = base_type::get_stopped_threads ();
321
+ nl::json continue_request = {
322
+ {" type" , " request" },
323
+ {" command" , " continue" },
324
+ {" seq" , message[" seq" ].get <int >() + 1 },
325
+ {" arguments" , {{" threadId" , *stopped_threads.begin ()}}}
326
+ };
327
+ log_debug (" [debugger::configuration_done_request] Sending continue request:\n " + continue_request.dump (4 ));
328
+ nl::json continue_reply = forward_message (continue_request);
329
+ log_debug (" [debugger::configuration_done_request] Continue reply received:\n " + continue_reply.dump (4 ));
255
330
return reply;
256
331
}
257
332
258
333
nl::json debugger::variables_request_impl (const nl::json& message)
259
334
{
260
- log_debug (" Variables request received:\n " + message.dump (4 ));
335
+ log_debug (" [debugger::variables_request_impl] Variables request received:\n " + message.dump (4 ));
261
336
nl::json reply = {
262
337
{" type" , " response" },
263
338
{" request_seq" , message[" seq" ]},
@@ -269,6 +344,165 @@ namespace xcpp
269
344
return reply;
270
345
}
271
346
347
+ nl::json debugger::rich_inspect_variables_request (const nl::json& message)
348
+ {
349
+ log_debug (" [debugger::rich_inspect_variables_request] Rich inspect variables request received:\n " + message.dump (4 ));
350
+ return {};
351
+ // nl::json reply = {
352
+ // {"type", "response"},
353
+ // {"request_seq", message["seq"]},
354
+ // {"success", false},
355
+ // {"command", message["command"]}
356
+ // };
357
+
358
+ // std::string var_name = message["arguments"]["variableName"].get<std::string>();
359
+ // py::str py_var_name = py::str(var_name);
360
+ // bool valid_name = PyUnicode_IsIdentifier(py_var_name.ptr()) == 1;
361
+ // if (!valid_name)
362
+ // {
363
+ // reply["body"] = {
364
+ // {"data", {}},
365
+ // {"metadata", {}}
366
+ // };
367
+ // if (var_name == "special variables" || var_name == "function variables")
368
+ // {
369
+ // reply["success"] = true;
370
+ // }
371
+ // return reply;
372
+ // }
373
+
374
+ // std::string var_repr_data = var_name + "_repr_data";
375
+ // std::string var_repr_metadata = var_name + "_repr_metada";
376
+
377
+ // if (base_type::get_stopped_threads().empty())
378
+ // {
379
+ // // The code did not hit a breakpoint, we use the interpreter
380
+ // // to get the rich representation of the variable
381
+ // std::string code = "from IPython import get_ipython;";
382
+ // code += var_repr_data + ',' + var_repr_metadata + "= get_ipython().display_formatter.format(" + var_name + ")";
383
+ // py::gil_scoped_acquire acquire;
384
+ // exec(py::str(code));
385
+ // }
386
+ // else
387
+ // {
388
+ // // The code has stopped on a breakpoint, we use the setExpression request
389
+ // // to get the rich representation of the variable
390
+ // std::string code = "get_ipython().display_formatter.format(" + var_name + ")";
391
+ // int frame_id = message["arguments"]["frameId"].get<int>();
392
+ // int seq = message["seq"].get<int>();
393
+ // nl::json request = {
394
+ // {"type", "request"},
395
+ // {"command", "evaluate"},
396
+ // {"seq", seq+1},
397
+ // {"arguments", {
398
+ // {"expression", code},
399
+ // {"frameId", frame_id},
400
+ // {"context", "clipboard"}
401
+ // }}
402
+ // };
403
+ // nl::json request_reply = forward_message(request);
404
+ // std::string result = request_reply["body"]["result"];
405
+
406
+ // py::gil_scoped_acquire acquire;
407
+ // std::string exec_code = var_repr_data + ',' + var_repr_metadata + "= eval(str(" + result + "))";
408
+ // exec(py::str(exec_code));
409
+ // }
410
+
411
+ // py::gil_scoped_acquire acquire;
412
+ // py::object variables = py::globals();
413
+ // py::object repr_data = variables[py::str(var_repr_data)];
414
+ // py::object repr_metadata = variables[py::str(var_repr_metadata)];
415
+ // nl::json body = {
416
+ // {"data", {}},
417
+ // {"metadata", {}}
418
+ // };
419
+ // for (const py::handle& key : repr_data)
420
+ // {
421
+ // std::string data_key = py::str(key);
422
+ // body["data"][data_key] = repr_data[key];
423
+ // if (repr_metadata.contains(key))
424
+ // {
425
+ // body["metadata"][data_key] = repr_metadata[key];
426
+ // }
427
+ // }
428
+ // PyDict_DelItem(variables.ptr(), py::str(var_repr_data).ptr());
429
+ // PyDict_DelItem(variables.ptr(), py::str(var_repr_metadata).ptr());
430
+ // reply["body"] = body;
431
+ // reply["success"] = true;
432
+ // return reply;
433
+ }
434
+
435
+ nl::json debugger::stack_trace_request (const nl::json& message)
436
+ {
437
+ int requested_thread_id = message[" arguments" ][" threadId" ];
438
+
439
+ auto stopped_threads = base_type::get_stopped_threads ();
440
+
441
+ if (stopped_threads.empty ()) {
442
+ nl::json error_reply = {
443
+ {" command" , " stackTrace" },
444
+ {" request_seq" , message[" seq" ]},
445
+ {" seq" , message[" seq" ]},
446
+ {" success" , false },
447
+ {" message" , " No threads are currently stopped" },
448
+ {" type" , " response" }
449
+ };
450
+ return error_reply;
451
+ }
452
+
453
+ int actual_thread_id;
454
+ nl::json modified_message = message;
455
+
456
+ if (requested_thread_id == 1 && !stopped_threads.empty ()) {
457
+ actual_thread_id = *stopped_threads.begin ();
458
+ modified_message[" arguments" ][" threadId" ] = actual_thread_id;
459
+ std::clog << " XDEBUGGER: Mapping client thread 1 to actual thread " << actual_thread_id << std::endl;
460
+ }
461
+ else if (stopped_threads.find (requested_thread_id) != stopped_threads.end ()) {
462
+ actual_thread_id = requested_thread_id;
463
+ }
464
+ else {
465
+ actual_thread_id = *stopped_threads.begin ();
466
+ modified_message[" arguments" ][" threadId" ] = actual_thread_id;
467
+ std::clog << " XDEBUGGER: Thread " << requested_thread_id
468
+ << " not found in stopped threads, using " << actual_thread_id << std::endl;
469
+ }
470
+
471
+ for (auto x : stopped_threads)
472
+ {
473
+ log_debug (" Stopped thread ID: " + std::to_string (x));
474
+ }
475
+
476
+ log_debug (" [debugger::stack_trace_request]:\n " + modified_message.dump (4 ));
477
+
478
+ nl::json reply = forward_message (modified_message);
479
+
480
+ if (!reply.contains (" body" ) || !reply[" body" ].contains (" stackFrames" )) {
481
+ return reply;
482
+ }
483
+
484
+ auto & stack_frames = reply[" body" ][" stackFrames" ];
485
+ for (auto it = stack_frames.begin (); it != stack_frames.end (); ++it) {
486
+ if (it->contains (" source" ) && (*it)[" source" ].contains (" path" ) &&
487
+ (*it)[" source" ][" path" ] == " <string>" ) {
488
+ stack_frames.erase (it);
489
+ break ;
490
+ }
491
+ }
492
+
493
+ #ifdef WIN32
494
+ for (auto & frame : stack_frames) {
495
+ if (frame.contains (" source" ) && frame[" source" ].contains (" path" )) {
496
+ std::string path = frame[" source" ][" path" ];
497
+ std::replace (path.begin (), path.end (), ' \\ ' , ' /' );
498
+ frame[" source" ][" path" ] = path;
499
+ }
500
+ }
501
+ #endif
502
+
503
+ return reply;
504
+ }
505
+
272
506
void debugger::stop ()
273
507
{
274
508
std::string controller_end_point = xeus::get_controller_end_point (" debugger" );
@@ -279,6 +513,7 @@ namespace xcpp
279
513
xeus::xdebugger_info debugger::get_debugger_info () const
280
514
{
281
515
// Placeholder debugger info
516
+ log_debug (" [debugger::get_debugger_info] Returning debugger info" );
282
517
return xeus::xdebugger_info (
283
518
xeus::get_tmp_hash_seed (),
284
519
get_tmp_prefix (),
@@ -291,6 +526,7 @@ namespace xcpp
291
526
292
527
nl::json debugger::dump_cell_request (const nl::json& message)
293
528
{
529
+ log_debug (" [debugger::dump_cell_request] Dump cell request received:\n " + message.dump (4 ));
294
530
std::string code;
295
531
try
296
532
{
0 commit comments