Document array indexing for Python gdb.Value
[binutils-gdb.git] / gdb / amd-dbgapi-target.c
1 /* Target used to communicate with the AMD Debugger API.
2
3 Copyright (C) 2019-2023 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21
22 #include "amd-dbgapi-target.h"
23 #include "amdgpu-tdep.h"
24 #include "async-event.h"
25 #include "cli/cli-cmds.h"
26 #include "cli/cli-style.h"
27 #include "inf-loop.h"
28 #include "inferior.h"
29 #include "objfiles.h"
30 #include "observable.h"
31 #include "registry.h"
32 #include "solib.h"
33 #include "target.h"
34
35 /* When true, print debug messages relating to the amd-dbgapi target. */
36
37 static bool debug_amd_dbgapi = false;
38
39 /* Make a copy of S styled in green. */
40
41 static std::string
42 make_green (const char *s)
43 {
44 cli_style_option style (nullptr, ui_file_style::GREEN);
45 string_file sf (true);
46 gdb_printf (&sf, "%ps", styled_string (style.style(), s));
47 return sf.release ();
48 }
49
50 /* Debug module names. "amd-dbgapi" is for the target debug messages (this
51 file), whereas "amd-dbgapi-lib" is for logging messages output by the
52 amd-dbgapi library. */
53
54 static const char *amd_dbgapi_debug_module_unstyled = "amd-dbgapi";
55 static const char *amd_dbgapi_lib_debug_module_unstyled
56 = "amd-dbgapi-lib";
57
58 /* Styled variants of the above. */
59
60 static const std::string amd_dbgapi_debug_module_styled
61 = make_green (amd_dbgapi_debug_module_unstyled);
62 static const std::string amd_dbgapi_lib_debug_module_styled
63 = make_green (amd_dbgapi_lib_debug_module_unstyled);
64
65 /* Return the styled or unstyled variant of the amd-dbgapi module name,
66 depending on whether gdb_stdlog can emit colors. */
67
68 static const char *
69 amd_dbgapi_debug_module ()
70 {
71 if (gdb_stdlog->can_emit_style_escape ())
72 return amd_dbgapi_debug_module_styled.c_str ();
73 else
74 return amd_dbgapi_debug_module_unstyled;
75 }
76
77 /* Same as the above, but for the amd-dbgapi-lib module name. */
78
79 static const char *
80 amd_dbgapi_lib_debug_module ()
81 {
82 if (gdb_stdlog->can_emit_style_escape ())
83 return amd_dbgapi_lib_debug_module_styled.c_str ();
84 else
85 return amd_dbgapi_lib_debug_module_unstyled;
86 }
87
88 /* Print an amd-dbgapi debug statement. */
89
90 #define amd_dbgapi_debug_printf(fmt, ...) \
91 debug_prefixed_printf_cond (debug_amd_dbgapi, \
92 amd_dbgapi_debug_module (), \
93 fmt, ##__VA_ARGS__)
94
95 /* Print amd-dbgapi start/end debug statements. */
96
97 #define AMD_DBGAPI_SCOPED_DEBUG_START_END(fmt, ...) \
98 scoped_debug_start_end (debug_infrun, amd_dbgapi_debug_module (), \
99 fmt, ##__VA_ARGS__)
100
101 /* inferior_created observer token. */
102
103 static gdb::observers::token amd_dbgapi_target_inferior_created_observer_token;
104
105 const gdb::observers::token &
106 get_amd_dbgapi_target_inferior_created_observer_token ()
107 {
108 return amd_dbgapi_target_inferior_created_observer_token;
109 }
110
111
112 /* Big enough to hold the size of the largest register in bytes. */
113 #define AMDGPU_MAX_REGISTER_SIZE 256
114
115 /* amd-dbgapi-specific inferior data. */
116
117 struct amd_dbgapi_inferior_info
118 {
119 explicit amd_dbgapi_inferior_info (inferior *inf)
120 : inf (inf)
121 {}
122
123 /* Backlink to inferior. */
124 inferior *inf;
125
126 /* The amd_dbgapi_process_id for this inferior. */
127 amd_dbgapi_process_id_t process_id = AMD_DBGAPI_PROCESS_NONE;
128
129 /* The amd_dbgapi_notifier_t for this inferior. */
130 amd_dbgapi_notifier_t notifier = -1;
131
132 /* The status of the inferior's runtime support. */
133 amd_dbgapi_runtime_state_t runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED;
134
135 /* This value mirrors the current "forward progress needed" value for this
136 process in amd-dbgapi. It is used to avoid unnecessary calls to
137 amd_dbgapi_process_set_progress, to reduce the noise in the logs.
138
139 Initialized to true, since that's the default in amd-dbgapi too. */
140 bool forward_progress_required = true;
141
142 std::unordered_map<decltype (amd_dbgapi_breakpoint_id_t::handle),
143 struct breakpoint *>
144 breakpoint_map;
145
146 /* List of pending events the amd-dbgapi target retrieved from the dbgapi. */
147 std::list<std::pair<ptid_t, target_waitstatus>> wave_events;
148 };
149
150 static amd_dbgapi_event_id_t process_event_queue
151 (amd_dbgapi_process_id_t process_id = AMD_DBGAPI_PROCESS_NONE,
152 amd_dbgapi_event_kind_t until_event_kind = AMD_DBGAPI_EVENT_KIND_NONE);
153
154 static const target_info amd_dbgapi_target_info = {
155 "amd-dbgapi",
156 N_("AMD Debugger API"),
157 N_("GPU debugging using the AMD Debugger API")
158 };
159
160 static amd_dbgapi_log_level_t get_debug_amd_dbgapi_lib_log_level ();
161
162 struct amd_dbgapi_target final : public target_ops
163 {
164 const target_info &
165 info () const override
166 {
167 return amd_dbgapi_target_info;
168 }
169 strata
170 stratum () const override
171 {
172 return arch_stratum;
173 }
174
175 void close () override;
176 void mourn_inferior () override;
177 void detach (inferior *inf, int from_tty) override;
178
179 void async (bool enable) override;
180
181 bool has_pending_events () override;
182 ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
183 void resume (ptid_t, int, enum gdb_signal) override;
184 void commit_resumed () override;
185 void stop (ptid_t ptid) override;
186
187 void fetch_registers (struct regcache *, int) override;
188 void store_registers (struct regcache *, int) override;
189
190 void update_thread_list () override;
191
192 struct gdbarch *thread_architecture (ptid_t) override;
193
194 void thread_events (int enable) override;
195
196 std::string pid_to_str (ptid_t ptid) override;
197
198 const char *thread_name (thread_info *tp) override;
199
200 const char *extra_thread_info (thread_info *tp) override;
201
202 bool thread_alive (ptid_t ptid) override;
203
204 enum target_xfer_status xfer_partial (enum target_object object,
205 const char *annex, gdb_byte *readbuf,
206 const gdb_byte *writebuf,
207 ULONGEST offset, ULONGEST len,
208 ULONGEST *xfered_len) override;
209
210 bool stopped_by_watchpoint () override;
211
212 bool stopped_by_sw_breakpoint () override;
213 bool stopped_by_hw_breakpoint () override;
214
215 private:
216 /* True if we must report thread events. */
217 bool m_report_thread_events = false;
218
219 /* Cache for the last value returned by thread_architecture. */
220 gdbarch *m_cached_arch = nullptr;
221 ptid_t::tid_type m_cached_arch_tid = 0;
222 };
223
224 static struct amd_dbgapi_target the_amd_dbgapi_target;
225
226 /* Per-inferior data key. */
227
228 static const registry<inferior>::key<amd_dbgapi_inferior_info>
229 amd_dbgapi_inferior_data;
230
231 /* The async event handler registered with the event loop, indicating that we
232 might have events to report to the core and that we'd like our wait method
233 to be called.
234
235 This is nullptr when async is disabled and non-nullptr when async is
236 enabled.
237
238 It is marked when a notifier fd tells us there's an event available. The
239 callback triggers handle_inferior_event in order to pull the event from
240 amd-dbgapi and handle it. */
241
242 static async_event_handler *amd_dbgapi_async_event_handler = nullptr;
243
244 /* Return the target id string for a given wave. */
245
246 static std::string
247 wave_target_id_string (amd_dbgapi_wave_id_t wave_id)
248 {
249 amd_dbgapi_dispatch_id_t dispatch_id;
250 amd_dbgapi_queue_id_t queue_id;
251 amd_dbgapi_agent_id_t agent_id;
252 uint32_t group_ids[3], wave_in_group;
253 std::string str = "AMDGPU Wave";
254
255 amd_dbgapi_status_t status
256 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_AGENT,
257 sizeof (agent_id), &agent_id);
258 str += (status == AMD_DBGAPI_STATUS_SUCCESS
259 ? string_printf (" %ld", agent_id.handle)
260 : " ?");
261
262 status = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_QUEUE,
263 sizeof (queue_id), &queue_id);
264 str += (status == AMD_DBGAPI_STATUS_SUCCESS
265 ? string_printf (":%ld", queue_id.handle)
266 : ":?");
267
268 status = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_DISPATCH,
269 sizeof (dispatch_id), &dispatch_id);
270 str += (status == AMD_DBGAPI_STATUS_SUCCESS
271 ? string_printf (":%ld", dispatch_id.handle)
272 : ":?");
273
274 str += string_printf (":%ld", wave_id.handle);
275
276 status = amd_dbgapi_wave_get_info (wave_id,
277 AMD_DBGAPI_WAVE_INFO_WORKGROUP_COORD,
278 sizeof (group_ids), &group_ids);
279 str += (status == AMD_DBGAPI_STATUS_SUCCESS
280 ? string_printf (" (%d,%d,%d)", group_ids[0], group_ids[1],
281 group_ids[2])
282 : " (?,?,?)");
283
284 status = amd_dbgapi_wave_get_info
285 (wave_id, AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORKGROUP,
286 sizeof (wave_in_group), &wave_in_group);
287 str += (status == AMD_DBGAPI_STATUS_SUCCESS
288 ? string_printf ("/%d", wave_in_group)
289 : "/?");
290
291 return str;
292 }
293
294 /* Clear our async event handler. */
295
296 static void
297 async_event_handler_clear ()
298 {
299 gdb_assert (amd_dbgapi_async_event_handler != nullptr);
300 clear_async_event_handler (amd_dbgapi_async_event_handler);
301 }
302
303 /* Mark our async event handler. */
304
305 static void
306 async_event_handler_mark ()
307 {
308 gdb_assert (amd_dbgapi_async_event_handler != nullptr);
309 mark_async_event_handler (amd_dbgapi_async_event_handler);
310 }
311
312 /* Fetch the amd_dbgapi_inferior_info data for the given inferior. */
313
314 static struct amd_dbgapi_inferior_info *
315 get_amd_dbgapi_inferior_info (struct inferior *inferior)
316 {
317 amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (inferior);
318
319 if (info == nullptr)
320 info = amd_dbgapi_inferior_data.emplace (inferior, inferior);
321
322 return info;
323 }
324
325 /* Set forward progress requirement to REQUIRE for all processes of PROC_TARGET
326 matching PTID. */
327
328 static void
329 require_forward_progress (ptid_t ptid, process_stratum_target *proc_target,
330 bool require)
331 {
332 for (inferior *inf : all_inferiors (proc_target))
333 {
334 if (ptid != minus_one_ptid && inf->pid != ptid.pid ())
335 continue;
336
337 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
338
339 if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
340 continue;
341
342 /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */
343 if (info->forward_progress_required == require)
344 continue;
345
346 amd_dbgapi_status_t status
347 = amd_dbgapi_process_set_progress
348 (info->process_id, (require
349 ? AMD_DBGAPI_PROGRESS_NORMAL
350 : AMD_DBGAPI_PROGRESS_NO_FORWARD));
351 gdb_assert (status == AMD_DBGAPI_STATUS_SUCCESS);
352
353 info->forward_progress_required = require;
354
355 /* If ptid targets a single inferior and we have found it, no need to
356 continue. */
357 if (ptid != minus_one_ptid)
358 break;
359 }
360 }
361
362 /* See amd-dbgapi-target.h. */
363
364 amd_dbgapi_process_id_t
365 get_amd_dbgapi_process_id (inferior *inf)
366 {
367 return get_amd_dbgapi_inferior_info (inf)->process_id;
368 }
369
370 /* A breakpoint dbgapi wants us to insert, to handle shared library
371 loading/unloading. */
372
373 struct amd_dbgapi_target_breakpoint : public code_breakpoint
374 {
375 amd_dbgapi_target_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
376 : code_breakpoint (gdbarch, bp_breakpoint)
377 {
378 symtab_and_line sal;
379 sal.pc = address;
380 sal.section = find_pc_overlay (sal.pc);
381 sal.pspace = current_program_space;
382 add_location (sal);
383
384 pspace = current_program_space;
385 disposition = disp_donttouch;
386 }
387
388 void re_set () override;
389 void check_status (struct bpstat *bs) override;
390 };
391
392 void
393 amd_dbgapi_target_breakpoint::re_set ()
394 {
395 /* Nothing. */
396 }
397
398 void
399 amd_dbgapi_target_breakpoint::check_status (struct bpstat *bs)
400 {
401 inferior *inf = current_inferior ();
402 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
403 amd_dbgapi_status_t status;
404
405 bs->stop = 0;
406 bs->print_it = print_it_noop;
407
408 /* Find the address the breakpoint is set at. */
409 auto match_breakpoint
410 = [bs] (const decltype (info->breakpoint_map)::value_type &value)
411 { return value.second == bs->breakpoint_at; };
412 auto it
413 = std::find_if (info->breakpoint_map.begin (), info->breakpoint_map.end (),
414 match_breakpoint);
415
416 if (it == info->breakpoint_map.end ())
417 error (_("Could not find breakpoint_id for breakpoint at %s"),
418 paddress (inf->gdbarch, bs->bp_location_at->address));
419
420 amd_dbgapi_breakpoint_id_t breakpoint_id { it->first };
421 amd_dbgapi_breakpoint_action_t action;
422
423 status = amd_dbgapi_report_breakpoint_hit
424 (breakpoint_id,
425 reinterpret_cast<amd_dbgapi_client_thread_id_t> (inferior_thread ()),
426 &action);
427
428 if (status != AMD_DBGAPI_STATUS_SUCCESS)
429 error (_("amd_dbgapi_report_breakpoint_hit failed for breakpoint %ld "
430 "at %s (%s)"),
431 breakpoint_id.handle, paddress (inf->gdbarch, bs->bp_location_at->address),
432 get_status_string (status));
433
434 if (action == AMD_DBGAPI_BREAKPOINT_ACTION_RESUME)
435 return;
436
437 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
438 a breakpoint resume event for this breakpoint_id is seen. */
439 amd_dbgapi_event_id_t resume_event_id
440 = process_event_queue (info->process_id,
441 AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
442
443 /* We should always get a breakpoint_resume event after processing all
444 events generated by reporting the breakpoint hit. */
445 gdb_assert (resume_event_id != AMD_DBGAPI_EVENT_NONE);
446
447 amd_dbgapi_breakpoint_id_t resume_breakpoint_id;
448 status = amd_dbgapi_event_get_info (resume_event_id,
449 AMD_DBGAPI_EVENT_INFO_BREAKPOINT,
450 sizeof (resume_breakpoint_id),
451 &resume_breakpoint_id);
452
453 if (status != AMD_DBGAPI_STATUS_SUCCESS)
454 error (_("amd_dbgapi_event_get_info failed (%s)"), get_status_string (status));
455
456 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint]
457 sequences cannot interleave, so this breakpoint resume event must be
458 for our breakpoint_id. */
459 if (resume_breakpoint_id != breakpoint_id)
460 error (_("breakpoint resume event is not for this breakpoint. "
461 "Expected breakpoint_%ld, got breakpoint_%ld"),
462 breakpoint_id.handle, resume_breakpoint_id.handle);
463
464 amd_dbgapi_event_processed (resume_event_id);
465 }
466
467 bool
468 amd_dbgapi_target::thread_alive (ptid_t ptid)
469 {
470 if (!ptid_is_gpu (ptid))
471 return beneath ()->thread_alive (ptid);
472
473 /* Check that the wave_id is valid. */
474
475 amd_dbgapi_wave_state_t state;
476 amd_dbgapi_status_t status
477 = amd_dbgapi_wave_get_info (get_amd_dbgapi_wave_id (ptid),
478 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state),
479 &state);
480 return status == AMD_DBGAPI_STATUS_SUCCESS;
481 }
482
483 const char *
484 amd_dbgapi_target::thread_name (thread_info *tp)
485 {
486 if (!ptid_is_gpu (tp->ptid))
487 return beneath ()->thread_name (tp);
488
489 return nullptr;
490 }
491
492 std::string
493 amd_dbgapi_target::pid_to_str (ptid_t ptid)
494 {
495 if (!ptid_is_gpu (ptid))
496 return beneath ()->pid_to_str (ptid);
497
498 return wave_target_id_string (get_amd_dbgapi_wave_id (ptid));
499 }
500
501 const char *
502 amd_dbgapi_target::extra_thread_info (thread_info *tp)
503 {
504 if (!ptid_is_gpu (tp->ptid))
505 beneath ()->extra_thread_info (tp);
506
507 return nullptr;
508 }
509
510 target_xfer_status
511 amd_dbgapi_target::xfer_partial (enum target_object object, const char *annex,
512 gdb_byte *readbuf, const gdb_byte *writebuf,
513 ULONGEST offset, ULONGEST requested_len,
514 ULONGEST *xfered_len)
515 {
516 gdb::optional<scoped_restore_current_thread> maybe_restore_thread;
517
518 if (!ptid_is_gpu (inferior_ptid))
519 return beneath ()->xfer_partial (object, annex, readbuf, writebuf, offset,
520 requested_len, xfered_len);
521
522 gdb_assert (requested_len > 0);
523 gdb_assert (xfered_len != nullptr);
524
525 if (object != TARGET_OBJECT_MEMORY)
526 return TARGET_XFER_E_IO;
527
528 amd_dbgapi_process_id_t process_id
529 = get_amd_dbgapi_process_id (current_inferior ());
530 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid);
531
532 size_t len = requested_len;
533 amd_dbgapi_status_t status;
534
535 if (readbuf != nullptr)
536 status = amd_dbgapi_read_memory (process_id, wave_id, 0,
537 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL,
538 offset, &len, readbuf);
539 else
540 status = amd_dbgapi_write_memory (process_id, wave_id, 0,
541 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL,
542 offset, &len, writebuf);
543
544 if (status != AMD_DBGAPI_STATUS_SUCCESS)
545 return TARGET_XFER_E_IO;
546
547 *xfered_len = len;
548 return TARGET_XFER_OK;
549 }
550
551 bool
552 amd_dbgapi_target::stopped_by_watchpoint ()
553 {
554 if (!ptid_is_gpu (inferior_ptid))
555 return beneath ()->stopped_by_watchpoint ();
556
557 return false;
558 }
559
560 void
561 amd_dbgapi_target::resume (ptid_t scope_ptid, int step, enum gdb_signal signo)
562 {
563 amd_dbgapi_debug_printf ("scope_ptid = %s", scope_ptid.to_string ().c_str ());
564
565 /* The amd_dbgapi_exceptions_t matching SIGNO will only be used if the
566 thread which is the target of the signal SIGNO is a GPU thread. If so,
567 make sure that there is a corresponding amd_dbgapi_exceptions_t for SIGNO
568 before we try to resume any thread. */
569 amd_dbgapi_exceptions_t exception = AMD_DBGAPI_EXCEPTION_NONE;
570 if (ptid_is_gpu (inferior_ptid))
571 {
572 switch (signo)
573 {
574 case GDB_SIGNAL_BUS:
575 exception = AMD_DBGAPI_EXCEPTION_WAVE_APERTURE_VIOLATION;
576 break;
577 case GDB_SIGNAL_SEGV:
578 exception = AMD_DBGAPI_EXCEPTION_WAVE_MEMORY_VIOLATION;
579 break;
580 case GDB_SIGNAL_ILL:
581 exception = AMD_DBGAPI_EXCEPTION_WAVE_ILLEGAL_INSTRUCTION;
582 break;
583 case GDB_SIGNAL_FPE:
584 exception = AMD_DBGAPI_EXCEPTION_WAVE_MATH_ERROR;
585 break;
586 case GDB_SIGNAL_ABRT:
587 exception = AMD_DBGAPI_EXCEPTION_WAVE_ABORT;
588 break;
589 case GDB_SIGNAL_TRAP:
590 exception = AMD_DBGAPI_EXCEPTION_WAVE_TRAP;
591 break;
592 case GDB_SIGNAL_0:
593 exception = AMD_DBGAPI_EXCEPTION_NONE;
594 break;
595 default:
596 error (_("Resuming with signal %s is not supported by this agent."),
597 gdb_signal_to_name (signo));
598 }
599 }
600
601 if (!ptid_is_gpu (inferior_ptid) || scope_ptid != inferior_ptid)
602 {
603 beneath ()->resume (scope_ptid, step, signo);
604
605 /* If the request is for a single thread, we are done. */
606 if (scope_ptid == inferior_ptid)
607 return;
608 }
609
610 process_stratum_target *proc_target = current_inferior ()->process_target ();
611
612 /* Disable forward progress requirement. */
613 require_forward_progress (scope_ptid, proc_target, false);
614
615 for (thread_info *thread : all_non_exited_threads (proc_target, scope_ptid))
616 {
617 if (!ptid_is_gpu (thread->ptid))
618 continue;
619
620 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid);
621 amd_dbgapi_status_t status;
622 if (thread->ptid == inferior_ptid)
623 status = amd_dbgapi_wave_resume (wave_id,
624 (step
625 ? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
626 : AMD_DBGAPI_RESUME_MODE_NORMAL),
627 exception);
628 else
629 status = amd_dbgapi_wave_resume (wave_id, AMD_DBGAPI_RESUME_MODE_NORMAL,
630 AMD_DBGAPI_EXCEPTION_NONE);
631
632 if (status != AMD_DBGAPI_STATUS_SUCCESS
633 /* Ignore the error that wave is no longer valid as that could
634 indicate that the process has exited. GDB treats resuming a
635 thread that no longer exists as being successful. */
636 && status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
637 error (_("wave_resume for wave_%ld failed (%s)"), wave_id.handle,
638 get_status_string (status));
639 }
640 }
641
642 void
643 amd_dbgapi_target::commit_resumed ()
644 {
645 amd_dbgapi_debug_printf ("called");
646
647 beneath ()->commit_resumed ();
648
649 process_stratum_target *proc_target = current_inferior ()->process_target ();
650 require_forward_progress (minus_one_ptid, proc_target, true);
651 }
652
653 void
654 amd_dbgapi_target::stop (ptid_t ptid)
655 {
656 amd_dbgapi_debug_printf ("ptid = %s", ptid.to_string ().c_str ());
657
658 bool many_threads = ptid == minus_one_ptid || ptid.is_pid ();
659
660 if (!ptid_is_gpu (ptid) || many_threads)
661 {
662 beneath ()->stop (ptid);
663
664 /* The request is for a single thread, we are done. */
665 if (!many_threads)
666 return;
667 }
668
669 auto stop_one_thread = [this] (thread_info *thread)
670 {
671 gdb_assert (thread != nullptr);
672
673 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid);
674 amd_dbgapi_wave_state_t state;
675 amd_dbgapi_status_t status
676 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STATE,
677 sizeof (state), &state);
678 if (status == AMD_DBGAPI_STATUS_SUCCESS)
679 {
680 /* If the wave is already known to be stopped then do nothing. */
681 if (state == AMD_DBGAPI_WAVE_STATE_STOP)
682 return;
683
684 status = amd_dbgapi_wave_stop (wave_id);
685 if (status == AMD_DBGAPI_STATUS_SUCCESS)
686 return;
687
688 if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
689 error (_("wave_stop for wave_%ld failed (%s)"), wave_id.handle,
690 get_status_string (status));
691 }
692 else if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
693 error (_("wave_get_info for wave_%ld failed (%s)"), wave_id.handle,
694 get_status_string (status));
695
696 /* The status is AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID. The wave
697 could have terminated since the last time the wave list was
698 refreshed. */
699
700 if (m_report_thread_events)
701 {
702 get_amd_dbgapi_inferior_info (thread->inf)->wave_events.emplace_back
703 (thread->ptid, target_waitstatus ().set_thread_exited (0));
704
705 if (target_is_async_p ())
706 async_event_handler_mark ();
707 }
708
709 delete_thread_silent (thread);
710 };
711
712 process_stratum_target *proc_target = current_inferior ()->process_target ();
713
714 /* Disable forward progress requirement. */
715 require_forward_progress (ptid, proc_target, false);
716
717 if (!many_threads)
718 {
719 /* No need to iterate all non-exited threads if the request is to stop a
720 specific thread. */
721 stop_one_thread (proc_target->find_thread (ptid));
722 return;
723 }
724
725 for (auto *inf : all_inferiors (proc_target))
726 /* Use the threads_safe iterator since stop_one_thread may delete the
727 thread if it has exited. */
728 for (auto *thread : inf->threads_safe ())
729 if (thread->state != THREAD_EXITED && thread->ptid.matches (ptid)
730 && ptid_is_gpu (thread->ptid))
731 stop_one_thread (thread);
732 }
733
734 /* Callback for our async event handler. */
735
736 static void
737 handle_target_event (gdb_client_data client_data)
738 {
739 inferior_event_handler (INF_REG_EVENT);
740 }
741
742 struct scoped_amd_dbgapi_event_processed
743 {
744 scoped_amd_dbgapi_event_processed (amd_dbgapi_event_id_t event_id)
745 : m_event_id (event_id)
746 {
747 gdb_assert (event_id != AMD_DBGAPI_EVENT_NONE);
748 }
749
750 ~scoped_amd_dbgapi_event_processed ()
751 {
752 amd_dbgapi_status_t status = amd_dbgapi_event_processed (m_event_id);
753 if (status != AMD_DBGAPI_STATUS_SUCCESS)
754 warning (_("Failed to acknowledge amd-dbgapi event %" PRIu64),
755 m_event_id.handle);
756 }
757
758 DISABLE_COPY_AND_ASSIGN (scoped_amd_dbgapi_event_processed);
759
760 private:
761 amd_dbgapi_event_id_t m_event_id;
762 };
763
764 /* Called when a dbgapi notifier fd is readable. CLIENT_DATA is the
765 amd_dbgapi_inferior_info object corresponding to the notifier. */
766
767 static void
768 dbgapi_notifier_handler (int err, gdb_client_data client_data)
769 {
770 amd_dbgapi_inferior_info *info = (amd_dbgapi_inferior_info *) client_data;
771 int ret;
772
773 /* Drain the notifier pipe. */
774 do
775 {
776 char buf;
777 ret = read (info->notifier, &buf, 1);
778 }
779 while (ret >= 0 || (ret == -1 && errno == EINTR));
780
781 if (info->inf->target_is_pushed (&the_amd_dbgapi_target))
782 {
783 /* The amd-dbgapi target is pushed: signal our async handler, the event
784 will be consumed through our wait method. */
785
786 async_event_handler_mark ();
787 }
788 else
789 {
790 /* The amd-dbgapi target is not pushed: if there's an event, the only
791 expected one is one of the RUNTIME kind. If the event tells us the
792 inferior as activated the ROCm runtime, push the amd-dbgapi
793 target. */
794
795 amd_dbgapi_event_id_t event_id;
796 amd_dbgapi_event_kind_t event_kind;
797 amd_dbgapi_status_t status
798 = amd_dbgapi_process_next_pending_event (info->process_id, &event_id,
799 &event_kind);
800 if (status != AMD_DBGAPI_STATUS_SUCCESS)
801 error (_("next_pending_event failed (%s)"), get_status_string (status));
802
803 if (event_id == AMD_DBGAPI_EVENT_NONE)
804 return;
805
806 gdb_assert (event_kind == AMD_DBGAPI_EVENT_KIND_RUNTIME);
807
808 scoped_amd_dbgapi_event_processed mark_event_processed (event_id);
809
810 amd_dbgapi_runtime_state_t runtime_state;
811 status = amd_dbgapi_event_get_info (event_id,
812 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
813 sizeof (runtime_state),
814 &runtime_state);
815 if (status != AMD_DBGAPI_STATUS_SUCCESS)
816 error (_("event_get_info for event_%ld failed (%s)"),
817 event_id.handle, get_status_string (status));
818
819 switch (runtime_state)
820 {
821 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS:
822 gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
823 info->runtime_state = runtime_state;
824 amd_dbgapi_debug_printf ("pushing amd-dbgapi target");
825 info->inf->push_target (&the_amd_dbgapi_target);
826
827 /* The underlying target will already be async if we are running, but not if
828 we are attaching. */
829 if (info->inf->process_target ()->is_async_p ())
830 {
831 scoped_restore_current_thread restore_thread;
832 switch_to_inferior_no_thread (info->inf);
833
834 /* Make sure our async event handler is created. */
835 target_async (true);
836 }
837 break;
838
839 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED:
840 gdb_assert (info->runtime_state
841 == AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION);
842 info->runtime_state = runtime_state;
843 break;
844
845 case AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION:
846 gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
847 info->runtime_state = runtime_state;
848 warning (_("amd-dbgapi: unable to enable GPU debugging "
849 "due to a restriction error"));
850 break;
851 }
852 }
853 }
854
855 void
856 amd_dbgapi_target::async (bool enable)
857 {
858 beneath ()->async (enable);
859
860 if (enable)
861 {
862 if (amd_dbgapi_async_event_handler != nullptr)
863 {
864 /* Already enabled. */
865 return;
866 }
867
868 /* The library gives us one notifier file descriptor per inferior (even
869 the ones that have not yet loaded their runtime). Register them
870 all with the event loop. */
871 process_stratum_target *proc_target
872 = current_inferior ()->process_target ();
873
874 for (inferior *inf : all_non_exited_inferiors (proc_target))
875 {
876 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
877
878 if (info->notifier != -1)
879 add_file_handler (info->notifier, dbgapi_notifier_handler, info,
880 string_printf ("amd-dbgapi notifier for pid %d",
881 inf->pid));
882 }
883
884 amd_dbgapi_async_event_handler
885 = create_async_event_handler (handle_target_event, nullptr,
886 "amd-dbgapi");
887
888 /* There may be pending events to handle. Tell the event loop to poll
889 them. */
890 async_event_handler_mark ();
891 }
892 else
893 {
894 if (amd_dbgapi_async_event_handler == nullptr)
895 return;
896
897 for (inferior *inf : all_inferiors ())
898 {
899 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
900
901 if (info->notifier != -1)
902 delete_file_handler (info->notifier);
903 }
904
905 delete_async_event_handler (&amd_dbgapi_async_event_handler);
906 }
907 }
908
909 /* Make a ptid for a GPU wave. See comment on ptid_is_gpu for more details. */
910
911 static ptid_t
912 make_gpu_ptid (ptid_t::pid_type pid, amd_dbgapi_wave_id_t wave_id)
913 {
914 return ptid_t (pid, 1, wave_id.handle);
915 }
916
917 /* Process an event that was just pulled out of the amd-dbgapi library. */
918
919 static void
920 process_one_event (amd_dbgapi_event_id_t event_id,
921 amd_dbgapi_event_kind_t event_kind)
922 {
923 /* Automatically mark this event processed when going out of scope. */
924 scoped_amd_dbgapi_event_processed mark_event_processed (event_id);
925
926 amd_dbgapi_process_id_t process_id;
927 amd_dbgapi_status_t status
928 = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_PROCESS,
929 sizeof (process_id), &process_id);
930 if (status != AMD_DBGAPI_STATUS_SUCCESS)
931 error (_("event_get_info for event_%ld failed (%s)"), event_id.handle,
932 get_status_string (status));
933
934 amd_dbgapi_os_process_id_t pid;
935 status = amd_dbgapi_process_get_info (process_id,
936 AMD_DBGAPI_PROCESS_INFO_OS_ID,
937 sizeof (pid), &pid);
938 if (status != AMD_DBGAPI_STATUS_SUCCESS)
939 error (_("process_get_info for process_%ld failed (%s)"),
940 process_id.handle, get_status_string (status));
941
942 auto *proc_target = current_inferior ()->process_target ();
943 inferior *inf = find_inferior_pid (proc_target, pid);
944 gdb_assert (inf != nullptr);
945 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
946
947 switch (event_kind)
948 {
949 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED:
950 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
951 {
952 amd_dbgapi_wave_id_t wave_id;
953 status
954 = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_WAVE,
955 sizeof (wave_id), &wave_id);
956 if (status != AMD_DBGAPI_STATUS_SUCCESS)
957 error (_("event_get_info for event_%ld failed (%s)"),
958 event_id.handle, get_status_string (status));
959
960 ptid_t event_ptid = make_gpu_ptid (pid, wave_id);
961 target_waitstatus ws;
962
963 amd_dbgapi_wave_stop_reasons_t stop_reason;
964 status = amd_dbgapi_wave_get_info (wave_id,
965 AMD_DBGAPI_WAVE_INFO_STOP_REASON,
966 sizeof (stop_reason), &stop_reason);
967 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
968 && event_kind == AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED)
969 ws.set_thread_exited (0);
970 else if (status == AMD_DBGAPI_STATUS_SUCCESS)
971 {
972 if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_APERTURE_VIOLATION)
973 ws.set_stopped (GDB_SIGNAL_BUS);
974 else if (stop_reason
975 & AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION)
976 ws.set_stopped (GDB_SIGNAL_SEGV);
977 else if (stop_reason
978 & AMD_DBGAPI_WAVE_STOP_REASON_ILLEGAL_INSTRUCTION)
979 ws.set_stopped (GDB_SIGNAL_ILL);
980 else if (stop_reason
981 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
982 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
983 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
984 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
985 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
986 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
987 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0))
988 ws.set_stopped (GDB_SIGNAL_FPE);
989 else if (stop_reason
990 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
991 | AMD_DBGAPI_WAVE_STOP_REASON_WATCHPOINT
992 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
993 | AMD_DBGAPI_WAVE_STOP_REASON_DEBUG_TRAP
994 | AMD_DBGAPI_WAVE_STOP_REASON_TRAP))
995 ws.set_stopped (GDB_SIGNAL_TRAP);
996 else if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_ASSERT_TRAP)
997 ws.set_stopped (GDB_SIGNAL_ABRT);
998 else
999 ws.set_stopped (GDB_SIGNAL_0);
1000
1001 thread_info *thread = proc_target->find_thread (event_ptid);
1002 if (thread == nullptr)
1003 {
1004 /* Silently create new GPU threads to avoid spamming the
1005 terminal with thousands of "[New Thread ...]" messages. */
1006 thread = add_thread_silent (proc_target, event_ptid);
1007 set_running (proc_target, event_ptid, true);
1008 set_executing (proc_target, event_ptid, true);
1009 }
1010
1011 /* If the wave is stopped because of a software breakpoint, the
1012 program counter needs to be adjusted so that it points to the
1013 breakpoint instruction. */
1014 if ((stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT) != 0)
1015 {
1016 regcache *regcache = get_thread_regcache (thread);
1017 gdbarch *gdbarch = regcache->arch ();
1018
1019 CORE_ADDR pc = regcache_read_pc (regcache);
1020 CORE_ADDR adjusted_pc
1021 = pc - gdbarch_decr_pc_after_break (gdbarch);
1022
1023 if (adjusted_pc != pc)
1024 regcache_write_pc (regcache, adjusted_pc);
1025 }
1026 }
1027 else
1028 error (_("wave_get_info for wave_%ld failed (%s)"),
1029 wave_id.handle, get_status_string (status));
1030
1031 info->wave_events.emplace_back (event_ptid, ws);
1032 break;
1033 }
1034
1035 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED:
1036 /* We get here when the following sequence of events happens:
1037
1038 - the inferior hits the amd-dbgapi "r_brk" internal breakpoint
1039 - amd_dbgapi_target_breakpoint::check_status calls
1040 amd_dbgapi_report_breakpoint_hit, which queues an event of this
1041 kind in dbgapi
1042 - amd_dbgapi_target_breakpoint::check_status calls
1043 process_event_queue, which pulls the event out of dbgapi, and
1044 gets us here
1045
1046 When amd_dbgapi_target_breakpoint::check_status is called, the current
1047 inferior is the inferior that hit the breakpoint, which should still be
1048 the case now. */
1049 gdb_assert (inf == current_inferior ());
1050 handle_solib_event ();
1051 break;
1052
1053 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME:
1054 /* Breakpoint resume events should be handled by the breakpoint
1055 action, and this code should not reach this. */
1056 gdb_assert_not_reached ("unhandled event kind");
1057 break;
1058
1059 case AMD_DBGAPI_EVENT_KIND_RUNTIME:
1060 {
1061 amd_dbgapi_runtime_state_t runtime_state;
1062
1063 status = amd_dbgapi_event_get_info (event_id,
1064 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
1065 sizeof (runtime_state),
1066 &runtime_state);
1067 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1068 error (_("event_get_info for event_%ld failed (%s)"),
1069 event_id.handle, get_status_string (status));
1070
1071 gdb_assert (runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
1072 gdb_assert
1073 (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
1074
1075 info->runtime_state = runtime_state;
1076
1077 gdb_assert (inf->target_is_pushed (&the_amd_dbgapi_target));
1078 inf->unpush_target (&the_amd_dbgapi_target);
1079 }
1080 break;
1081
1082 default:
1083 error (_("event kind (%d) not supported"), event_kind);
1084 }
1085 }
1086
1087 /* Return a textual version of KIND. */
1088
1089 static const char *
1090 event_kind_str (amd_dbgapi_event_kind_t kind)
1091 {
1092 switch (kind)
1093 {
1094 case AMD_DBGAPI_EVENT_KIND_NONE:
1095 return "NONE";
1096
1097 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
1098 return "WAVE_STOP";
1099
1100 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED:
1101 return "WAVE_COMMAND_TERMINATED";
1102
1103 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED:
1104 return "CODE_OBJECT_LIST_UPDATED";
1105
1106 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME:
1107 return "BREAKPOINT_RESUME";
1108
1109 case AMD_DBGAPI_EVENT_KIND_RUNTIME:
1110 return "RUNTIME";
1111
1112 case AMD_DBGAPI_EVENT_KIND_QUEUE_ERROR:
1113 return "QUEUE_ERROR";
1114 }
1115
1116 gdb_assert_not_reached ("unhandled amd_dbgapi_event_kind_t value");
1117 }
1118
1119 /* Drain the dbgapi event queue of a given process_id, or of all processes if
1120 process_id is AMD_DBGAPI_PROCESS_NONE. Stop processing the events if an
1121 event of a given kind is requested and `process_id` is not
1122 AMD_DBGAPI_PROCESS_NONE. Wave stop events that are not returned are queued
1123 into their inferior's amd_dbgapi_inferior_info pending wave events. */
1124
1125 static amd_dbgapi_event_id_t
1126 process_event_queue (amd_dbgapi_process_id_t process_id,
1127 amd_dbgapi_event_kind_t until_event_kind)
1128 {
1129 /* An event of a given type can only be requested from a single
1130 process_id. */
1131 gdb_assert (until_event_kind == AMD_DBGAPI_EVENT_KIND_NONE
1132 || process_id != AMD_DBGAPI_PROCESS_NONE);
1133
1134 while (true)
1135 {
1136 amd_dbgapi_event_id_t event_id;
1137 amd_dbgapi_event_kind_t event_kind;
1138
1139 amd_dbgapi_status_t status
1140 = amd_dbgapi_process_next_pending_event (process_id, &event_id,
1141 &event_kind);
1142
1143 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1144 error (_("next_pending_event failed (%s)"), get_status_string (status));
1145
1146 if (event_kind != AMD_DBGAPI_EVENT_KIND_NONE)
1147 amd_dbgapi_debug_printf ("Pulled event from dbgapi: "
1148 "event_id.handle = %" PRIu64 ", "
1149 "event_kind = %s",
1150 event_id.handle,
1151 event_kind_str (event_kind));
1152
1153 if (event_id == AMD_DBGAPI_EVENT_NONE || event_kind == until_event_kind)
1154 return event_id;
1155
1156 process_one_event (event_id, event_kind);
1157 }
1158 }
1159
1160 bool
1161 amd_dbgapi_target::has_pending_events ()
1162 {
1163 if (amd_dbgapi_async_event_handler != nullptr
1164 && async_event_handler_marked (amd_dbgapi_async_event_handler))
1165 return true;
1166
1167 return beneath ()->has_pending_events ();
1168 }
1169
1170 /* Pop one pending event from the per-inferior structures.
1171
1172 If PID is not -1, restrict the search to the inferior with that pid. */
1173
1174 static std::pair<ptid_t, target_waitstatus>
1175 consume_one_event (int pid)
1176 {
1177 auto *target = current_inferior ()->process_target ();
1178 struct amd_dbgapi_inferior_info *info = nullptr;
1179
1180 if (pid == -1)
1181 {
1182 for (inferior *inf : all_inferiors (target))
1183 {
1184 info = get_amd_dbgapi_inferior_info (inf);
1185 if (!info->wave_events.empty ())
1186 break;
1187 }
1188
1189 gdb_assert (info != nullptr);
1190 }
1191 else
1192 {
1193 inferior *inf = find_inferior_pid (target, pid);
1194
1195 gdb_assert (inf != nullptr);
1196 info = get_amd_dbgapi_inferior_info (inf);
1197 }
1198
1199 if (info->wave_events.empty ())
1200 return { minus_one_ptid, {} };
1201
1202 auto event = info->wave_events.front ();
1203 info->wave_events.pop_front ();
1204
1205 return event;
1206 }
1207
1208 ptid_t
1209 amd_dbgapi_target::wait (ptid_t ptid, struct target_waitstatus *ws,
1210 target_wait_flags target_options)
1211 {
1212 gdb_assert (!current_inferior ()->process_target ()->commit_resumed_state);
1213 gdb_assert (ptid == minus_one_ptid || ptid.is_pid ());
1214
1215 amd_dbgapi_debug_printf ("ptid = %s", ptid.to_string ().c_str ());
1216
1217 ptid_t event_ptid = beneath ()->wait (ptid, ws, target_options);
1218 if (event_ptid != minus_one_ptid)
1219 {
1220 if (ws->kind () == TARGET_WAITKIND_EXITED
1221 || ws->kind () == TARGET_WAITKIND_SIGNALLED)
1222 {
1223 /* This inferior has exited so drain its dbgapi event queue. */
1224 while (consume_one_event (event_ptid.pid ()).first
1225 != minus_one_ptid)
1226 ;
1227 }
1228 return event_ptid;
1229 }
1230
1231 gdb_assert (ws->kind () == TARGET_WAITKIND_NO_RESUMED
1232 || ws->kind () == TARGET_WAITKIND_IGNORE);
1233
1234 /* Flush the async handler first. */
1235 if (target_is_async_p ())
1236 async_event_handler_clear ();
1237
1238 /* There may be more events to process (either already in `wave_events` or
1239 that we need to fetch from dbgapi. Mark the async event handler so that
1240 amd_dbgapi_target::wait gets called again and again, until it eventually
1241 returns minus_one_ptid. */
1242 auto more_events = make_scope_exit ([] ()
1243 {
1244 if (target_is_async_p ())
1245 async_event_handler_mark ();
1246 });
1247
1248 auto *proc_target = current_inferior ()->process_target ();
1249
1250 /* Disable forward progress for the specified pid in ptid if it isn't
1251 minus_on_ptid, or all attached processes if ptid is minus_one_ptid. */
1252 require_forward_progress (ptid, proc_target, false);
1253
1254 target_waitstatus gpu_waitstatus;
1255 std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
1256 if (event_ptid == minus_one_ptid)
1257 {
1258 /* Drain the events from the amd_dbgapi and preserve the ordering. */
1259 process_event_queue ();
1260
1261 std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
1262 if (event_ptid == minus_one_ptid)
1263 {
1264 /* If we requested a specific ptid, and nothing came out, assume
1265 another ptid may have more events, otherwise, keep the
1266 async_event_handler flushed. */
1267 if (ptid == minus_one_ptid)
1268 more_events.release ();
1269
1270 if (ws->kind () == TARGET_WAITKIND_NO_RESUMED)
1271 {
1272 /* We can't easily check that all GPU waves are stopped, and no
1273 new waves can be created (the GPU has fixed function hardware
1274 to create new threads), so even if the target beneath returns
1275 waitkind_no_resumed, we have to report waitkind_ignore if GPU
1276 debugging is enabled for at least one resumed inferior handled
1277 by the amd-dbgapi target. */
1278
1279 for (inferior *inf : all_inferiors ())
1280 if (inf->target_at (arch_stratum) == &the_amd_dbgapi_target
1281 && get_amd_dbgapi_inferior_info (inf)->runtime_state
1282 == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS)
1283 {
1284 ws->set_ignore ();
1285 break;
1286 }
1287 }
1288
1289 /* There are no events to report, return the target beneath's
1290 waitstatus (either IGNORE or NO_RESUMED). */
1291 return minus_one_ptid;
1292 }
1293 }
1294
1295 *ws = gpu_waitstatus;
1296 return event_ptid;
1297 }
1298
1299 bool
1300 amd_dbgapi_target::stopped_by_sw_breakpoint ()
1301 {
1302 if (!ptid_is_gpu (inferior_ptid))
1303 return beneath ()->stopped_by_sw_breakpoint ();
1304
1305 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid);
1306
1307 amd_dbgapi_wave_stop_reasons_t stop_reason;
1308 amd_dbgapi_status_t status
1309 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STOP_REASON,
1310 sizeof (stop_reason), &stop_reason);
1311
1312 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1313 return false;
1314
1315 return (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT) != 0;
1316 }
1317
1318 bool
1319 amd_dbgapi_target::stopped_by_hw_breakpoint ()
1320 {
1321 if (!ptid_is_gpu (inferior_ptid))
1322 return beneath ()->stopped_by_hw_breakpoint ();
1323
1324 return false;
1325 }
1326
1327 /* Make the amd-dbgapi library attach to the process behind INF.
1328
1329 Note that this is unrelated to the "attach" GDB concept / command.
1330
1331 By attaching to the process, we get a notifier fd that tells us when it
1332 activates the ROCm runtime and when there are subsequent debug events. */
1333
1334 static void
1335 attach_amd_dbgapi (inferior *inf)
1336 {
1337 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num);
1338
1339 if (!target_can_async_p ())
1340 {
1341 warning (_("The amd-dbgapi target requires the target beneath to be "
1342 "asynchronous, GPU debugging is disabled"));
1343 return;
1344 }
1345
1346 /* dbgapi can't attach to a vfork child (a process born from a vfork that
1347 hasn't exec'ed yet) while we are still attached to the parent. It would
1348 not be useful for us to attach to vfork children anyway, because vfork
1349 children are very restricted in what they can do (see vfork(2)) and aren't
1350 going to launch some GPU programs that we need to debug. To avoid this
1351 problem, we don't push the amd-dbgapi target / attach dbgapi in vfork
1352 children. If a vfork child execs, we'll try enabling the amd-dbgapi target
1353 through the inferior_execd observer. */
1354 if (inf->vfork_parent != nullptr)
1355 return;
1356
1357 auto *info = get_amd_dbgapi_inferior_info (inf);
1358
1359 /* Are we already attached? */
1360 if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
1361 {
1362 amd_dbgapi_debug_printf
1363 ("already attached: process_id = %" PRIu64, info->process_id.handle);
1364 return;
1365 }
1366
1367 amd_dbgapi_status_t status
1368 = amd_dbgapi_process_attach
1369 (reinterpret_cast<amd_dbgapi_client_process_id_t> (inf),
1370 &info->process_id);
1371 if (status == AMD_DBGAPI_STATUS_ERROR_RESTRICTION)
1372 {
1373 warning (_("amd-dbgapi: unable to enable GPU debugging due to a "
1374 "restriction error"));
1375 return;
1376 }
1377 else if (status != AMD_DBGAPI_STATUS_SUCCESS)
1378 {
1379 warning (_("amd-dbgapi: could not attach to process %d (%s), GPU "
1380 "debugging will not be available."), inf->pid,
1381 get_status_string (status));
1382 return;
1383 }
1384
1385 if (amd_dbgapi_process_get_info (info->process_id,
1386 AMD_DBGAPI_PROCESS_INFO_NOTIFIER,
1387 sizeof (info->notifier), &info->notifier)
1388 != AMD_DBGAPI_STATUS_SUCCESS)
1389 {
1390 amd_dbgapi_process_detach (info->process_id);
1391 info->process_id = AMD_DBGAPI_PROCESS_NONE;
1392 warning (_("amd-dbgapi: could not retrieve process %d's notifier, GPU "
1393 "debugging will not be available."), inf->pid);
1394 return;
1395 }
1396
1397 amd_dbgapi_debug_printf ("process_id = %" PRIu64 ", notifier fd = %d",
1398 info->process_id.handle, info->notifier);
1399
1400 /* If GDB is attaching to a process that has the runtime loaded, there will
1401 already be a "runtime loaded" event available. Consume it and push the
1402 target. */
1403 dbgapi_notifier_handler (0, info);
1404
1405 add_file_handler (info->notifier, dbgapi_notifier_handler, info,
1406 "amd-dbgapi notifier");
1407 }
1408
1409 static void maybe_reset_amd_dbgapi ();
1410
1411 /* Make the amd-dbgapi library detach from INF.
1412
1413 Note that this us unrelated to the "detach" GDB concept / command.
1414
1415 This undoes what attach_amd_dbgapi does. */
1416
1417 static void
1418 detach_amd_dbgapi (inferior *inf)
1419 {
1420 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num);
1421
1422 auto *info = get_amd_dbgapi_inferior_info (inf);
1423
1424 if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
1425 return;
1426
1427 info->runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED;
1428
1429 amd_dbgapi_status_t status = amd_dbgapi_process_detach (info->process_id);
1430 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1431 warning (_("amd-dbgapi: could not detach from process %d (%s)"),
1432 inf->pid, get_status_string (status));
1433
1434 gdb_assert (info->notifier != -1);
1435 delete_file_handler (info->notifier);
1436
1437 /* This is a noop if the target is not pushed. */
1438 inf->unpush_target (&the_amd_dbgapi_target);
1439
1440 /* Delete the breakpoints that are still active. */
1441 for (auto &&value : info->breakpoint_map)
1442 delete_breakpoint (value.second);
1443
1444 /* Reset the amd_dbgapi_inferior_info. */
1445 *info = amd_dbgapi_inferior_info (inf);
1446
1447 maybe_reset_amd_dbgapi ();
1448 }
1449
1450 void
1451 amd_dbgapi_target::mourn_inferior ()
1452 {
1453 detach_amd_dbgapi (current_inferior ());
1454 beneath ()->mourn_inferior ();
1455 }
1456
1457 void
1458 amd_dbgapi_target::detach (inferior *inf, int from_tty)
1459 {
1460 /* We're about to resume the waves by detaching the dbgapi library from the
1461 inferior, so we need to remove all breakpoints that are still inserted.
1462
1463 Breakpoints may still be inserted because the inferior may be running in
1464 non-stop mode, or because GDB changed the default setting to leave all
1465 breakpoints inserted in all-stop mode when all threads are stopped. */
1466 remove_breakpoints_inf (inf);
1467
1468 detach_amd_dbgapi (inf);
1469 beneath ()->detach (inf, from_tty);
1470 }
1471
1472 void
1473 amd_dbgapi_target::fetch_registers (struct regcache *regcache, int regno)
1474 {
1475 if (!ptid_is_gpu (regcache->ptid ()))
1476 {
1477 beneath ()->fetch_registers (regcache, regno);
1478 return;
1479 }
1480
1481 struct gdbarch *gdbarch = regcache->arch ();
1482 gdb_assert (is_amdgpu_arch (gdbarch));
1483
1484 amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch);
1485 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
1486 gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
1487 amd_dbgapi_status_t status
1488 = amd_dbgapi_read_register (wave_id, tdep->register_ids[regno], 0,
1489 register_type (gdbarch, regno)->length (),
1490 raw);
1491
1492 if (status == AMD_DBGAPI_STATUS_SUCCESS)
1493 regcache->raw_supply (regno, raw);
1494 else if (status != AMD_DBGAPI_STATUS_ERROR_REGISTER_NOT_AVAILABLE)
1495 warning (_("Couldn't read register %s (#%d) (%s)."),
1496 gdbarch_register_name (gdbarch, regno), regno,
1497 get_status_string (status));
1498 }
1499
1500 void
1501 amd_dbgapi_target::store_registers (struct regcache *regcache, int regno)
1502 {
1503 if (!ptid_is_gpu (regcache->ptid ()))
1504 {
1505 beneath ()->store_registers (regcache, regno);
1506 return;
1507 }
1508
1509 struct gdbarch *gdbarch = regcache->arch ();
1510 gdb_assert (is_amdgpu_arch (gdbarch));
1511
1512 gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
1513 regcache->raw_collect (regno, &raw);
1514
1515 amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch);
1516
1517 /* If the register has read-only bits, invalidate the value in the regcache
1518 as the value actually written may differ. */
1519 if (tdep->register_properties[regno]
1520 & AMD_DBGAPI_REGISTER_PROPERTY_READONLY_BITS)
1521 regcache->invalidate (regno);
1522
1523 /* Invalidate all volatile registers if this register has the invalidate
1524 volatile property. For example, writing to VCC may change the content
1525 of STATUS.VCCZ. */
1526 if (tdep->register_properties[regno]
1527 & AMD_DBGAPI_REGISTER_PROPERTY_INVALIDATE_VOLATILE)
1528 {
1529 for (size_t r = 0; r < tdep->register_properties.size (); ++r)
1530 if (tdep->register_properties[r] & AMD_DBGAPI_REGISTER_PROPERTY_VOLATILE)
1531 regcache->invalidate (r);
1532 }
1533
1534 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
1535 amd_dbgapi_status_t status
1536 = amd_dbgapi_write_register (wave_id, tdep->register_ids[regno], 0,
1537 register_type (gdbarch, regno)->length (),
1538 raw);
1539
1540 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1541 warning (_("Couldn't write register %s (#%d)."),
1542 gdbarch_register_name (gdbarch, regno), regno);
1543 }
1544
1545 struct gdbarch *
1546 amd_dbgapi_target::thread_architecture (ptid_t ptid)
1547 {
1548 if (!ptid_is_gpu (ptid))
1549 return beneath ()->thread_architecture (ptid);
1550
1551 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
1552 wave IDs are unique, and aren't reused. */
1553 if (ptid.tid () == m_cached_arch_tid)
1554 return m_cached_arch;
1555
1556 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (ptid);
1557 amd_dbgapi_architecture_id_t architecture_id;
1558 amd_dbgapi_status_t status;
1559
1560 status = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_ARCHITECTURE,
1561 sizeof (architecture_id),
1562 &architecture_id);
1563 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1564 error (_("Couldn't get architecture for wave_%ld"), ptid.tid ());
1565
1566 uint32_t elf_amdgpu_machine;
1567 status = amd_dbgapi_architecture_get_info
1568 (architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE,
1569 sizeof (elf_amdgpu_machine), &elf_amdgpu_machine);
1570 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1571 error (_("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1572 architecture_id.handle);
1573
1574 struct gdbarch_info info;
1575 info.bfd_arch_info = bfd_lookup_arch (bfd_arch_amdgcn, elf_amdgpu_machine);
1576 info.byte_order = BFD_ENDIAN_LITTLE;
1577
1578 m_cached_arch_tid = ptid.tid ();
1579 m_cached_arch = gdbarch_find_by_info (info);
1580 if (m_cached_arch == nullptr)
1581 error (_("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine);
1582
1583 return m_cached_arch;
1584 }
1585
1586 void
1587 amd_dbgapi_target::thread_events (int enable)
1588 {
1589 m_report_thread_events = enable;
1590 beneath ()->thread_events (enable);
1591 }
1592
1593 void
1594 amd_dbgapi_target::update_thread_list ()
1595 {
1596 for (inferior *inf : all_inferiors ())
1597 {
1598 amd_dbgapi_process_id_t process_id
1599 = get_amd_dbgapi_process_id (inf);
1600 if (process_id == AMD_DBGAPI_PROCESS_NONE)
1601 {
1602 /* The inferior may not be attached yet. */
1603 continue;
1604 }
1605
1606 size_t count;
1607 amd_dbgapi_wave_id_t *wave_list;
1608 amd_dbgapi_changed_t changed;
1609 amd_dbgapi_status_t status
1610 = amd_dbgapi_process_wave_list (process_id, &count, &wave_list,
1611 &changed);
1612 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1613 error (_("amd_dbgapi_wave_list failed (%s)"),
1614 get_status_string (status));
1615
1616 if (changed == AMD_DBGAPI_CHANGED_NO)
1617 continue;
1618
1619 /* Create a set and free the wave list. */
1620 std::set<ptid_t::tid_type> threads;
1621 for (size_t i = 0; i < count; ++i)
1622 threads.emplace (wave_list[i].handle);
1623
1624 xfree (wave_list);
1625
1626 /* Prune the wave_ids that already have a thread_info. Any thread_info
1627 which does not have a corresponding wave_id represents a wave which
1628 is gone at this point and should be deleted. */
1629 for (thread_info *tp : inf->threads_safe ())
1630 if (ptid_is_gpu (tp->ptid) && tp->state != THREAD_EXITED)
1631 {
1632 auto it = threads.find (tp->ptid.tid ());
1633
1634 if (it == threads.end ())
1635 delete_thread (tp);
1636 else
1637 threads.erase (it);
1638 }
1639
1640 /* The wave_ids that are left require a new thread_info. */
1641 for (ptid_t::tid_type tid : threads)
1642 {
1643 ptid_t wave_ptid
1644 = make_gpu_ptid (inf->pid, amd_dbgapi_wave_id_t {tid});
1645
1646 add_thread_silent (inf->process_target (), wave_ptid);
1647 set_running (inf->process_target (), wave_ptid, true);
1648 set_executing (inf->process_target (), wave_ptid, true);
1649 }
1650 }
1651
1652 /* Give the beneath target a chance to do extra processing. */
1653 this->beneath ()->update_thread_list ();
1654 }
1655
1656 /* inferior_created observer. */
1657
1658 static void
1659 amd_dbgapi_target_inferior_created (inferior *inf)
1660 {
1661 /* If the inferior is not running on the native target (e.g. it is running
1662 on a remote target), we don't want to deal with it. */
1663 if (inf->process_target () != get_native_target ())
1664 return;
1665
1666 attach_amd_dbgapi (inf);
1667 }
1668
1669 /* inferior_execd observer. */
1670
1671 static void
1672 amd_dbgapi_inferior_execd (inferior *exec_inf, inferior *follow_inf)
1673 {
1674 /* The inferior has EXEC'd and the process image has changed. The dbgapi is
1675 attached to the old process image, so we need to detach and re-attach to
1676 the new process image. */
1677 detach_amd_dbgapi (exec_inf);
1678 attach_amd_dbgapi (follow_inf);
1679 }
1680
1681 /* inferior_forked observer. */
1682
1683 static void
1684 amd_dbgapi_inferior_forked (inferior *parent_inf, inferior *child_inf,
1685 target_waitkind fork_kind)
1686 {
1687 if (child_inf != nullptr && fork_kind != TARGET_WAITKIND_VFORKED)
1688 {
1689 scoped_restore_current_thread restore_thread;
1690 switch_to_thread (*child_inf->threads ().begin ());
1691 attach_amd_dbgapi (child_inf);
1692 }
1693 }
1694
1695 /* inferior_exit observer.
1696
1697 This covers normal exits, but also detached inferiors (including detached
1698 fork parents). */
1699
1700 static void
1701 amd_dbgapi_inferior_exited (inferior *inf)
1702 {
1703 detach_amd_dbgapi (inf);
1704 }
1705
1706 /* inferior_pre_detach observer. */
1707
1708 static void
1709 amd_dbgapi_inferior_pre_detach (inferior *inf)
1710 {
1711 /* We need to amd-dbgapi-detach before we ptrace-detach. If the amd-dbgapi
1712 target isn't pushed, do that now. If the amd-dbgapi target is pushed,
1713 we'll do it in amd_dbgapi_target::detach. */
1714 if (!inf->target_is_pushed (&the_amd_dbgapi_target))
1715 detach_amd_dbgapi (inf);
1716 }
1717
1718 /* get_os_pid callback. */
1719
1720 static amd_dbgapi_status_t
1721 amd_dbgapi_get_os_pid_callback
1722 (amd_dbgapi_client_process_id_t client_process_id, pid_t *pid)
1723 {
1724 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
1725
1726 if (inf->pid == 0)
1727 return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
1728
1729 *pid = inf->pid;
1730 return AMD_DBGAPI_STATUS_SUCCESS;
1731 }
1732
1733 /* insert_breakpoint callback. */
1734
1735 static amd_dbgapi_status_t
1736 amd_dbgapi_insert_breakpoint_callback
1737 (amd_dbgapi_client_process_id_t client_process_id,
1738 amd_dbgapi_global_address_t address,
1739 amd_dbgapi_breakpoint_id_t breakpoint_id)
1740 {
1741 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
1742 struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1743
1744 auto it = info->breakpoint_map.find (breakpoint_id.handle);
1745 if (it != info->breakpoint_map.end ())
1746 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
1747
1748 /* We need to find the address in the given inferior's program space. */
1749 scoped_restore_current_thread restore_thread;
1750 switch_to_inferior_no_thread (inf);
1751
1752 /* Create a new breakpoint. */
1753 struct obj_section *section = find_pc_section (address);
1754 if (section == nullptr || section->objfile == nullptr)
1755 return AMD_DBGAPI_STATUS_ERROR;
1756
1757 std::unique_ptr<breakpoint> bp_up
1758 (new amd_dbgapi_target_breakpoint (section->objfile->arch (), address));
1759
1760 breakpoint *bp = install_breakpoint (true, std::move (bp_up), 1);
1761
1762 info->breakpoint_map.emplace (breakpoint_id.handle, bp);
1763 return AMD_DBGAPI_STATUS_SUCCESS;
1764 }
1765
1766 /* remove_breakpoint callback. */
1767
1768 static amd_dbgapi_status_t
1769 amd_dbgapi_remove_breakpoint_callback
1770 (amd_dbgapi_client_process_id_t client_process_id,
1771 amd_dbgapi_breakpoint_id_t breakpoint_id)
1772 {
1773 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
1774 struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1775
1776 auto it = info->breakpoint_map.find (breakpoint_id.handle);
1777 if (it == info->breakpoint_map.end ())
1778 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
1779
1780 delete_breakpoint (it->second);
1781 info->breakpoint_map.erase (it);
1782
1783 return AMD_DBGAPI_STATUS_SUCCESS;
1784 }
1785
1786 /* Style for some kinds of messages. */
1787
1788 static cli_style_option fatal_error_style
1789 ("amd_dbgapi_fatal_error", ui_file_style::RED);
1790 static cli_style_option warning_style
1791 ("amd_dbgapi_warning", ui_file_style::YELLOW);
1792
1793 /* BLACK + BOLD means dark gray. */
1794 static cli_style_option trace_style
1795 ("amd_dbgapi_trace", ui_file_style::BLACK, ui_file_style::BOLD);
1796
1797 /* log_message callback. */
1798
1799 static void
1800 amd_dbgapi_log_message_callback (amd_dbgapi_log_level_t level,
1801 const char *message)
1802 {
1803 gdb::optional<target_terminal::scoped_restore_terminal_state> tstate;
1804
1805 if (target_supports_terminal_ours ())
1806 {
1807 tstate.emplace ();
1808 target_terminal::ours_for_output ();
1809 }
1810
1811 /* Error and warning messages are meant to be printed to the user. */
1812 if (level == AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
1813 || level == AMD_DBGAPI_LOG_LEVEL_WARNING)
1814 {
1815 begin_line ();
1816 ui_file_style style = (level == AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
1817 ? fatal_error_style : warning_style).style ();
1818 gdb_printf (gdb_stderr, "%ps\n", styled_string (style, message));
1819 return;
1820 }
1821
1822 /* Print other messages as debug logs. TRACE and VERBOSE messages are
1823 very verbose, print them dark grey so it's easier to spot other messages
1824 through the flood. */
1825 if (level >= AMD_DBGAPI_LOG_LEVEL_TRACE)
1826 {
1827 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%ps",
1828 styled_string (trace_style.style (), message));
1829 return;
1830 }
1831
1832 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%s",
1833 message);
1834 }
1835
1836 /* Callbacks passed to amd_dbgapi_initialize. */
1837
1838 static amd_dbgapi_callbacks_t dbgapi_callbacks = {
1839 .allocate_memory = malloc,
1840 .deallocate_memory = free,
1841 .get_os_pid = amd_dbgapi_get_os_pid_callback,
1842 .insert_breakpoint = amd_dbgapi_insert_breakpoint_callback,
1843 .remove_breakpoint = amd_dbgapi_remove_breakpoint_callback,
1844 .log_message = amd_dbgapi_log_message_callback,
1845 };
1846
1847 void
1848 amd_dbgapi_target::close ()
1849 {
1850 if (amd_dbgapi_async_event_handler != nullptr)
1851 delete_async_event_handler (&amd_dbgapi_async_event_handler);
1852 }
1853
1854 /* List of set/show debug amd-dbgapi-lib commands. */
1855 struct cmd_list_element *set_debug_amd_dbgapi_lib_list;
1856 struct cmd_list_element *show_debug_amd_dbgapi_lib_list;
1857
1858 /* Mapping from amd-dbgapi log level enum values to text. */
1859
1860 static constexpr const char *debug_amd_dbgapi_lib_log_level_enums[] =
1861 {
1862 /* [AMD_DBGAPI_LOG_LEVEL_NONE] = */ "off",
1863 /* [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR] = */ "error",
1864 /* [AMD_DBGAPI_LOG_LEVEL_WARNING] = */ "warning",
1865 /* [AMD_DBGAPI_LOG_LEVEL_INFO] = */ "info",
1866 /* [AMD_DBGAPI_LOG_LEVEL_TRACE] = */ "trace",
1867 /* [AMD_DBGAPI_LOG_LEVEL_VERBOSE] = */ "verbose",
1868 nullptr
1869 };
1870
1871 /* Storage for "set debug amd-dbgapi-lib log-level". */
1872
1873 static const char *debug_amd_dbgapi_lib_log_level
1874 = debug_amd_dbgapi_lib_log_level_enums[AMD_DBGAPI_LOG_LEVEL_WARNING];
1875
1876 /* Get the amd-dbgapi library log level requested by the user. */
1877
1878 static amd_dbgapi_log_level_t
1879 get_debug_amd_dbgapi_lib_log_level ()
1880 {
1881 for (size_t pos = 0;
1882 debug_amd_dbgapi_lib_log_level_enums[pos] != nullptr;
1883 ++pos)
1884 if (debug_amd_dbgapi_lib_log_level
1885 == debug_amd_dbgapi_lib_log_level_enums[pos])
1886 return static_cast<amd_dbgapi_log_level_t> (pos);
1887
1888 gdb_assert_not_reached ("invalid log level");
1889 }
1890
1891 /* Callback for "set debug amd-dbgapi log-level", apply the selected log level
1892 to the library. */
1893
1894 static void
1895 set_debug_amd_dbgapi_lib_log_level (const char *args, int from_tty,
1896 struct cmd_list_element *c)
1897 {
1898 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ());
1899 }
1900
1901 /* Callback for "show debug amd-dbgapi log-level". */
1902
1903 static void
1904 show_debug_amd_dbgapi_lib_log_level (struct ui_file *file, int from_tty,
1905 struct cmd_list_element *c,
1906 const char *value)
1907 {
1908 gdb_printf (file, _("The amd-dbgapi library log level is %s.\n"), value);
1909 }
1910
1911 /* If the amd-dbgapi library is not attached to any process, finalize and
1912 re-initialize it so that the handle ID numbers will all start from the
1913 beginning again. This is only for convenience, not essential. */
1914
1915 static void
1916 maybe_reset_amd_dbgapi ()
1917 {
1918 for (inferior *inf : all_non_exited_inferiors ())
1919 {
1920 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1921
1922 if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
1923 return;
1924 }
1925
1926 amd_dbgapi_status_t status = amd_dbgapi_finalize ();
1927 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1928 error (_("amd-dbgapi failed to finalize (%s)"),
1929 get_status_string (status));
1930
1931 status = amd_dbgapi_initialize (&dbgapi_callbacks);
1932 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1933 error (_("amd-dbgapi failed to initialize (%s)"),
1934 get_status_string (status));
1935 }
1936
1937 extern initialize_file_ftype _initialize_amd_dbgapi_target;
1938
1939 void
1940 _initialize_amd_dbgapi_target ()
1941 {
1942 /* Make sure the loaded debugger library version is greater than or equal to
1943 the one used to build GDB. */
1944 uint32_t major, minor, patch;
1945 amd_dbgapi_get_version (&major, &minor, &patch);
1946 if (major != AMD_DBGAPI_VERSION_MAJOR || minor < AMD_DBGAPI_VERSION_MINOR)
1947 error (_("amd-dbgapi library version mismatch, got %d.%d.%d, need %d.%d+"),
1948 major, minor, patch, AMD_DBGAPI_VERSION_MAJOR,
1949 AMD_DBGAPI_VERSION_MINOR);
1950
1951 /* Initialize the AMD Debugger API. */
1952 amd_dbgapi_status_t status = amd_dbgapi_initialize (&dbgapi_callbacks);
1953 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1954 error (_("amd-dbgapi failed to initialize (%s)"),
1955 get_status_string (status));
1956
1957 /* Set the initial log level. */
1958 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ());
1959
1960 /* Install observers. */
1961 gdb::observers::inferior_created.attach
1962 (amd_dbgapi_target_inferior_created,
1963 amd_dbgapi_target_inferior_created_observer_token, "amd-dbgapi");
1964 gdb::observers::inferior_execd.attach (amd_dbgapi_inferior_execd, "amd-dbgapi");
1965 gdb::observers::inferior_forked.attach (amd_dbgapi_inferior_forked, "amd-dbgapi");
1966 gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi");
1967 gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi");
1968
1969 add_basic_prefix_cmd ("amd-dbgapi-lib", no_class,
1970 _("Generic command for setting amd-dbgapi library "
1971 "debugging flags."),
1972 &set_debug_amd_dbgapi_lib_list, 0, &setdebuglist);
1973
1974 add_show_prefix_cmd ("amd-dbgapi-lib", no_class,
1975 _("Generic command for showing amd-dbgapi library "
1976 "debugging flags."),
1977 &show_debug_amd_dbgapi_lib_list, 0, &showdebuglist);
1978
1979 add_setshow_enum_cmd ("log-level", class_maintenance,
1980 debug_amd_dbgapi_lib_log_level_enums,
1981 &debug_amd_dbgapi_lib_log_level,
1982 _("Set the amd-dbgapi library log level."),
1983 _("Show the amd-dbgapi library log level."),
1984 _("off == no logging is enabled\n"
1985 "error == fatal errors are reported\n"
1986 "warning == fatal errors and warnings are reported\n"
1987 "info == fatal errors, warnings, and info "
1988 "messages are reported\n"
1989 "trace == fatal errors, warnings, info, and "
1990 "API tracing messages are reported\n"
1991 "verbose == all messages are reported"),
1992 set_debug_amd_dbgapi_lib_log_level,
1993 show_debug_amd_dbgapi_lib_log_level,
1994 &set_debug_amd_dbgapi_lib_list,
1995 &show_debug_amd_dbgapi_lib_list);
1996
1997 add_setshow_boolean_cmd ("amd-dbgapi", class_maintenance,
1998 &debug_amd_dbgapi,
1999 _("Set debugging of amd-dbgapi target."),
2000 _("Show debugging of amd-dbgapi target."),
2001 _("\
2002 When on, print debug messages relating to the amd-dbgapi target."),
2003 nullptr, nullptr,
2004 &setdebuglist, &showdebuglist);
2005 }