Add translations for various sub-directories
[binutils-gdb.git] / gdb / amd-dbgapi-target.c
blob2bb79acd76f0dc88fb332d9fb567e7cb4fb0dcb8
1 /* Target used to communicate with the AMD Debugger API.
3 Copyright (C) 2019-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
21 #include "amd-dbgapi-target.h"
22 #include "amdgpu-tdep.h"
23 #include "async-event.h"
24 #include "cli/cli-cmds.h"
25 #include "cli/cli-decode.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"
35 /* When true, print debug messages relating to the amd-dbgapi target. */
37 static bool debug_amd_dbgapi = false;
39 /* Make a copy of S styled in green. */
41 static std::string
42 make_green (const char *s)
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 ();
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. */
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";
58 /* Styled variants of the above. */
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);
65 /* Return the styled or unstyled variant of the amd-dbgapi module name,
66 depending on whether gdb_stdlog can emit colors. */
68 static const char *
69 amd_dbgapi_debug_module ()
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;
77 /* Same as the above, but for the amd-dbgapi-lib module name. */
79 static const char *
80 amd_dbgapi_lib_debug_module ()
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;
88 /* Print an amd-dbgapi debug statement. */
90 #define amd_dbgapi_debug_printf(fmt, ...) \
91 debug_prefixed_printf_cond (debug_amd_dbgapi, \
92 amd_dbgapi_debug_module (), \
93 fmt, ##__VA_ARGS__)
95 /* Print amd-dbgapi start/end debug statements. */
97 #define AMD_DBGAPI_SCOPED_DEBUG_START_END(fmt, ...) \
98 scoped_debug_start_end (debug_amd_dbgapi, amd_dbgapi_debug_module (), \
99 fmt, ##__VA_ARGS__)
101 /* inferior_created observer token. */
103 static gdb::observers::token amd_dbgapi_target_inferior_created_observer_token;
105 const gdb::observers::token &
106 get_amd_dbgapi_target_inferior_created_observer_token ()
108 return amd_dbgapi_target_inferior_created_observer_token;
111 /* A type holding coordinates, etc. info for a given wave. */
113 struct wave_coordinates
115 /* The wave. Set by the ctor. */
116 amd_dbgapi_wave_id_t wave_id;
118 /* All these fields are initialized here to a value that is printed
119 as "?". */
120 amd_dbgapi_dispatch_id_t dispatch_id = AMD_DBGAPI_DISPATCH_NONE;
121 amd_dbgapi_queue_id_t queue_id = AMD_DBGAPI_QUEUE_NONE;
122 amd_dbgapi_agent_id_t agent_id = AMD_DBGAPI_AGENT_NONE;
123 uint32_t group_ids[3] {UINT32_MAX, UINT32_MAX, UINT32_MAX};
124 uint32_t wave_in_group = UINT32_MAX;
126 explicit wave_coordinates (amd_dbgapi_wave_id_t wave_id)
127 : wave_id (wave_id)
130 /* Return the target ID string for the wave this wave_coordinates is
131 for. */
132 std::string to_string () const;
134 /* Pull out coordinates info from the amd-dbgapi library. */
135 void fetch ();
138 /* A type holding info about a given wave. */
140 struct wave_info
142 /* We cache the coordinates info because we need it after a wave
143 exits. The wave's ID is here. */
144 wave_coordinates coords;
146 /* The last resume_mode passed to amd_dbgapi_wave_resume for this
147 wave. We track this because we are guaranteed to see a
148 WAVE_COMMAND_TERMINATED event if a stepping wave terminates, and
149 we need to know to not delete such a wave until we process that
150 event. */
151 amd_dbgapi_resume_mode_t last_resume_mode = AMD_DBGAPI_RESUME_MODE_NORMAL;
153 /* Whether we've called amd_dbgapi_wave_stop for this wave and are
154 waiting for its stop event. Similarly, we track this because
155 we're guaranteed to get a WAVE_COMMAND_TERMINATED event if the
156 wave terminates while being stopped. */
157 bool stopping = false;
159 explicit wave_info (amd_dbgapi_wave_id_t wave_id)
160 : coords (wave_id)
162 coords.fetch ();
166 /* Big enough to hold the size of the largest register in bytes. */
167 #define AMDGPU_MAX_REGISTER_SIZE 256
169 /* amd-dbgapi-specific inferior data. */
171 struct amd_dbgapi_inferior_info
173 explicit amd_dbgapi_inferior_info (inferior *inf,
174 bool precise_memory_requested = false)
175 : inf (inf)
177 precise_memory.requested = precise_memory_requested;
180 /* Backlink to inferior. */
181 inferior *inf;
183 /* The amd_dbgapi_process_id for this inferior. */
184 amd_dbgapi_process_id_t process_id = AMD_DBGAPI_PROCESS_NONE;
186 /* The amd_dbgapi_notifier_t for this inferior. */
187 amd_dbgapi_notifier_t notifier = -1;
189 /* The status of the inferior's runtime support. */
190 amd_dbgapi_runtime_state_t runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED;
192 /* This value mirrors the current "forward progress needed" value for this
193 process in amd-dbgapi. It is used to avoid unnecessary calls to
194 amd_dbgapi_process_set_progress, to reduce the noise in the logs.
196 Initialized to true, since that's the default in amd-dbgapi too. */
197 bool forward_progress_required = true;
199 struct
201 /* Whether precise memory reporting is requested. */
202 bool requested;
204 /* Whether precise memory was requested and successfully enabled by
205 dbgapi (it may not be available for the current hardware, for
206 instance). */
207 bool enabled = false;
208 } precise_memory;
210 std::unordered_map<decltype (amd_dbgapi_breakpoint_id_t::handle),
211 struct breakpoint *>
212 breakpoint_map;
214 /* List of pending events the amd-dbgapi target retrieved from the dbgapi. */
215 std::list<std::pair<ptid_t, target_waitstatus>> wave_events;
217 /* Map of wave ID to wave_info. We cache wave_info objects because
218 we need to access the info after the wave is gone, in the thread
219 exit nofication. E.g.:
220 [AMDGPU Wave 1:4:1:1 (0,0,0)/0 exited]
222 wave_info objects are added when we first see the wave, and
223 removed from a thread_deleted observer. */
224 std::unordered_map<decltype (amd_dbgapi_wave_id_t::handle), wave_info>
225 wave_info_map;
228 static amd_dbgapi_event_id_t process_event_queue
229 (amd_dbgapi_process_id_t process_id,
230 amd_dbgapi_event_kind_t until_event_kind = AMD_DBGAPI_EVENT_KIND_NONE);
232 static const target_info amd_dbgapi_target_info = {
233 "amd-dbgapi",
234 N_("AMD Debugger API"),
235 N_("GPU debugging using the AMD Debugger API")
238 static amd_dbgapi_log_level_t get_debug_amd_dbgapi_lib_log_level ();
240 struct amd_dbgapi_target final : public target_ops
242 const target_info &
243 info () const override
245 return amd_dbgapi_target_info;
247 strata
248 stratum () const override
250 return arch_stratum;
253 void close () override;
254 void mourn_inferior () override;
255 void detach (inferior *inf, int from_tty) override;
257 void async (bool enable) override;
259 bool has_pending_events () override;
260 ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
261 void resume (ptid_t, int, enum gdb_signal) override;
262 void commit_resumed () override;
263 void stop (ptid_t ptid) override;
265 void fetch_registers (struct regcache *, int) override;
266 void store_registers (struct regcache *, int) override;
268 void update_thread_list () override;
270 struct gdbarch *thread_architecture (ptid_t) override;
272 void thread_events (bool enable) override;
274 std::string pid_to_str (ptid_t ptid) override;
276 const char *thread_name (thread_info *tp) override;
278 const char *extra_thread_info (thread_info *tp) override;
280 bool thread_alive (ptid_t ptid) override;
282 enum target_xfer_status xfer_partial (enum target_object object,
283 const char *annex, gdb_byte *readbuf,
284 const gdb_byte *writebuf,
285 ULONGEST offset, ULONGEST len,
286 ULONGEST *xfered_len) override;
288 bool stopped_by_watchpoint () override;
290 bool stopped_by_sw_breakpoint () override;
291 bool stopped_by_hw_breakpoint () override;
293 private:
294 /* True if we must report thread events. */
295 bool m_report_thread_events = false;
297 /* Cache for the last value returned by thread_architecture. */
298 gdbarch *m_cached_arch = nullptr;
299 ptid_t::tid_type m_cached_arch_tid = 0;
302 static struct amd_dbgapi_target the_amd_dbgapi_target;
304 /* Per-inferior data key. */
306 static const registry<inferior>::key<amd_dbgapi_inferior_info>
307 amd_dbgapi_inferior_data;
309 /* Fetch the amd_dbgapi_inferior_info data for the given inferior. */
311 static struct amd_dbgapi_inferior_info *
312 get_amd_dbgapi_inferior_info (struct inferior *inferior)
314 amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (inferior);
316 if (info == nullptr)
317 info = amd_dbgapi_inferior_data.emplace (inferior, inferior);
319 return info;
322 /* The async event handler registered with the event loop, indicating that we
323 might have events to report to the core and that we'd like our wait method
324 to be called.
326 This is nullptr when async is disabled and non-nullptr when async is
327 enabled.
329 It is marked when a notifier fd tells us there's an event available. The
330 callback triggers handle_inferior_event in order to pull the event from
331 amd-dbgapi and handle it. */
333 static async_event_handler *amd_dbgapi_async_event_handler = nullptr;
335 std::string
336 wave_coordinates::to_string () const
338 std::string str = "AMDGPU Wave";
340 str += (agent_id != AMD_DBGAPI_AGENT_NONE
341 ? string_printf (" %ld", agent_id.handle)
342 : " ?");
344 str += (queue_id != AMD_DBGAPI_QUEUE_NONE
345 ? string_printf (":%ld", queue_id.handle)
346 : ":?");
348 str += (dispatch_id != AMD_DBGAPI_DISPATCH_NONE
349 ? string_printf (":%ld", dispatch_id.handle)
350 : ":?");
352 str += string_printf (":%ld", wave_id.handle);
354 str += (group_ids[0] != UINT32_MAX
355 ? string_printf (" (%d,%d,%d)", group_ids[0], group_ids[1],
356 group_ids[2])
357 : " (?,?,?)");
359 str += (wave_in_group != UINT32_MAX
360 ? string_printf ("/%d", wave_in_group)
361 : "/?");
363 return str;
366 /* Read in wave_info for WAVE_ID. */
368 void
369 wave_coordinates::fetch ()
371 /* Any field that fails to be read is left with its in-class
372 initialized value, which is printed as "?". */
374 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_AGENT,
375 sizeof (agent_id), &agent_id);
376 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_QUEUE,
377 sizeof (queue_id), &queue_id);
378 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_DISPATCH,
379 sizeof (dispatch_id), &dispatch_id);
381 amd_dbgapi_wave_get_info (wave_id,
382 AMD_DBGAPI_WAVE_INFO_WORKGROUP_COORD,
383 sizeof (group_ids), &group_ids);
385 amd_dbgapi_wave_get_info (wave_id,
386 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORKGROUP,
387 sizeof (wave_in_group), &wave_in_group);
390 /* Get the wave_info object for TP, from the wave_info map. It is
391 assumed that the wave is in the map. */
393 static wave_info &
394 get_thread_wave_info (thread_info *tp)
396 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (tp->inf);
397 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (tp->ptid);
399 auto it = info->wave_info_map.find (wave_id.handle);
400 gdb_assert (it != info->wave_info_map.end ());
402 return it->second;
405 /* Clear our async event handler. */
407 static void
408 async_event_handler_clear ()
410 gdb_assert (amd_dbgapi_async_event_handler != nullptr);
411 clear_async_event_handler (amd_dbgapi_async_event_handler);
414 /* Mark our async event handler. */
416 static void
417 async_event_handler_mark ()
419 gdb_assert (amd_dbgapi_async_event_handler != nullptr);
420 mark_async_event_handler (amd_dbgapi_async_event_handler);
423 /* Set forward progress requirement to REQUIRE for all processes of PROC_TARGET
424 matching PTID. */
426 static void
427 require_forward_progress (ptid_t ptid, process_stratum_target *proc_target,
428 bool require)
430 for (inferior *inf : all_inferiors (proc_target))
432 if (ptid != minus_one_ptid && inf->pid != ptid.pid ())
433 continue;
435 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
437 if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
438 continue;
440 /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */
441 if (info->forward_progress_required == require)
442 continue;
444 amd_dbgapi_status_t status
445 = amd_dbgapi_process_set_progress
446 (info->process_id, (require
447 ? AMD_DBGAPI_PROGRESS_NORMAL
448 : AMD_DBGAPI_PROGRESS_NO_FORWARD));
449 gdb_assert (status == AMD_DBGAPI_STATUS_SUCCESS);
451 info->forward_progress_required = require;
453 /* If ptid targets a single inferior and we have found it, no need to
454 continue. */
455 if (ptid != minus_one_ptid)
456 break;
460 /* See amd-dbgapi-target.h. */
462 amd_dbgapi_process_id_t
463 get_amd_dbgapi_process_id (inferior *inf)
465 return get_amd_dbgapi_inferior_info (inf)->process_id;
468 /* A breakpoint dbgapi wants us to insert, to handle shared library
469 loading/unloading. */
471 struct amd_dbgapi_target_breakpoint : public code_breakpoint
473 amd_dbgapi_target_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
474 : code_breakpoint (gdbarch, bp_breakpoint)
476 symtab_and_line sal;
477 sal.pc = address;
478 sal.section = find_pc_overlay (sal.pc);
479 sal.pspace = current_program_space;
480 add_location (sal);
482 pspace = current_program_space;
483 disposition = disp_donttouch;
486 void re_set (program_space *) override;
487 void check_status (struct bpstat *bs) override;
490 void
491 amd_dbgapi_target_breakpoint::re_set (program_space *)
493 /* Nothing. */
496 void
497 amd_dbgapi_target_breakpoint::check_status (struct bpstat *bs)
499 struct inferior *inf = current_inferior ();
500 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
501 amd_dbgapi_status_t status;
503 bs->stop = 0;
504 bs->print_it = print_it_noop;
506 /* Find the address the breakpoint is set at. */
507 auto match_breakpoint
508 = [bs] (const decltype (info->breakpoint_map)::value_type &value)
509 { return value.second == bs->breakpoint_at; };
510 auto it
511 = std::find_if (info->breakpoint_map.begin (), info->breakpoint_map.end (),
512 match_breakpoint);
514 if (it == info->breakpoint_map.end ())
515 error (_("Could not find breakpoint_id for breakpoint at %s"),
516 paddress (inf->arch (), bs->bp_location_at->address));
518 amd_dbgapi_breakpoint_id_t breakpoint_id { it->first };
519 amd_dbgapi_breakpoint_action_t action;
521 status = amd_dbgapi_report_breakpoint_hit
522 (breakpoint_id,
523 reinterpret_cast<amd_dbgapi_client_thread_id_t> (inferior_thread ()),
524 &action);
526 if (status != AMD_DBGAPI_STATUS_SUCCESS)
527 error (_("amd_dbgapi_report_breakpoint_hit failed for breakpoint %ld "
528 "at %s (%s)"),
529 breakpoint_id.handle, paddress (inf->arch (), bs->bp_location_at->address),
530 get_status_string (status));
532 if (action == AMD_DBGAPI_BREAKPOINT_ACTION_RESUME)
533 return;
535 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
536 a breakpoint resume event for this breakpoint_id is seen. */
537 amd_dbgapi_event_id_t resume_event_id
538 = process_event_queue (info->process_id,
539 AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
541 /* We should always get a breakpoint_resume event after processing all
542 events generated by reporting the breakpoint hit. */
543 gdb_assert (resume_event_id != AMD_DBGAPI_EVENT_NONE);
545 amd_dbgapi_breakpoint_id_t resume_breakpoint_id;
546 status = amd_dbgapi_event_get_info (resume_event_id,
547 AMD_DBGAPI_EVENT_INFO_BREAKPOINT,
548 sizeof (resume_breakpoint_id),
549 &resume_breakpoint_id);
551 if (status != AMD_DBGAPI_STATUS_SUCCESS)
552 error (_("amd_dbgapi_event_get_info failed (%s)"), get_status_string (status));
554 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint]
555 sequences cannot interleave, so this breakpoint resume event must be
556 for our breakpoint_id. */
557 if (resume_breakpoint_id != breakpoint_id)
558 error (_("breakpoint resume event is not for this breakpoint. "
559 "Expected breakpoint_%ld, got breakpoint_%ld"),
560 breakpoint_id.handle, resume_breakpoint_id.handle);
562 amd_dbgapi_event_processed (resume_event_id);
565 bool
566 amd_dbgapi_target::thread_alive (ptid_t ptid)
568 if (!ptid_is_gpu (ptid))
569 return beneath ()->thread_alive (ptid);
571 /* Check that the wave_id is valid. */
573 amd_dbgapi_wave_state_t state;
574 amd_dbgapi_status_t status
575 = amd_dbgapi_wave_get_info (get_amd_dbgapi_wave_id (ptid),
576 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state),
577 &state);
578 return status == AMD_DBGAPI_STATUS_SUCCESS;
581 const char *
582 amd_dbgapi_target::thread_name (thread_info *tp)
584 if (!ptid_is_gpu (tp->ptid))
585 return beneath ()->thread_name (tp);
587 return nullptr;
590 std::string
591 amd_dbgapi_target::pid_to_str (ptid_t ptid)
593 if (!ptid_is_gpu (ptid))
594 return beneath ()->pid_to_str (ptid);
596 process_stratum_target *proc_target = current_inferior ()->process_target ();
597 inferior *inf = find_inferior_pid (proc_target, ptid.pid ());
598 gdb_assert (inf != nullptr);
599 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
601 auto wave_id = get_amd_dbgapi_wave_id (ptid);
603 auto it = info->wave_info_map.find (wave_id.handle);
604 if (it != info->wave_info_map.end ())
605 return it->second.coords.to_string ();
607 /* A wave we don't know about. Shouldn't usually happen, but
608 asserting and bringing down the session is a bit too harsh. Just
609 print all unknown info as "?"s. */
610 return wave_coordinates (wave_id).to_string ();
613 const char *
614 amd_dbgapi_target::extra_thread_info (thread_info *tp)
616 if (!ptid_is_gpu (tp->ptid))
617 beneath ()->extra_thread_info (tp);
619 return nullptr;
622 target_xfer_status
623 amd_dbgapi_target::xfer_partial (enum target_object object, const char *annex,
624 gdb_byte *readbuf, const gdb_byte *writebuf,
625 ULONGEST offset, ULONGEST requested_len,
626 ULONGEST *xfered_len)
628 std::optional<scoped_restore_current_thread> maybe_restore_thread;
630 if (!ptid_is_gpu (inferior_ptid))
631 return beneath ()->xfer_partial (object, annex, readbuf, writebuf, offset,
632 requested_len, xfered_len);
634 gdb_assert (requested_len > 0);
635 gdb_assert (xfered_len != nullptr);
637 if (object != TARGET_OBJECT_MEMORY)
638 return TARGET_XFER_E_IO;
640 amd_dbgapi_process_id_t process_id
641 = get_amd_dbgapi_process_id (current_inferior ());
642 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid);
644 size_t len = requested_len;
645 amd_dbgapi_status_t status;
647 if (readbuf != nullptr)
648 status = amd_dbgapi_read_memory (process_id, wave_id, 0,
649 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL,
650 offset, &len, readbuf);
651 else
652 status = amd_dbgapi_write_memory (process_id, wave_id, 0,
653 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL,
654 offset, &len, writebuf);
656 if (status != AMD_DBGAPI_STATUS_SUCCESS)
657 return TARGET_XFER_E_IO;
659 *xfered_len = len;
660 return TARGET_XFER_OK;
663 bool
664 amd_dbgapi_target::stopped_by_watchpoint ()
666 if (!ptid_is_gpu (inferior_ptid))
667 return beneath ()->stopped_by_watchpoint ();
669 return false;
672 void
673 amd_dbgapi_target::resume (ptid_t scope_ptid, int step, enum gdb_signal signo)
675 amd_dbgapi_debug_printf ("scope_ptid = %s", scope_ptid.to_string ().c_str ());
677 /* The amd_dbgapi_exceptions_t matching SIGNO will only be used if the
678 thread which is the target of the signal SIGNO is a GPU thread. If so,
679 make sure that there is a corresponding amd_dbgapi_exceptions_t for SIGNO
680 before we try to resume any thread. */
681 amd_dbgapi_exceptions_t exception = AMD_DBGAPI_EXCEPTION_NONE;
682 if (ptid_is_gpu (inferior_ptid))
684 switch (signo)
686 case GDB_SIGNAL_BUS:
687 exception = AMD_DBGAPI_EXCEPTION_WAVE_ADDRESS_ERROR;
688 break;
689 case GDB_SIGNAL_SEGV:
690 exception = AMD_DBGAPI_EXCEPTION_WAVE_MEMORY_VIOLATION;
691 break;
692 case GDB_SIGNAL_ILL:
693 exception = AMD_DBGAPI_EXCEPTION_WAVE_ILLEGAL_INSTRUCTION;
694 break;
695 case GDB_SIGNAL_FPE:
696 exception = AMD_DBGAPI_EXCEPTION_WAVE_MATH_ERROR;
697 break;
698 case GDB_SIGNAL_ABRT:
699 exception = AMD_DBGAPI_EXCEPTION_WAVE_ABORT;
700 break;
701 case GDB_SIGNAL_TRAP:
702 exception = AMD_DBGAPI_EXCEPTION_WAVE_TRAP;
703 break;
704 case GDB_SIGNAL_0:
705 exception = AMD_DBGAPI_EXCEPTION_NONE;
706 break;
707 default:
708 error (_("Resuming with signal %s is not supported by this agent."),
709 gdb_signal_to_name (signo));
713 if (!ptid_is_gpu (inferior_ptid) || scope_ptid != inferior_ptid)
715 beneath ()->resume (scope_ptid, step, signo);
717 /* If the request is for a single thread, we are done. */
718 if (scope_ptid == inferior_ptid)
719 return;
722 process_stratum_target *proc_target = current_inferior ()->process_target ();
724 /* Disable forward progress requirement. */
725 require_forward_progress (scope_ptid, proc_target, false);
727 for (thread_info *thread : all_non_exited_threads (proc_target, scope_ptid))
729 if (!ptid_is_gpu (thread->ptid))
730 continue;
732 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid);
733 amd_dbgapi_status_t status;
735 wave_info &wi = get_thread_wave_info (thread);
736 amd_dbgapi_resume_mode_t &resume_mode = wi.last_resume_mode;
737 amd_dbgapi_exceptions_t wave_exception;
738 if (thread->ptid == inferior_ptid)
740 resume_mode = (step
741 ? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
742 : AMD_DBGAPI_RESUME_MODE_NORMAL);
743 wave_exception = exception;
745 else
747 resume_mode = AMD_DBGAPI_RESUME_MODE_NORMAL;
748 wave_exception = AMD_DBGAPI_EXCEPTION_NONE;
751 status = amd_dbgapi_wave_resume (wave_id, resume_mode, wave_exception);
752 if (status != AMD_DBGAPI_STATUS_SUCCESS
753 /* Ignore the error that wave is no longer valid as that could
754 indicate that the process has exited. GDB treats resuming a
755 thread that no longer exists as being successful. */
756 && status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
757 error (_("wave_resume for wave_%ld failed (%s)"), wave_id.handle,
758 get_status_string (status));
760 wi.stopping = false;
764 void
765 amd_dbgapi_target::commit_resumed ()
767 amd_dbgapi_debug_printf ("called");
769 beneath ()->commit_resumed ();
771 process_stratum_target *proc_target = current_inferior ()->process_target ();
772 require_forward_progress (minus_one_ptid, proc_target, true);
775 /* Return a string version of RESUME_MODE, for debug log purposes. */
777 static const char *
778 resume_mode_to_string (amd_dbgapi_resume_mode_t resume_mode)
780 switch (resume_mode)
782 case AMD_DBGAPI_RESUME_MODE_NORMAL:
783 return "normal";
784 case AMD_DBGAPI_RESUME_MODE_SINGLE_STEP:
785 return "step";
787 gdb_assert_not_reached ("invalid amd_dbgapi_resume_mode_t");
790 void
791 amd_dbgapi_target::stop (ptid_t ptid)
793 amd_dbgapi_debug_printf ("ptid = %s", ptid.to_string ().c_str ());
795 bool many_threads = ptid == minus_one_ptid || ptid.is_pid ();
797 if (!ptid_is_gpu (ptid) || many_threads)
799 beneath ()->stop (ptid);
801 /* The request is for a single thread, we are done. */
802 if (!many_threads)
803 return;
806 auto stop_one_thread = [this] (thread_info *thread)
808 gdb_assert (thread != nullptr);
810 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid);
811 amd_dbgapi_wave_state_t state;
812 amd_dbgapi_status_t status
813 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STATE,
814 sizeof (state), &state);
815 if (status == AMD_DBGAPI_STATUS_SUCCESS)
817 /* If the wave is already known to be stopped then do nothing. */
818 if (state == AMD_DBGAPI_WAVE_STATE_STOP)
819 return;
821 status = amd_dbgapi_wave_stop (wave_id);
822 if (status == AMD_DBGAPI_STATUS_SUCCESS)
824 wave_info &wi = get_thread_wave_info (thread);
825 wi.stopping = true;
826 return;
829 if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
830 error (_("wave_stop for wave_%ld failed (%s)"), wave_id.handle,
831 get_status_string (status));
833 else if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
834 error (_("wave_get_info for wave_%ld failed (%s)"), wave_id.handle,
835 get_status_string (status));
837 /* The status is AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID. The wave
838 could have terminated since the last time the wave list was
839 refreshed. */
841 wave_info &wi = get_thread_wave_info (thread);
842 wi.stopping = true;
844 amd_dbgapi_debug_printf ("got AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID "
845 "for wave_%ld, last_resume_mode=%s, "
846 "report_thread_events=%d",
847 wave_id.handle,
848 resume_mode_to_string (wi.last_resume_mode),
849 m_report_thread_events);
851 /* If the wave was stepping when it terminated, then it is
852 guaranteed that we will see a WAVE_COMMAND_TERMINATED event
853 for it. Don't report a thread exit event or delete the
854 thread yet, until we see such event. */
855 if (wi.last_resume_mode == AMD_DBGAPI_RESUME_MODE_SINGLE_STEP)
856 return;
858 if (m_report_thread_events)
860 get_amd_dbgapi_inferior_info (thread->inf)->wave_events.emplace_back
861 (thread->ptid, target_waitstatus ().set_thread_exited (0));
863 if (target_is_async_p ())
864 async_event_handler_mark ();
867 delete_thread_silent (thread);
870 process_stratum_target *proc_target = current_inferior ()->process_target ();
872 /* Disable forward progress requirement. */
873 require_forward_progress (ptid, proc_target, false);
875 if (!many_threads)
877 /* No need to iterate all non-exited threads if the request is to stop a
878 specific thread. */
879 stop_one_thread (proc_target->find_thread (ptid));
880 return;
883 for (auto *inf : all_inferiors (proc_target))
884 /* Use the threads_safe iterator since stop_one_thread may delete the
885 thread if it has exited. */
886 for (auto *thread : inf->threads_safe ())
887 if (thread->state != THREAD_EXITED && thread->ptid.matches (ptid)
888 && ptid_is_gpu (thread->ptid))
889 stop_one_thread (thread);
892 /* Callback for our async event handler. */
894 static void
895 handle_target_event (gdb_client_data client_data)
897 inferior_event_handler (INF_REG_EVENT);
900 struct scoped_amd_dbgapi_event_processed
902 scoped_amd_dbgapi_event_processed (amd_dbgapi_event_id_t event_id)
903 : m_event_id (event_id)
905 gdb_assert (event_id != AMD_DBGAPI_EVENT_NONE);
908 ~scoped_amd_dbgapi_event_processed ()
910 amd_dbgapi_status_t status = amd_dbgapi_event_processed (m_event_id);
911 if (status != AMD_DBGAPI_STATUS_SUCCESS)
912 warning (_("Failed to acknowledge amd-dbgapi event %" PRIu64),
913 m_event_id.handle);
916 DISABLE_COPY_AND_ASSIGN (scoped_amd_dbgapi_event_processed);
918 private:
919 amd_dbgapi_event_id_t m_event_id;
922 /* Called when a dbgapi notifier fd is readable. CLIENT_DATA is the
923 amd_dbgapi_inferior_info object corresponding to the notifier. */
925 static void
926 dbgapi_notifier_handler (int err, gdb_client_data client_data)
928 amd_dbgapi_inferior_info *info = (amd_dbgapi_inferior_info *) client_data;
929 int ret;
931 /* Drain the notifier pipe. */
934 char buf;
935 ret = read (info->notifier, &buf, 1);
937 while (ret >= 0 || (ret == -1 && errno == EINTR));
939 if (info->inf->target_is_pushed (&the_amd_dbgapi_target))
941 /* The amd-dbgapi target is pushed: signal our async handler, the event
942 will be consumed through our wait method. */
944 async_event_handler_mark ();
946 else
948 /* The amd-dbgapi target is not pushed: if there's an event, the only
949 expected one is one of the RUNTIME kind. If the event tells us the
950 inferior as activated the ROCm runtime, push the amd-dbgapi
951 target. */
953 amd_dbgapi_event_id_t event_id;
954 amd_dbgapi_event_kind_t event_kind;
955 amd_dbgapi_status_t status
956 = amd_dbgapi_process_next_pending_event (info->process_id, &event_id,
957 &event_kind);
958 if (status != AMD_DBGAPI_STATUS_SUCCESS)
959 error (_("next_pending_event failed (%s)"), get_status_string (status));
961 if (event_id == AMD_DBGAPI_EVENT_NONE)
962 return;
964 gdb_assert (event_kind == AMD_DBGAPI_EVENT_KIND_RUNTIME);
966 scoped_amd_dbgapi_event_processed mark_event_processed (event_id);
968 amd_dbgapi_runtime_state_t runtime_state;
969 status = amd_dbgapi_event_get_info (event_id,
970 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
971 sizeof (runtime_state),
972 &runtime_state);
973 if (status != AMD_DBGAPI_STATUS_SUCCESS)
974 error (_("event_get_info for event_%ld failed (%s)"),
975 event_id.handle, get_status_string (status));
977 switch (runtime_state)
979 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS:
980 gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
981 info->runtime_state = runtime_state;
982 amd_dbgapi_debug_printf ("pushing amd-dbgapi target");
983 info->inf->push_target (&the_amd_dbgapi_target);
985 /* The underlying target will already be async if we are running, but not if
986 we are attaching. */
987 if (info->inf->process_target ()->is_async_p ())
989 scoped_restore_current_thread restore_thread;
990 switch_to_inferior_no_thread (info->inf);
992 /* Make sure our async event handler is created. */
993 target_async (true);
995 break;
997 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED:
998 gdb_assert (info->runtime_state
999 == AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION);
1000 info->runtime_state = runtime_state;
1001 break;
1003 case AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION:
1004 gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
1005 info->runtime_state = runtime_state;
1006 warning (_("amd-dbgapi: unable to enable GPU debugging "
1007 "due to a restriction error"));
1008 break;
1013 void
1014 amd_dbgapi_target::async (bool enable)
1016 beneath ()->async (enable);
1018 if (enable)
1020 if (amd_dbgapi_async_event_handler != nullptr)
1022 /* Already enabled. */
1023 return;
1026 /* The library gives us one notifier file descriptor per inferior (even
1027 the ones that have not yet loaded their runtime). Register them
1028 all with the event loop. */
1029 process_stratum_target *proc_target
1030 = current_inferior ()->process_target ();
1032 for (inferior *inf : all_non_exited_inferiors (proc_target))
1034 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1036 if (info->notifier != -1)
1037 add_file_handler (info->notifier, dbgapi_notifier_handler, info,
1038 string_printf ("amd-dbgapi notifier for pid %d",
1039 inf->pid));
1042 amd_dbgapi_async_event_handler
1043 = create_async_event_handler (handle_target_event, nullptr,
1044 "amd-dbgapi");
1046 /* There may be pending events to handle. Tell the event loop to poll
1047 them. */
1048 async_event_handler_mark ();
1050 else
1052 if (amd_dbgapi_async_event_handler == nullptr)
1053 return;
1055 for (inferior *inf : all_inferiors ())
1057 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1059 if (info->notifier != -1)
1060 delete_file_handler (info->notifier);
1063 delete_async_event_handler (&amd_dbgapi_async_event_handler);
1067 /* Make a ptid for a GPU wave. See comment on ptid_is_gpu for more details. */
1069 static ptid_t
1070 make_gpu_ptid (ptid_t::pid_type pid, amd_dbgapi_wave_id_t wave_id)
1072 return ptid_t (pid, 1, wave_id.handle);
1075 /* When a thread is deleted, remove its wave_info from the inferior's
1076 wave_info map. */
1078 static void
1079 amd_dbgapi_thread_deleted (thread_info *tp)
1081 if (tp->inf->target_at (arch_stratum) == &the_amd_dbgapi_target
1082 && ptid_is_gpu (tp->ptid))
1084 amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (tp->inf);
1085 auto wave_id = get_amd_dbgapi_wave_id (tp->ptid);
1086 auto it = info->wave_info_map.find (wave_id.handle);
1087 gdb_assert (it != info->wave_info_map.end ());
1088 info->wave_info_map.erase (it);
1092 /* Register WAVE_PTID as a new thread in INF's thread list, and record
1093 its wave_info in the inferior's wave_info map. */
1095 static thread_info *
1096 add_gpu_thread (inferior *inf, ptid_t wave_ptid)
1098 process_stratum_target *proc_target = inf->process_target ();
1099 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1101 auto wave_id = get_amd_dbgapi_wave_id (wave_ptid);
1103 if (!info->wave_info_map.try_emplace (wave_id.handle,
1104 wave_info (wave_id)).second)
1105 internal_error ("wave ID %ld already in map", wave_id.handle);
1107 /* Create new GPU threads silently to avoid spamming the terminal
1108 with thousands of "[New Thread ...]" messages. */
1109 thread_info *thread = add_thread_silent (proc_target, wave_ptid);
1110 set_running (proc_target, wave_ptid, true);
1111 set_executing (proc_target, wave_ptid, true);
1112 return thread;
1115 /* Process an event that was just pulled out of the amd-dbgapi library. */
1117 static void
1118 process_one_event (amd_dbgapi_event_id_t event_id,
1119 amd_dbgapi_event_kind_t event_kind)
1121 /* Automatically mark this event processed when going out of scope. */
1122 scoped_amd_dbgapi_event_processed mark_event_processed (event_id);
1124 amd_dbgapi_process_id_t process_id;
1125 amd_dbgapi_status_t status
1126 = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_PROCESS,
1127 sizeof (process_id), &process_id);
1128 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1129 error (_("event_get_info for event_%ld failed (%s)"), event_id.handle,
1130 get_status_string (status));
1132 amd_dbgapi_os_process_id_t pid;
1133 status = amd_dbgapi_process_get_info (process_id,
1134 AMD_DBGAPI_PROCESS_INFO_OS_ID,
1135 sizeof (pid), &pid);
1136 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1137 error (_("process_get_info for process_%ld failed (%s)"),
1138 process_id.handle, get_status_string (status));
1140 auto *proc_target = current_inferior ()->process_target ();
1141 inferior *inf = find_inferior_pid (proc_target, pid);
1142 gdb_assert (inf != nullptr);
1143 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1145 switch (event_kind)
1147 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED:
1148 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
1150 amd_dbgapi_wave_id_t wave_id;
1151 status
1152 = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_WAVE,
1153 sizeof (wave_id), &wave_id);
1154 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1155 error (_("event_get_info for event_%ld failed (%s)"),
1156 event_id.handle, get_status_string (status));
1158 ptid_t event_ptid = make_gpu_ptid (pid, wave_id);
1159 target_waitstatus ws;
1161 amd_dbgapi_wave_stop_reasons_t stop_reason;
1162 status = amd_dbgapi_wave_get_info (wave_id,
1163 AMD_DBGAPI_WAVE_INFO_STOP_REASON,
1164 sizeof (stop_reason), &stop_reason);
1165 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
1166 && event_kind == AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED)
1167 ws.set_thread_exited (0);
1168 else if (status == AMD_DBGAPI_STATUS_SUCCESS)
1170 if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_ADDRESS_ERROR)
1171 ws.set_stopped (GDB_SIGNAL_BUS);
1172 else if (stop_reason
1173 & AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION)
1174 ws.set_stopped (GDB_SIGNAL_SEGV);
1175 else if (stop_reason
1176 & AMD_DBGAPI_WAVE_STOP_REASON_ILLEGAL_INSTRUCTION)
1177 ws.set_stopped (GDB_SIGNAL_ILL);
1178 else if (stop_reason
1179 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
1180 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
1181 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
1182 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
1183 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
1184 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
1185 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0))
1186 ws.set_stopped (GDB_SIGNAL_FPE);
1187 else if (stop_reason
1188 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
1189 | AMD_DBGAPI_WAVE_STOP_REASON_WATCHPOINT
1190 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
1191 | AMD_DBGAPI_WAVE_STOP_REASON_DEBUG_TRAP
1192 | AMD_DBGAPI_WAVE_STOP_REASON_TRAP))
1193 ws.set_stopped (GDB_SIGNAL_TRAP);
1194 else if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_ASSERT_TRAP)
1195 ws.set_stopped (GDB_SIGNAL_ABRT);
1196 else
1197 ws.set_stopped (GDB_SIGNAL_0);
1199 thread_info *thread = proc_target->find_thread (event_ptid);
1200 if (thread == nullptr)
1201 thread = add_gpu_thread (inf, event_ptid);
1203 /* If the wave is stopped because of a software breakpoint, the
1204 program counter needs to be adjusted so that it points to the
1205 breakpoint instruction. */
1206 if ((stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT) != 0)
1208 regcache *regcache = get_thread_regcache (thread);
1209 gdbarch *gdbarch = regcache->arch ();
1211 CORE_ADDR pc = regcache_read_pc (regcache);
1212 CORE_ADDR adjusted_pc
1213 = pc - gdbarch_decr_pc_after_break (gdbarch);
1215 if (adjusted_pc != pc)
1216 regcache_write_pc (regcache, adjusted_pc);
1219 else
1220 error (_("wave_get_info for wave_%ld failed (%s)"),
1221 wave_id.handle, get_status_string (status));
1223 info->wave_events.emplace_back (event_ptid, ws);
1224 break;
1227 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED:
1228 /* We get here when the following sequence of events happens:
1230 - the inferior hits the amd-dbgapi "r_brk" internal breakpoint
1231 - amd_dbgapi_target_breakpoint::check_status calls
1232 amd_dbgapi_report_breakpoint_hit, which queues an event of this
1233 kind in dbgapi
1234 - amd_dbgapi_target_breakpoint::check_status calls
1235 process_event_queue, which pulls the event out of dbgapi, and
1236 gets us here
1238 When amd_dbgapi_target_breakpoint::check_status is called, the current
1239 inferior is the inferior that hit the breakpoint, which should still be
1240 the case now. */
1241 gdb_assert (inf == current_inferior ());
1242 handle_solib_event ();
1243 break;
1245 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME:
1246 /* Breakpoint resume events should be handled by the breakpoint
1247 action, and this code should not reach this. */
1248 gdb_assert_not_reached ("unhandled event kind");
1249 break;
1251 case AMD_DBGAPI_EVENT_KIND_RUNTIME:
1253 amd_dbgapi_runtime_state_t runtime_state;
1255 status = amd_dbgapi_event_get_info (event_id,
1256 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
1257 sizeof (runtime_state),
1258 &runtime_state);
1259 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1260 error (_("event_get_info for event_%ld failed (%s)"),
1261 event_id.handle, get_status_string (status));
1263 gdb_assert (runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
1264 gdb_assert
1265 (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
1267 info->runtime_state = runtime_state;
1269 gdb_assert (inf->target_is_pushed (&the_amd_dbgapi_target));
1270 inf->unpush_target (&the_amd_dbgapi_target);
1272 break;
1274 default:
1275 error (_("event kind (%d) not supported"), event_kind);
1279 /* Return a textual version of KIND. */
1281 static const char *
1282 event_kind_str (amd_dbgapi_event_kind_t kind)
1284 switch (kind)
1286 case AMD_DBGAPI_EVENT_KIND_NONE:
1287 return "NONE";
1289 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
1290 return "WAVE_STOP";
1292 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED:
1293 return "WAVE_COMMAND_TERMINATED";
1295 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED:
1296 return "CODE_OBJECT_LIST_UPDATED";
1298 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME:
1299 return "BREAKPOINT_RESUME";
1301 case AMD_DBGAPI_EVENT_KIND_RUNTIME:
1302 return "RUNTIME";
1304 case AMD_DBGAPI_EVENT_KIND_QUEUE_ERROR:
1305 return "QUEUE_ERROR";
1308 gdb_assert_not_reached ("unhandled amd_dbgapi_event_kind_t value");
1311 /* Drain the dbgapi event queue of a given process_id, or of all processes if
1312 process_id is AMD_DBGAPI_PROCESS_NONE. Stop processing the events if an
1313 event of a given kind is requested and `process_id` is not
1314 AMD_DBGAPI_PROCESS_NONE. Wave stop events that are not returned are queued
1315 into their inferior's amd_dbgapi_inferior_info pending wave events. */
1317 static amd_dbgapi_event_id_t
1318 process_event_queue (amd_dbgapi_process_id_t process_id,
1319 amd_dbgapi_event_kind_t until_event_kind)
1321 /* An event of a given type can only be requested from a single
1322 process_id. */
1323 gdb_assert (until_event_kind == AMD_DBGAPI_EVENT_KIND_NONE
1324 || process_id != AMD_DBGAPI_PROCESS_NONE);
1326 while (true)
1328 amd_dbgapi_event_id_t event_id;
1329 amd_dbgapi_event_kind_t event_kind;
1331 amd_dbgapi_status_t status
1332 = amd_dbgapi_process_next_pending_event (process_id, &event_id,
1333 &event_kind);
1335 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1336 error (_("next_pending_event failed (%s)"), get_status_string (status));
1338 if (event_kind != AMD_DBGAPI_EVENT_KIND_NONE)
1339 amd_dbgapi_debug_printf ("Pulled event from dbgapi: "
1340 "event_id.handle = %" PRIu64 ", "
1341 "event_kind = %s",
1342 event_id.handle,
1343 event_kind_str (event_kind));
1345 if (event_id == AMD_DBGAPI_EVENT_NONE || event_kind == until_event_kind)
1346 return event_id;
1348 process_one_event (event_id, event_kind);
1352 bool
1353 amd_dbgapi_target::has_pending_events ()
1355 if (amd_dbgapi_async_event_handler != nullptr
1356 && async_event_handler_marked (amd_dbgapi_async_event_handler))
1357 return true;
1359 return beneath ()->has_pending_events ();
1362 /* Pop one pending event from the per-inferior structures.
1364 If PID is not -1, restrict the search to the inferior with that pid. */
1366 static std::pair<ptid_t, target_waitstatus>
1367 consume_one_event (int pid)
1369 auto *target = current_inferior ()->process_target ();
1370 struct amd_dbgapi_inferior_info *info = nullptr;
1372 if (pid == -1)
1374 for (inferior *inf : all_inferiors (target))
1376 info = get_amd_dbgapi_inferior_info (inf);
1377 if (!info->wave_events.empty ())
1378 break;
1381 gdb_assert (info != nullptr);
1383 else
1385 inferior *inf = find_inferior_pid (target, pid);
1387 gdb_assert (inf != nullptr);
1388 info = get_amd_dbgapi_inferior_info (inf);
1391 if (info->wave_events.empty ())
1392 return { minus_one_ptid, {} };
1394 auto event = info->wave_events.front ();
1395 info->wave_events.pop_front ();
1397 return event;
1400 ptid_t
1401 amd_dbgapi_target::wait (ptid_t ptid, struct target_waitstatus *ws,
1402 target_wait_flags target_options)
1404 gdb_assert (!current_inferior ()->process_target ()->commit_resumed_state);
1405 gdb_assert (ptid == minus_one_ptid || ptid.is_pid ());
1407 amd_dbgapi_debug_printf ("ptid = %s", ptid.to_string ().c_str ());
1409 ptid_t event_ptid = beneath ()->wait (ptid, ws, target_options);
1410 if (event_ptid != minus_one_ptid)
1412 if (ws->kind () == TARGET_WAITKIND_EXITED
1413 || ws->kind () == TARGET_WAITKIND_SIGNALLED)
1415 /* This inferior has exited so drain its dbgapi event queue. */
1416 while (consume_one_event (event_ptid.pid ()).first
1417 != minus_one_ptid)
1420 return event_ptid;
1423 gdb_assert (ws->kind () == TARGET_WAITKIND_NO_RESUMED
1424 || ws->kind () == TARGET_WAITKIND_IGNORE);
1426 /* Flush the async handler first. */
1427 if (target_is_async_p ())
1428 async_event_handler_clear ();
1430 /* There may be more events to process (either already in `wave_events` or
1431 that we need to fetch from dbgapi. Mark the async event handler so that
1432 amd_dbgapi_target::wait gets called again and again, until it eventually
1433 returns minus_one_ptid. */
1434 auto more_events = make_scope_exit ([] ()
1436 if (target_is_async_p ())
1437 async_event_handler_mark ();
1440 auto *proc_target = current_inferior ()->process_target ();
1442 /* Disable forward progress for the specified pid in ptid if it isn't
1443 minus_on_ptid, or all attached processes if ptid is minus_one_ptid. */
1444 require_forward_progress (ptid, proc_target, false);
1446 target_waitstatus gpu_waitstatus;
1447 std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
1448 if (event_ptid == minus_one_ptid)
1450 /* Drain the events for the current inferior from the amd_dbgapi and
1451 preserve the ordering. */
1452 auto info = get_amd_dbgapi_inferior_info (current_inferior ());
1453 process_event_queue (info->process_id, AMD_DBGAPI_EVENT_KIND_NONE);
1455 std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
1456 if (event_ptid == minus_one_ptid)
1458 /* If we requested a specific ptid, and nothing came out, assume
1459 another ptid may have more events, otherwise, keep the
1460 async_event_handler flushed. */
1461 if (ptid == minus_one_ptid)
1462 more_events.release ();
1464 if (ws->kind () == TARGET_WAITKIND_NO_RESUMED)
1466 /* We can't easily check that all GPU waves are stopped, and no
1467 new waves can be created (the GPU has fixed function hardware
1468 to create new threads), so even if the target beneath returns
1469 waitkind_no_resumed, we have to report waitkind_ignore if GPU
1470 debugging is enabled for at least one resumed inferior handled
1471 by the amd-dbgapi target. */
1473 for (inferior *inf : all_inferiors ())
1474 if (inf->target_at (arch_stratum) == &the_amd_dbgapi_target
1475 && get_amd_dbgapi_inferior_info (inf)->runtime_state
1476 == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS)
1478 ws->set_ignore ();
1479 break;
1483 /* There are no events to report, return the target beneath's
1484 waitstatus (either IGNORE or NO_RESUMED). */
1485 return minus_one_ptid;
1489 *ws = gpu_waitstatus;
1490 return event_ptid;
1493 bool
1494 amd_dbgapi_target::stopped_by_sw_breakpoint ()
1496 if (!ptid_is_gpu (inferior_ptid))
1497 return beneath ()->stopped_by_sw_breakpoint ();
1499 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid);
1501 amd_dbgapi_wave_stop_reasons_t stop_reason;
1502 amd_dbgapi_status_t status
1503 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STOP_REASON,
1504 sizeof (stop_reason), &stop_reason);
1506 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1507 return false;
1509 return (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT) != 0;
1512 bool
1513 amd_dbgapi_target::stopped_by_hw_breakpoint ()
1515 if (!ptid_is_gpu (inferior_ptid))
1516 return beneath ()->stopped_by_hw_breakpoint ();
1518 return false;
1521 /* Set the process' memory access reporting precision mode.
1523 Warn if the requested mode is not supported on at least one agent in the
1524 process.
1526 Error out if setting the requested mode failed for some other reason. */
1528 static void
1529 set_process_memory_precision (amd_dbgapi_inferior_info &info)
1531 auto mode = (info.precise_memory.requested
1532 ? AMD_DBGAPI_MEMORY_PRECISION_PRECISE
1533 : AMD_DBGAPI_MEMORY_PRECISION_NONE);
1534 amd_dbgapi_status_t status
1535 = amd_dbgapi_set_memory_precision (info.process_id, mode);
1537 if (status == AMD_DBGAPI_STATUS_SUCCESS)
1538 info.precise_memory.enabled = info.precise_memory.requested;
1539 else if (status == AMD_DBGAPI_STATUS_ERROR_NOT_SUPPORTED)
1540 warning (_("AMDGPU precise memory access reporting could not be enabled."));
1541 else if (status != AMD_DBGAPI_STATUS_SUCCESS)
1542 error (_("amd_dbgapi_set_memory_precision failed (%s)"),
1543 get_status_string (status));
1546 /* Make the amd-dbgapi library attach to the process behind INF.
1548 Note that this is unrelated to the "attach" GDB concept / command.
1550 By attaching to the process, we get a notifier fd that tells us when it
1551 activates the ROCm runtime and when there are subsequent debug events. */
1553 static void
1554 attach_amd_dbgapi (inferior *inf)
1556 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num);
1558 if (!target_can_async_p ())
1560 warning (_("The amd-dbgapi target requires the target beneath to be "
1561 "asynchronous, GPU debugging is disabled"));
1562 return;
1565 /* dbgapi can't attach to a vfork child (a process born from a vfork that
1566 hasn't exec'ed yet) while we are still attached to the parent. It would
1567 not be useful for us to attach to vfork children anyway, because vfork
1568 children are very restricted in what they can do (see vfork(2)) and aren't
1569 going to launch some GPU programs that we need to debug. To avoid this
1570 problem, we don't push the amd-dbgapi target / attach dbgapi in vfork
1571 children. If a vfork child execs, we'll try enabling the amd-dbgapi target
1572 through the inferior_execd observer. */
1573 if (inf->vfork_parent != nullptr)
1574 return;
1576 auto *info = get_amd_dbgapi_inferior_info (inf);
1578 /* Are we already attached? */
1579 if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
1581 amd_dbgapi_debug_printf
1582 ("already attached: process_id = %" PRIu64, info->process_id.handle);
1583 return;
1586 amd_dbgapi_status_t status
1587 = amd_dbgapi_process_attach
1588 (reinterpret_cast<amd_dbgapi_client_process_id_t> (inf),
1589 &info->process_id);
1590 if (status == AMD_DBGAPI_STATUS_ERROR_RESTRICTION)
1592 warning (_("amd-dbgapi: unable to enable GPU debugging due to a "
1593 "restriction error"));
1594 return;
1596 else if (status != AMD_DBGAPI_STATUS_SUCCESS)
1598 warning (_("amd-dbgapi: could not attach to process %d (%s), GPU "
1599 "debugging will not be available."), inf->pid,
1600 get_status_string (status));
1601 return;
1604 if (amd_dbgapi_process_get_info (info->process_id,
1605 AMD_DBGAPI_PROCESS_INFO_NOTIFIER,
1606 sizeof (info->notifier), &info->notifier)
1607 != AMD_DBGAPI_STATUS_SUCCESS)
1609 amd_dbgapi_process_detach (info->process_id);
1610 info->process_id = AMD_DBGAPI_PROCESS_NONE;
1611 warning (_("amd-dbgapi: could not retrieve process %d's notifier, GPU "
1612 "debugging will not be available."), inf->pid);
1613 return;
1616 amd_dbgapi_debug_printf ("process_id = %" PRIu64 ", notifier fd = %d",
1617 info->process_id.handle, info->notifier);
1619 set_process_memory_precision (*info);
1621 /* If GDB is attaching to a process that has the runtime loaded, there will
1622 already be a "runtime loaded" event available. Consume it and push the
1623 target. */
1624 dbgapi_notifier_handler (0, info);
1626 add_file_handler (info->notifier, dbgapi_notifier_handler, info,
1627 "amd-dbgapi notifier");
1630 static void maybe_reset_amd_dbgapi ();
1632 /* Make the amd-dbgapi library detach from INF.
1634 Note that this us unrelated to the "detach" GDB concept / command.
1636 This undoes what attach_amd_dbgapi does. */
1638 static void
1639 detach_amd_dbgapi (inferior *inf)
1641 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num);
1643 auto *info = get_amd_dbgapi_inferior_info (inf);
1645 if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
1646 return;
1648 info->runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED;
1650 amd_dbgapi_status_t status = amd_dbgapi_process_detach (info->process_id);
1651 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1652 warning (_("amd-dbgapi: could not detach from process %d (%s)"),
1653 inf->pid, get_status_string (status));
1655 gdb_assert (info->notifier != -1);
1656 delete_file_handler (info->notifier);
1658 /* This is a noop if the target is not pushed. */
1659 inf->unpush_target (&the_amd_dbgapi_target);
1661 /* Delete the breakpoints that are still active. */
1662 for (auto &&value : info->breakpoint_map)
1663 delete_breakpoint (value.second);
1665 /* Reset the amd_dbgapi_inferior_info, except for precise_memory_mode. */
1666 *info = amd_dbgapi_inferior_info (inf, info->precise_memory.requested);
1668 maybe_reset_amd_dbgapi ();
1671 void
1672 amd_dbgapi_target::mourn_inferior ()
1674 detach_amd_dbgapi (current_inferior ());
1675 beneath ()->mourn_inferior ();
1678 void
1679 amd_dbgapi_target::detach (inferior *inf, int from_tty)
1681 /* We're about to resume the waves by detaching the dbgapi library from the
1682 inferior, so we need to remove all breakpoints that are still inserted.
1684 Breakpoints may still be inserted because the inferior may be running in
1685 non-stop mode, or because GDB changed the default setting to leave all
1686 breakpoints inserted in all-stop mode when all threads are stopped. */
1687 remove_breakpoints_inf (inf);
1689 detach_amd_dbgapi (inf);
1690 beneath ()->detach (inf, from_tty);
1693 void
1694 amd_dbgapi_target::fetch_registers (struct regcache *regcache, int regno)
1696 if (!ptid_is_gpu (regcache->ptid ()))
1698 beneath ()->fetch_registers (regcache, regno);
1699 return;
1702 struct gdbarch *gdbarch = regcache->arch ();
1703 gdb_assert (is_amdgpu_arch (gdbarch));
1705 amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch);
1706 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
1707 gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
1708 amd_dbgapi_status_t status
1709 = amd_dbgapi_read_register (wave_id, tdep->register_ids[regno], 0,
1710 register_type (gdbarch, regno)->length (),
1711 raw);
1713 if (status == AMD_DBGAPI_STATUS_SUCCESS)
1714 regcache->raw_supply (regno, raw);
1715 else if (status != AMD_DBGAPI_STATUS_ERROR_REGISTER_NOT_AVAILABLE)
1716 warning (_("Couldn't read register %s (#%d) (%s)."),
1717 gdbarch_register_name (gdbarch, regno), regno,
1718 get_status_string (status));
1721 void
1722 amd_dbgapi_target::store_registers (struct regcache *regcache, int regno)
1724 if (!ptid_is_gpu (regcache->ptid ()))
1726 beneath ()->store_registers (regcache, regno);
1727 return;
1730 struct gdbarch *gdbarch = regcache->arch ();
1731 gdb_assert (is_amdgpu_arch (gdbarch));
1733 gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
1734 regcache->raw_collect (regno, &raw);
1736 amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch);
1738 /* If the register has read-only bits, invalidate the value in the regcache
1739 as the value actually written may differ. */
1740 if (tdep->register_properties[regno]
1741 & AMD_DBGAPI_REGISTER_PROPERTY_READONLY_BITS)
1742 regcache->invalidate (regno);
1744 /* Invalidate all volatile registers if this register has the invalidate
1745 volatile property. For example, writing to VCC may change the content
1746 of STATUS.VCCZ. */
1747 if (tdep->register_properties[regno]
1748 & AMD_DBGAPI_REGISTER_PROPERTY_INVALIDATE_VOLATILE)
1750 for (size_t r = 0; r < tdep->register_properties.size (); ++r)
1751 if (tdep->register_properties[r] & AMD_DBGAPI_REGISTER_PROPERTY_VOLATILE)
1752 regcache->invalidate (r);
1755 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
1756 amd_dbgapi_status_t status
1757 = amd_dbgapi_write_register (wave_id, tdep->register_ids[regno], 0,
1758 register_type (gdbarch, regno)->length (),
1759 raw);
1761 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1762 warning (_("Couldn't write register %s (#%d)."),
1763 gdbarch_register_name (gdbarch, regno), regno);
1766 struct gdbarch *
1767 amd_dbgapi_target::thread_architecture (ptid_t ptid)
1769 if (!ptid_is_gpu (ptid))
1770 return beneath ()->thread_architecture (ptid);
1772 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
1773 wave IDs are unique, and aren't reused. */
1774 if (ptid.tid () == m_cached_arch_tid)
1775 return m_cached_arch;
1777 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (ptid);
1778 amd_dbgapi_architecture_id_t architecture_id;
1779 amd_dbgapi_status_t status;
1781 status = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_ARCHITECTURE,
1782 sizeof (architecture_id),
1783 &architecture_id);
1784 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1785 error (_("Couldn't get architecture for wave_%ld"), ptid.tid ());
1787 uint32_t elf_amdgpu_machine;
1788 status = amd_dbgapi_architecture_get_info
1789 (architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE,
1790 sizeof (elf_amdgpu_machine), &elf_amdgpu_machine);
1791 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1792 error (_("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1793 architecture_id.handle);
1795 struct gdbarch_info info;
1796 info.bfd_arch_info = bfd_lookup_arch (bfd_arch_amdgcn, elf_amdgpu_machine);
1797 info.byte_order = BFD_ENDIAN_LITTLE;
1799 m_cached_arch_tid = ptid.tid ();
1800 m_cached_arch = gdbarch_find_by_info (info);
1801 if (m_cached_arch == nullptr)
1802 error (_("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine);
1804 return m_cached_arch;
1807 void
1808 amd_dbgapi_target::thread_events (bool enable)
1810 m_report_thread_events = enable;
1811 beneath ()->thread_events (enable);
1814 void
1815 amd_dbgapi_target::update_thread_list ()
1817 for (inferior *inf : all_inferiors ())
1819 amd_dbgapi_process_id_t process_id
1820 = get_amd_dbgapi_process_id (inf);
1821 if (process_id == AMD_DBGAPI_PROCESS_NONE)
1823 /* The inferior may not be attached yet. */
1824 continue;
1827 size_t count;
1828 amd_dbgapi_wave_id_t *wave_list;
1829 amd_dbgapi_changed_t changed;
1830 amd_dbgapi_status_t status
1831 = amd_dbgapi_process_wave_list (process_id, &count, &wave_list,
1832 &changed);
1833 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1834 error (_("amd_dbgapi_wave_list failed (%s)"),
1835 get_status_string (status));
1837 if (changed == AMD_DBGAPI_CHANGED_NO)
1838 continue;
1840 /* Create a set and free the wave list. */
1841 std::set<ptid_t::tid_type> threads;
1842 for (size_t i = 0; i < count; ++i)
1843 threads.emplace (wave_list[i].handle);
1845 xfree (wave_list);
1847 /* Prune the wave_ids that already have a thread_info. Any thread_info
1848 which does not have a corresponding wave_id represents a wave which
1849 is gone at this point and should be deleted. */
1850 for (thread_info *tp : inf->threads_safe ())
1851 if (ptid_is_gpu (tp->ptid) && tp->state != THREAD_EXITED)
1853 auto it = threads.find (tp->ptid.tid ());
1855 if (it == threads.end ())
1857 auto wave_id = get_amd_dbgapi_wave_id (tp->ptid);
1858 wave_info &wi = get_thread_wave_info (tp);
1860 /* Waves that were stepping or in progress of being
1861 stopped are guaranteed to report a
1862 WAVE_COMMAND_TERMINATED event if they terminate.
1863 Don't delete such threads until we see the
1864 event. */
1865 if (wi.last_resume_mode == AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
1866 || wi.stopping)
1868 amd_dbgapi_debug_printf
1869 ("wave_%ld disappeared, keeping it"
1870 " (last_resume_mode=%s, stopping=%d)",
1871 wave_id.handle,
1872 resume_mode_to_string (wi.last_resume_mode),
1873 wi.stopping);
1875 else
1877 amd_dbgapi_debug_printf ("wave_%ld disappeared, deleting it",
1878 wave_id.handle);
1879 delete_thread_silent (tp);
1882 else
1883 threads.erase (it);
1886 /* The wave_ids that are left require a new thread_info. */
1887 for (ptid_t::tid_type tid : threads)
1889 ptid_t wave_ptid
1890 = make_gpu_ptid (inf->pid, amd_dbgapi_wave_id_t {tid});
1891 add_gpu_thread (inf, wave_ptid);
1895 /* Give the beneath target a chance to do extra processing. */
1896 this->beneath ()->update_thread_list ();
1899 /* inferior_created observer. */
1901 static void
1902 amd_dbgapi_target_inferior_created (inferior *inf)
1904 /* If the inferior is not running on the native target (e.g. it is running
1905 on a remote target), we don't want to deal with it. */
1906 if (inf->process_target () != get_native_target ())
1907 return;
1909 attach_amd_dbgapi (inf);
1912 /* Callback called when an inferior is cloned. */
1914 static void
1915 amd_dbgapi_target_inferior_cloned (inferior *original_inferior,
1916 inferior *new_inferior)
1918 auto *orig_info = get_amd_dbgapi_inferior_info (original_inferior);
1919 auto *new_info = get_amd_dbgapi_inferior_info (new_inferior);
1921 /* At this point, the process is not started. Therefore it is sufficient to
1922 copy the precise memory request, it will be applied when the process
1923 starts. */
1924 gdb_assert (new_info->process_id == AMD_DBGAPI_PROCESS_NONE);
1925 new_info->precise_memory.requested = orig_info->precise_memory.requested;
1928 /* inferior_execd observer. */
1930 static void
1931 amd_dbgapi_inferior_execd (inferior *exec_inf, inferior *follow_inf)
1933 /* The inferior has EXEC'd and the process image has changed. The dbgapi is
1934 attached to the old process image, so we need to detach and re-attach to
1935 the new process image. */
1936 detach_amd_dbgapi (exec_inf);
1938 /* If using "follow-exec-mode new", carry over the precise-memory setting
1939 to the new inferior (otherwise, FOLLOW_INF and ORIG_INF point to the same
1940 inferior, so this is a no-op). */
1941 get_amd_dbgapi_inferior_info (follow_inf)->precise_memory.requested
1942 = get_amd_dbgapi_inferior_info (exec_inf)->precise_memory.requested;
1944 attach_amd_dbgapi (follow_inf);
1947 /* inferior_forked observer. */
1949 static void
1950 amd_dbgapi_inferior_forked (inferior *parent_inf, inferior *child_inf,
1951 target_waitkind fork_kind)
1953 if (child_inf != nullptr)
1955 /* Copy precise-memory requested value from parent to child. */
1956 amd_dbgapi_inferior_info *parent_info
1957 = get_amd_dbgapi_inferior_info (parent_inf);
1958 amd_dbgapi_inferior_info *child_info
1959 = get_amd_dbgapi_inferior_info (child_inf);
1960 child_info->precise_memory.requested
1961 = parent_info->precise_memory.requested;
1963 if (fork_kind != TARGET_WAITKIND_VFORKED)
1965 scoped_restore_current_thread restore_thread;
1966 switch_to_thread (*child_inf->threads ().begin ());
1967 attach_amd_dbgapi (child_inf);
1972 /* inferior_exit observer.
1974 This covers normal exits, but also detached inferiors (including detached
1975 fork parents). */
1977 static void
1978 amd_dbgapi_inferior_exited (inferior *inf)
1980 detach_amd_dbgapi (inf);
1983 /* inferior_pre_detach observer. */
1985 static void
1986 amd_dbgapi_inferior_pre_detach (inferior *inf)
1988 /* We need to amd-dbgapi-detach before we ptrace-detach. If the amd-dbgapi
1989 target isn't pushed, do that now. If the amd-dbgapi target is pushed,
1990 we'll do it in amd_dbgapi_target::detach. */
1991 if (!inf->target_is_pushed (&the_amd_dbgapi_target))
1992 detach_amd_dbgapi (inf);
1995 /* client_process_get_info callback. */
1997 static amd_dbgapi_status_t
1998 amd_dbgapi_client_process_get_info_callback
1999 (amd_dbgapi_client_process_id_t client_process_id,
2000 amd_dbgapi_client_process_info_t query, size_t value_size, void *value)
2002 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
2004 if (inf->pid == 0)
2005 return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
2007 if (value == nullptr)
2008 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
2010 switch (query)
2012 case AMD_DBGAPI_CLIENT_PROCESS_INFO_OS_PID:
2013 if (value_size != sizeof (amd_dbgapi_os_process_id_t))
2014 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT_COMPATIBILITY;
2016 *static_cast<amd_dbgapi_os_process_id_t *> (value) = inf->pid;
2017 return AMD_DBGAPI_STATUS_SUCCESS;
2019 case AMD_DBGAPI_CLIENT_PROCESS_INFO_CORE_STATE:
2020 return AMD_DBGAPI_STATUS_ERROR_NOT_AVAILABLE;
2023 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
2026 /* insert_breakpoint callback. */
2028 static amd_dbgapi_status_t
2029 amd_dbgapi_insert_breakpoint_callback
2030 (amd_dbgapi_client_process_id_t client_process_id,
2031 amd_dbgapi_global_address_t address,
2032 amd_dbgapi_breakpoint_id_t breakpoint_id)
2034 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
2035 struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
2037 auto it = info->breakpoint_map.find (breakpoint_id.handle);
2038 if (it != info->breakpoint_map.end ())
2039 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
2041 /* We need to find the address in the given inferior's program space. */
2042 scoped_restore_current_thread restore_thread;
2043 switch_to_inferior_no_thread (inf);
2045 /* Create a new breakpoint. */
2046 struct obj_section *section = find_pc_section (address);
2047 if (section == nullptr || section->objfile == nullptr)
2048 return AMD_DBGAPI_STATUS_ERROR;
2050 std::unique_ptr<breakpoint> bp_up
2051 (new amd_dbgapi_target_breakpoint (section->objfile->arch (), address));
2053 breakpoint *bp = install_breakpoint (true, std::move (bp_up), 1);
2055 info->breakpoint_map.emplace (breakpoint_id.handle, bp);
2056 return AMD_DBGAPI_STATUS_SUCCESS;
2059 /* remove_breakpoint callback. */
2061 static amd_dbgapi_status_t
2062 amd_dbgapi_remove_breakpoint_callback
2063 (amd_dbgapi_client_process_id_t client_process_id,
2064 amd_dbgapi_breakpoint_id_t breakpoint_id)
2066 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
2067 struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
2069 auto it = info->breakpoint_map.find (breakpoint_id.handle);
2070 if (it == info->breakpoint_map.end ())
2071 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
2073 delete_breakpoint (it->second);
2074 info->breakpoint_map.erase (it);
2076 return AMD_DBGAPI_STATUS_SUCCESS;
2079 /* xfer_global_memory callback. */
2081 static amd_dbgapi_status_t
2082 amd_dbgapi_xfer_global_memory_callback
2083 (amd_dbgapi_client_process_id_t client_process_id,
2084 amd_dbgapi_global_address_t global_address,
2085 amd_dbgapi_size_t *value_size, void *read_buffer,
2086 const void *write_buffer)
2088 if ((read_buffer != nullptr) == (write_buffer != nullptr))
2089 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT_COMPATIBILITY;
2091 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
2093 /* We need to set inferior_ptid / current_inferior as those are
2094 used by the target which will process the xfer_partial request.
2096 Note that we end up here when amd-dbgapi tries to access device memory or
2097 register content which are at this point mapped/saved in the host process
2098 memory. As a consequence, unwinding GPU frames will most likely call into
2099 here. If we used switch_to_thread to select a host thread, this would
2100 implicitly call reinit_frame_cache. We do not want to clear the frame
2101 cache while trying to build it. */
2102 scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
2103 scoped_restore_current_inferior restore_current_inferior;
2104 scoped_restore_current_program_space restore_program_space;
2105 inferior_ptid = ptid_t (inf->pid);
2106 set_current_inferior (inf);
2107 set_current_program_space (inf->pspace);
2109 target_xfer_status status
2110 = target_xfer_partial (inf->top_target (), TARGET_OBJECT_RAW_MEMORY,
2111 nullptr, static_cast<gdb_byte *> (read_buffer),
2112 static_cast<const gdb_byte *> (write_buffer),
2113 global_address, *value_size, value_size);
2115 if (status == TARGET_XFER_EOF)
2116 return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
2117 else if (status != TARGET_XFER_OK)
2118 return AMD_DBGAPI_STATUS_ERROR_MEMORY_ACCESS;
2120 return AMD_DBGAPI_STATUS_SUCCESS;
2123 /* signal_received observer. */
2125 static void
2126 amd_dbgapi_target_signal_received (gdb_signal sig)
2128 amd_dbgapi_inferior_info *info
2129 = get_amd_dbgapi_inferior_info (current_inferior ());
2131 if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
2132 return;
2134 if (!ptid_is_gpu (inferior_thread ()->ptid))
2135 return;
2137 if (sig != GDB_SIGNAL_SEGV && sig != GDB_SIGNAL_BUS)
2138 return;
2140 if (!info->precise_memory.enabled)
2141 gdb_printf (_("\
2142 Warning: precise memory violation signal reporting is not enabled, reported\n\
2143 location may not be accurate. See \"show amdgpu precise-memory\".\n"));
2146 /* Style for some kinds of messages. */
2148 static cli_style_option fatal_error_style
2149 ("amd_dbgapi_fatal_error", ui_file_style::RED);
2150 static cli_style_option warning_style
2151 ("amd_dbgapi_warning", ui_file_style::YELLOW);
2153 /* BLACK + BOLD means dark gray. */
2154 static cli_style_option trace_style
2155 ("amd_dbgapi_trace", ui_file_style::BLACK, ui_file_style::BOLD);
2157 /* log_message callback. */
2159 static void
2160 amd_dbgapi_log_message_callback (amd_dbgapi_log_level_t level,
2161 const char *message)
2163 std::optional<target_terminal::scoped_restore_terminal_state> tstate;
2165 if (target_supports_terminal_ours ())
2167 tstate.emplace ();
2168 target_terminal::ours_for_output ();
2171 /* Error and warning messages are meant to be printed to the user. */
2172 if (level == AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
2173 || level == AMD_DBGAPI_LOG_LEVEL_WARNING)
2175 begin_line ();
2176 ui_file_style style = (level == AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
2177 ? fatal_error_style : warning_style).style ();
2178 gdb_printf (gdb_stderr, "%ps\n", styled_string (style, message));
2179 return;
2182 /* Print other messages as debug logs. TRACE and VERBOSE messages are
2183 very verbose, print them dark grey so it's easier to spot other messages
2184 through the flood. */
2185 if (level >= AMD_DBGAPI_LOG_LEVEL_TRACE)
2187 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%ps",
2188 styled_string (trace_style.style (), message));
2189 return;
2192 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%s",
2193 message);
2196 /* Callbacks passed to amd_dbgapi_initialize. */
2198 static amd_dbgapi_callbacks_t dbgapi_callbacks = {
2199 .allocate_memory = malloc,
2200 .deallocate_memory = free,
2201 .client_process_get_info = amd_dbgapi_client_process_get_info_callback,
2202 .insert_breakpoint = amd_dbgapi_insert_breakpoint_callback,
2203 .remove_breakpoint = amd_dbgapi_remove_breakpoint_callback,
2204 .xfer_global_memory = amd_dbgapi_xfer_global_memory_callback,
2205 .log_message = amd_dbgapi_log_message_callback,
2208 void
2209 amd_dbgapi_target::close ()
2211 if (amd_dbgapi_async_event_handler != nullptr)
2212 delete_async_event_handler (&amd_dbgapi_async_event_handler);
2215 /* Callback for "show amdgpu precise-memory". */
2217 static void
2218 show_precise_memory_mode (struct ui_file *file, int from_tty,
2219 struct cmd_list_element *c, const char *value)
2221 amd_dbgapi_inferior_info *info
2222 = get_amd_dbgapi_inferior_info (current_inferior ());
2224 gdb_printf (file,
2225 _("AMDGPU precise memory access reporting is %s "
2226 "(currently %s).\n"),
2227 info->precise_memory.requested ? "on" : "off",
2228 info->precise_memory.enabled ? "enabled" : "disabled");
2231 /* Callback for "set amdgpu precise-memory". */
2233 static void
2234 set_precise_memory_mode (bool value)
2236 amd_dbgapi_inferior_info *info
2237 = get_amd_dbgapi_inferior_info (current_inferior ());
2239 info->precise_memory.requested = value;
2241 if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
2242 set_process_memory_precision (*info);
2245 /* Return whether precise-memory is requested for the current inferior. */
2247 static bool
2248 get_precise_memory_mode ()
2250 amd_dbgapi_inferior_info *info
2251 = get_amd_dbgapi_inferior_info (current_inferior ());
2253 return info->precise_memory.requested;
2256 /* List of set/show amdgpu commands. */
2257 struct cmd_list_element *set_amdgpu_list;
2258 struct cmd_list_element *show_amdgpu_list;
2260 /* List of set/show debug amd-dbgapi-lib commands. */
2261 struct cmd_list_element *set_debug_amd_dbgapi_lib_list;
2262 struct cmd_list_element *show_debug_amd_dbgapi_lib_list;
2264 /* Mapping from amd-dbgapi log level enum values to text. */
2266 static constexpr const char *debug_amd_dbgapi_lib_log_level_enums[] =
2268 /* [AMD_DBGAPI_LOG_LEVEL_NONE] = */ "off",
2269 /* [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR] = */ "error",
2270 /* [AMD_DBGAPI_LOG_LEVEL_WARNING] = */ "warning",
2271 /* [AMD_DBGAPI_LOG_LEVEL_INFO] = */ "info",
2272 /* [AMD_DBGAPI_LOG_LEVEL_TRACE] = */ "trace",
2273 /* [AMD_DBGAPI_LOG_LEVEL_VERBOSE] = */ "verbose",
2274 nullptr
2277 /* Storage for "set debug amd-dbgapi-lib log-level". */
2279 static const char *debug_amd_dbgapi_lib_log_level
2280 = debug_amd_dbgapi_lib_log_level_enums[AMD_DBGAPI_LOG_LEVEL_WARNING];
2282 /* Get the amd-dbgapi library log level requested by the user. */
2284 static amd_dbgapi_log_level_t
2285 get_debug_amd_dbgapi_lib_log_level ()
2287 for (size_t pos = 0;
2288 debug_amd_dbgapi_lib_log_level_enums[pos] != nullptr;
2289 ++pos)
2290 if (debug_amd_dbgapi_lib_log_level
2291 == debug_amd_dbgapi_lib_log_level_enums[pos])
2292 return static_cast<amd_dbgapi_log_level_t> (pos);
2294 gdb_assert_not_reached ("invalid log level");
2297 /* Callback for "set debug amd-dbgapi log-level", apply the selected log level
2298 to the library. */
2300 static void
2301 set_debug_amd_dbgapi_lib_log_level (const char *args, int from_tty,
2302 struct cmd_list_element *c)
2304 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ());
2307 /* Callback for "show debug amd-dbgapi log-level". */
2309 static void
2310 show_debug_amd_dbgapi_lib_log_level (struct ui_file *file, int from_tty,
2311 struct cmd_list_element *c,
2312 const char *value)
2314 gdb_printf (file, _("The amd-dbgapi library log level is %s.\n"), value);
2317 /* If the amd-dbgapi library is not attached to any process, finalize and
2318 re-initialize it so that the handle ID numbers will all start from the
2319 beginning again. This is only for convenience, not essential. */
2321 static void
2322 maybe_reset_amd_dbgapi ()
2324 for (inferior *inf : all_non_exited_inferiors ())
2326 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
2328 if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
2329 return;
2332 amd_dbgapi_status_t status = amd_dbgapi_finalize ();
2333 if (status != AMD_DBGAPI_STATUS_SUCCESS)
2334 error (_("amd-dbgapi failed to finalize (%s)"),
2335 get_status_string (status));
2337 status = amd_dbgapi_initialize (&dbgapi_callbacks);
2338 if (status != AMD_DBGAPI_STATUS_SUCCESS)
2339 error (_("amd-dbgapi failed to initialize (%s)"),
2340 get_status_string (status));
2343 extern initialize_file_ftype _initialize_amd_dbgapi_target;
2345 void
2346 _initialize_amd_dbgapi_target ()
2348 /* Make sure the loaded debugger library version is greater than or equal to
2349 the one used to build GDB. */
2350 uint32_t major, minor, patch;
2351 amd_dbgapi_get_version (&major, &minor, &patch);
2352 if (major != AMD_DBGAPI_VERSION_MAJOR || minor < AMD_DBGAPI_VERSION_MINOR)
2353 error (_("amd-dbgapi library version mismatch, got %d.%d.%d, need %d.%d+"),
2354 major, minor, patch, AMD_DBGAPI_VERSION_MAJOR,
2355 AMD_DBGAPI_VERSION_MINOR);
2357 /* Initialize the AMD Debugger API. */
2358 amd_dbgapi_status_t status = amd_dbgapi_initialize (&dbgapi_callbacks);
2359 if (status != AMD_DBGAPI_STATUS_SUCCESS)
2360 error (_("amd-dbgapi failed to initialize (%s)"),
2361 get_status_string (status));
2363 /* Set the initial log level. */
2364 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ());
2366 /* Install observers. */
2367 gdb::observers::inferior_cloned.attach (amd_dbgapi_target_inferior_cloned,
2368 "amd-dbgapi");
2369 gdb::observers::signal_received.attach (amd_dbgapi_target_signal_received,
2370 "amd-dbgapi");
2371 gdb::observers::inferior_created.attach
2372 (amd_dbgapi_target_inferior_created,
2373 amd_dbgapi_target_inferior_created_observer_token, "amd-dbgapi");
2374 gdb::observers::inferior_execd.attach (amd_dbgapi_inferior_execd, "amd-dbgapi");
2375 gdb::observers::inferior_forked.attach (amd_dbgapi_inferior_forked, "amd-dbgapi");
2376 gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi");
2377 gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi");
2378 gdb::observers::thread_deleted.attach (amd_dbgapi_thread_deleted, "amd-dbgapi");
2380 add_basic_prefix_cmd ("amdgpu", no_class,
2381 _("Generic command for setting amdgpu flags."),
2382 &set_amdgpu_list, 0, &setlist);
2384 add_show_prefix_cmd ("amdgpu", no_class,
2385 _("Generic command for showing amdgpu flags."),
2386 &show_amdgpu_list, 0, &showlist);
2388 add_setshow_boolean_cmd ("precise-memory", no_class,
2389 _("Set precise-memory mode."),
2390 _("Show precise-memory mode."), _("\
2391 If on, precise memory reporting is enabled if/when the inferior is running.\n\
2392 If off (default), precise memory reporting is disabled."),
2393 set_precise_memory_mode,
2394 get_precise_memory_mode,
2395 show_precise_memory_mode,
2396 &set_amdgpu_list, &show_amdgpu_list);
2398 add_basic_prefix_cmd ("amd-dbgapi-lib", no_class,
2399 _("Generic command for setting amd-dbgapi library "
2400 "debugging flags."),
2401 &set_debug_amd_dbgapi_lib_list, 0, &setdebuglist);
2403 add_show_prefix_cmd ("amd-dbgapi-lib", no_class,
2404 _("Generic command for showing amd-dbgapi library "
2405 "debugging flags."),
2406 &show_debug_amd_dbgapi_lib_list, 0, &showdebuglist);
2408 add_setshow_enum_cmd ("log-level", class_maintenance,
2409 debug_amd_dbgapi_lib_log_level_enums,
2410 &debug_amd_dbgapi_lib_log_level,
2411 _("Set the amd-dbgapi library log level."),
2412 _("Show the amd-dbgapi library log level."),
2413 _("off == no logging is enabled\n"
2414 "error == fatal errors are reported\n"
2415 "warning == fatal errors and warnings are reported\n"
2416 "info == fatal errors, warnings, and info "
2417 "messages are reported\n"
2418 "trace == fatal errors, warnings, info, and "
2419 "API tracing messages are reported\n"
2420 "verbose == all messages are reported"),
2421 set_debug_amd_dbgapi_lib_log_level,
2422 show_debug_amd_dbgapi_lib_log_level,
2423 &set_debug_amd_dbgapi_lib_list,
2424 &show_debug_amd_dbgapi_lib_list);
2426 add_setshow_boolean_cmd ("amd-dbgapi", class_maintenance,
2427 &debug_amd_dbgapi,
2428 _("Set debugging of amd-dbgapi target."),
2429 _("Show debugging of amd-dbgapi target."),
2430 _("\
2431 When on, print debug messages relating to the amd-dbgapi target."),
2432 nullptr, nullptr,
2433 &setdebuglist, &showdebuglist);