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