Automatic date update in version.in
[binutils-gdb.git] / gdb / amd-dbgapi-target.c
blobae8c1ea14e37d7cf2a634342daf7905e3d39e4b2
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/>. */
20 #include "defs.h"
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"
36 /* When true, print debug messages relating to the amd-dbgapi target. */
38 static bool debug_amd_dbgapi = false;
40 /* Make a copy of S styled in green. */
42 static std::string
43 make_green (const char *s)
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 ();
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. */
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";
59 /* Styled variants of the above. */
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);
66 /* Return the styled or unstyled variant of the amd-dbgapi module name,
67 depending on whether gdb_stdlog can emit colors. */
69 static const char *
70 amd_dbgapi_debug_module ()
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;
78 /* Same as the above, but for the amd-dbgapi-lib module name. */
80 static const char *
81 amd_dbgapi_lib_debug_module ()
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;
89 /* Print an amd-dbgapi debug statement. */
91 #define amd_dbgapi_debug_printf(fmt, ...) \
92 debug_prefixed_printf_cond (debug_amd_dbgapi, \
93 amd_dbgapi_debug_module (), \
94 fmt, ##__VA_ARGS__)
96 /* Print amd-dbgapi start/end debug statements. */
98 #define AMD_DBGAPI_SCOPED_DEBUG_START_END(fmt, ...) \
99 scoped_debug_start_end (debug_amd_dbgapi, amd_dbgapi_debug_module (), \
100 fmt, ##__VA_ARGS__)
102 /* inferior_created observer token. */
104 static gdb::observers::token amd_dbgapi_target_inferior_created_observer_token;
106 const gdb::observers::token &
107 get_amd_dbgapi_target_inferior_created_observer_token ()
109 return amd_dbgapi_target_inferior_created_observer_token;
112 /* A type holding coordinates, etc. info for a given wave. */
114 struct wave_coordinates
116 /* The wave. Set by the ctor. */
117 amd_dbgapi_wave_id_t wave_id;
119 /* All these fields are initialized here to a value that is printed
120 as "?". */
121 amd_dbgapi_dispatch_id_t dispatch_id = AMD_DBGAPI_DISPATCH_NONE;
122 amd_dbgapi_queue_id_t queue_id = AMD_DBGAPI_QUEUE_NONE;
123 amd_dbgapi_agent_id_t agent_id = AMD_DBGAPI_AGENT_NONE;
124 uint32_t group_ids[3] {UINT32_MAX, UINT32_MAX, UINT32_MAX};
125 uint32_t wave_in_group = UINT32_MAX;
127 explicit wave_coordinates (amd_dbgapi_wave_id_t wave_id)
128 : wave_id (wave_id)
131 /* Return the target ID string for the wave this wave_coordinates is
132 for. */
133 std::string to_string () const;
135 /* Pull out coordinates info from the amd-dbgapi library. */
136 void fetch ();
139 /* A type holding info about a given wave. */
141 struct wave_info
143 /* We cache the coordinates info because we need it after a wave
144 exits. The wave's ID is here. */
145 wave_coordinates coords;
147 /* The last resume_mode passed to amd_dbgapi_wave_resume for this
148 wave. We track this because we are guaranteed to see a
149 WAVE_COMMAND_TERMINATED event if a stepping wave terminates, and
150 we need to know to not delete such a wave until we process that
151 event. */
152 amd_dbgapi_resume_mode_t last_resume_mode = AMD_DBGAPI_RESUME_MODE_NORMAL;
154 /* Whether we've called amd_dbgapi_wave_stop for this wave and are
155 waiting for its stop event. Similarly, we track this because
156 we're guaranteed to get a WAVE_COMMAND_TERMINATED event if the
157 wave terminates while being stopped. */
158 bool stopping = false;
160 explicit wave_info (amd_dbgapi_wave_id_t wave_id)
161 : coords (wave_id)
163 coords.fetch ();
167 /* Big enough to hold the size of the largest register in bytes. */
168 #define AMDGPU_MAX_REGISTER_SIZE 256
170 /* amd-dbgapi-specific inferior data. */
172 struct amd_dbgapi_inferior_info
174 explicit amd_dbgapi_inferior_info (inferior *inf,
175 bool precise_memory_requested = false)
176 : inf (inf)
178 precise_memory.requested = precise_memory_requested;
181 /* Backlink to inferior. */
182 inferior *inf;
184 /* The amd_dbgapi_process_id for this inferior. */
185 amd_dbgapi_process_id_t process_id = AMD_DBGAPI_PROCESS_NONE;
187 /* The amd_dbgapi_notifier_t for this inferior. */
188 amd_dbgapi_notifier_t notifier = -1;
190 /* The status of the inferior's runtime support. */
191 amd_dbgapi_runtime_state_t runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED;
193 /* This value mirrors the current "forward progress needed" value for this
194 process in amd-dbgapi. It is used to avoid unnecessary calls to
195 amd_dbgapi_process_set_progress, to reduce the noise in the logs.
197 Initialized to true, since that's the default in amd-dbgapi too. */
198 bool forward_progress_required = true;
200 struct
202 /* Whether precise memory reporting is requested. */
203 bool requested;
205 /* Whether precise memory was requested and successfully enabled by
206 dbgapi (it may not be available for the current hardware, for
207 instance). */
208 bool enabled = false;
209 } precise_memory;
211 std::unordered_map<decltype (amd_dbgapi_breakpoint_id_t::handle),
212 struct breakpoint *>
213 breakpoint_map;
215 /* List of pending events the amd-dbgapi target retrieved from the dbgapi. */
216 std::list<std::pair<ptid_t, target_waitstatus>> wave_events;
218 /* Map of wave ID to wave_info. We cache wave_info objects because
219 we need to access the info after the wave is gone, in the thread
220 exit nofication. E.g.:
221 [AMDGPU Wave 1:4:1:1 (0,0,0)/0 exited]
223 wave_info objects are added when we first see the wave, and
224 removed from a thread_deleted observer. */
225 std::unordered_map<decltype (amd_dbgapi_wave_id_t::handle), wave_info>
226 wave_info_map;
229 static amd_dbgapi_event_id_t process_event_queue
230 (amd_dbgapi_process_id_t process_id,
231 amd_dbgapi_event_kind_t until_event_kind = AMD_DBGAPI_EVENT_KIND_NONE);
233 static const target_info amd_dbgapi_target_info = {
234 "amd-dbgapi",
235 N_("AMD Debugger API"),
236 N_("GPU debugging using the AMD Debugger API")
239 static amd_dbgapi_log_level_t get_debug_amd_dbgapi_lib_log_level ();
241 struct amd_dbgapi_target final : public target_ops
243 const target_info &
244 info () const override
246 return amd_dbgapi_target_info;
248 strata
249 stratum () const override
251 return arch_stratum;
254 void close () override;
255 void mourn_inferior () override;
256 void detach (inferior *inf, int from_tty) override;
258 void async (bool enable) override;
260 bool has_pending_events () override;
261 ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
262 void resume (ptid_t, int, enum gdb_signal) override;
263 void commit_resumed () override;
264 void stop (ptid_t ptid) override;
266 void fetch_registers (struct regcache *, int) override;
267 void store_registers (struct regcache *, int) override;
269 void update_thread_list () override;
271 struct gdbarch *thread_architecture (ptid_t) override;
273 void thread_events (int enable) override;
275 std::string pid_to_str (ptid_t ptid) override;
277 const char *thread_name (thread_info *tp) override;
279 const char *extra_thread_info (thread_info *tp) override;
281 bool thread_alive (ptid_t ptid) override;
283 enum target_xfer_status xfer_partial (enum target_object object,
284 const char *annex, gdb_byte *readbuf,
285 const gdb_byte *writebuf,
286 ULONGEST offset, ULONGEST len,
287 ULONGEST *xfered_len) override;
289 bool stopped_by_watchpoint () override;
291 bool stopped_by_sw_breakpoint () override;
292 bool stopped_by_hw_breakpoint () override;
294 private:
295 /* True if we must report thread events. */
296 bool m_report_thread_events = false;
298 /* Cache for the last value returned by thread_architecture. */
299 gdbarch *m_cached_arch = nullptr;
300 ptid_t::tid_type m_cached_arch_tid = 0;
303 static struct amd_dbgapi_target the_amd_dbgapi_target;
305 /* Per-inferior data key. */
307 static const registry<inferior>::key<amd_dbgapi_inferior_info>
308 amd_dbgapi_inferior_data;
310 /* Fetch the amd_dbgapi_inferior_info data for the given inferior. */
312 static struct amd_dbgapi_inferior_info *
313 get_amd_dbgapi_inferior_info (struct inferior *inferior)
315 amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (inferior);
317 if (info == nullptr)
318 info = amd_dbgapi_inferior_data.emplace (inferior, inferior);
320 return info;
323 /* The async event handler registered with the event loop, indicating that we
324 might have events to report to the core and that we'd like our wait method
325 to be called.
327 This is nullptr when async is disabled and non-nullptr when async is
328 enabled.
330 It is marked when a notifier fd tells us there's an event available. The
331 callback triggers handle_inferior_event in order to pull the event from
332 amd-dbgapi and handle it. */
334 static async_event_handler *amd_dbgapi_async_event_handler = nullptr;
336 std::string
337 wave_coordinates::to_string () const
339 std::string str = "AMDGPU Wave";
341 str += (agent_id != AMD_DBGAPI_AGENT_NONE
342 ? string_printf (" %ld", agent_id.handle)
343 : " ?");
345 str += (queue_id != AMD_DBGAPI_QUEUE_NONE
346 ? string_printf (":%ld", queue_id.handle)
347 : ":?");
349 str += (dispatch_id != AMD_DBGAPI_DISPATCH_NONE
350 ? string_printf (":%ld", dispatch_id.handle)
351 : ":?");
353 str += string_printf (":%ld", wave_id.handle);
355 str += (group_ids[0] != UINT32_MAX
356 ? string_printf (" (%d,%d,%d)", group_ids[0], group_ids[1],
357 group_ids[2])
358 : " (?,?,?)");
360 str += (wave_in_group != UINT32_MAX
361 ? string_printf ("/%d", wave_in_group)
362 : "/?");
364 return str;
367 /* Read in wave_info for WAVE_ID. */
369 void
370 wave_coordinates::fetch ()
372 /* Any field that fails to be read is left with its in-class
373 initialized value, which is printed as "?". */
375 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_AGENT,
376 sizeof (agent_id), &agent_id);
377 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_QUEUE,
378 sizeof (queue_id), &queue_id);
379 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_DISPATCH,
380 sizeof (dispatch_id), &dispatch_id);
382 amd_dbgapi_wave_get_info (wave_id,
383 AMD_DBGAPI_WAVE_INFO_WORKGROUP_COORD,
384 sizeof (group_ids), &group_ids);
386 amd_dbgapi_wave_get_info (wave_id,
387 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORKGROUP,
388 sizeof (wave_in_group), &wave_in_group);
391 /* Get the wave_info object for TP, from the wave_info map. It is
392 assumed that the wave is in the map. */
394 static wave_info &
395 get_thread_wave_info (thread_info *tp)
397 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (tp->inf);
398 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (tp->ptid);
400 auto it = info->wave_info_map.find (wave_id.handle);
401 gdb_assert (it != info->wave_info_map.end ());
403 return it->second;
406 /* Clear our async event handler. */
408 static void
409 async_event_handler_clear ()
411 gdb_assert (amd_dbgapi_async_event_handler != nullptr);
412 clear_async_event_handler (amd_dbgapi_async_event_handler);
415 /* Mark our async event handler. */
417 static void
418 async_event_handler_mark ()
420 gdb_assert (amd_dbgapi_async_event_handler != nullptr);
421 mark_async_event_handler (amd_dbgapi_async_event_handler);
424 /* Set forward progress requirement to REQUIRE for all processes of PROC_TARGET
425 matching PTID. */
427 static void
428 require_forward_progress (ptid_t ptid, process_stratum_target *proc_target,
429 bool require)
431 for (inferior *inf : all_inferiors (proc_target))
433 if (ptid != minus_one_ptid && inf->pid != ptid.pid ())
434 continue;
436 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
438 if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
439 continue;
441 /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */
442 if (info->forward_progress_required == require)
443 continue;
445 amd_dbgapi_status_t status
446 = amd_dbgapi_process_set_progress
447 (info->process_id, (require
448 ? AMD_DBGAPI_PROGRESS_NORMAL
449 : AMD_DBGAPI_PROGRESS_NO_FORWARD));
450 gdb_assert (status == AMD_DBGAPI_STATUS_SUCCESS);
452 info->forward_progress_required = require;
454 /* If ptid targets a single inferior and we have found it, no need to
455 continue. */
456 if (ptid != minus_one_ptid)
457 break;
461 /* See amd-dbgapi-target.h. */
463 amd_dbgapi_process_id_t
464 get_amd_dbgapi_process_id (inferior *inf)
466 return get_amd_dbgapi_inferior_info (inf)->process_id;
469 /* A breakpoint dbgapi wants us to insert, to handle shared library
470 loading/unloading. */
472 struct amd_dbgapi_target_breakpoint : public code_breakpoint
474 amd_dbgapi_target_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
475 : code_breakpoint (gdbarch, bp_breakpoint)
477 symtab_and_line sal;
478 sal.pc = address;
479 sal.section = find_pc_overlay (sal.pc);
480 sal.pspace = current_program_space;
481 add_location (sal);
483 pspace = current_program_space;
484 disposition = disp_donttouch;
487 void re_set () override;
488 void check_status (struct bpstat *bs) override;
491 void
492 amd_dbgapi_target_breakpoint::re_set ()
494 /* Nothing. */
497 void
498 amd_dbgapi_target_breakpoint::check_status (struct bpstat *bs)
500 struct inferior *inf = current_inferior ();
501 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
502 amd_dbgapi_status_t status;
504 bs->stop = 0;
505 bs->print_it = print_it_noop;
507 /* Find the address the breakpoint is set at. */
508 auto match_breakpoint
509 = [bs] (const decltype (info->breakpoint_map)::value_type &value)
510 { return value.second == bs->breakpoint_at; };
511 auto it
512 = std::find_if (info->breakpoint_map.begin (), info->breakpoint_map.end (),
513 match_breakpoint);
515 if (it == info->breakpoint_map.end ())
516 error (_("Could not find breakpoint_id for breakpoint at %s"),
517 paddress (inf->arch (), bs->bp_location_at->address));
519 amd_dbgapi_breakpoint_id_t breakpoint_id { it->first };
520 amd_dbgapi_breakpoint_action_t action;
522 status = amd_dbgapi_report_breakpoint_hit
523 (breakpoint_id,
524 reinterpret_cast<amd_dbgapi_client_thread_id_t> (inferior_thread ()),
525 &action);
527 if (status != AMD_DBGAPI_STATUS_SUCCESS)
528 error (_("amd_dbgapi_report_breakpoint_hit failed for breakpoint %ld "
529 "at %s (%s)"),
530 breakpoint_id.handle, paddress (inf->arch (), bs->bp_location_at->address),
531 get_status_string (status));
533 if (action == AMD_DBGAPI_BREAKPOINT_ACTION_RESUME)
534 return;
536 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
537 a breakpoint resume event for this breakpoint_id is seen. */
538 amd_dbgapi_event_id_t resume_event_id
539 = process_event_queue (info->process_id,
540 AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
542 /* We should always get a breakpoint_resume event after processing all
543 events generated by reporting the breakpoint hit. */
544 gdb_assert (resume_event_id != AMD_DBGAPI_EVENT_NONE);
546 amd_dbgapi_breakpoint_id_t resume_breakpoint_id;
547 status = amd_dbgapi_event_get_info (resume_event_id,
548 AMD_DBGAPI_EVENT_INFO_BREAKPOINT,
549 sizeof (resume_breakpoint_id),
550 &resume_breakpoint_id);
552 if (status != AMD_DBGAPI_STATUS_SUCCESS)
553 error (_("amd_dbgapi_event_get_info failed (%s)"), get_status_string (status));
555 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint]
556 sequences cannot interleave, so this breakpoint resume event must be
557 for our breakpoint_id. */
558 if (resume_breakpoint_id != breakpoint_id)
559 error (_("breakpoint resume event is not for this breakpoint. "
560 "Expected breakpoint_%ld, got breakpoint_%ld"),
561 breakpoint_id.handle, resume_breakpoint_id.handle);
563 amd_dbgapi_event_processed (resume_event_id);
566 bool
567 amd_dbgapi_target::thread_alive (ptid_t ptid)
569 if (!ptid_is_gpu (ptid))
570 return beneath ()->thread_alive (ptid);
572 /* Check that the wave_id is valid. */
574 amd_dbgapi_wave_state_t state;
575 amd_dbgapi_status_t status
576 = amd_dbgapi_wave_get_info (get_amd_dbgapi_wave_id (ptid),
577 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state),
578 &state);
579 return status == AMD_DBGAPI_STATUS_SUCCESS;
582 const char *
583 amd_dbgapi_target::thread_name (thread_info *tp)
585 if (!ptid_is_gpu (tp->ptid))
586 return beneath ()->thread_name (tp);
588 return nullptr;
591 std::string
592 amd_dbgapi_target::pid_to_str (ptid_t ptid)
594 if (!ptid_is_gpu (ptid))
595 return beneath ()->pid_to_str (ptid);
597 process_stratum_target *proc_target = current_inferior ()->process_target ();
598 inferior *inf = find_inferior_pid (proc_target, ptid.pid ());
599 gdb_assert (inf != nullptr);
600 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
602 auto wave_id = get_amd_dbgapi_wave_id (ptid);
604 auto it = info->wave_info_map.find (wave_id.handle);
605 if (it != info->wave_info_map.end ())
606 return it->second.coords.to_string ();
608 /* A wave we don't know about. Shouldn't usually happen, but
609 asserting and bringing down the session is a bit too harsh. Just
610 print all unknown info as "?"s. */
611 return wave_coordinates (wave_id).to_string ();
614 const char *
615 amd_dbgapi_target::extra_thread_info (thread_info *tp)
617 if (!ptid_is_gpu (tp->ptid))
618 beneath ()->extra_thread_info (tp);
620 return nullptr;
623 target_xfer_status
624 amd_dbgapi_target::xfer_partial (enum target_object object, const char *annex,
625 gdb_byte *readbuf, const gdb_byte *writebuf,
626 ULONGEST offset, ULONGEST requested_len,
627 ULONGEST *xfered_len)
629 std::optional<scoped_restore_current_thread> maybe_restore_thread;
631 if (!ptid_is_gpu (inferior_ptid))
632 return beneath ()->xfer_partial (object, annex, readbuf, writebuf, offset,
633 requested_len, xfered_len);
635 gdb_assert (requested_len > 0);
636 gdb_assert (xfered_len != nullptr);
638 if (object != TARGET_OBJECT_MEMORY)
639 return TARGET_XFER_E_IO;
641 amd_dbgapi_process_id_t process_id
642 = get_amd_dbgapi_process_id (current_inferior ());
643 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid);
645 size_t len = requested_len;
646 amd_dbgapi_status_t status;
648 if (readbuf != nullptr)
649 status = amd_dbgapi_read_memory (process_id, wave_id, 0,
650 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL,
651 offset, &len, readbuf);
652 else
653 status = amd_dbgapi_write_memory (process_id, wave_id, 0,
654 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL,
655 offset, &len, writebuf);
657 if (status != AMD_DBGAPI_STATUS_SUCCESS)
658 return TARGET_XFER_E_IO;
660 *xfered_len = len;
661 return TARGET_XFER_OK;
664 bool
665 amd_dbgapi_target::stopped_by_watchpoint ()
667 if (!ptid_is_gpu (inferior_ptid))
668 return beneath ()->stopped_by_watchpoint ();
670 return false;
673 void
674 amd_dbgapi_target::resume (ptid_t scope_ptid, int step, enum gdb_signal signo)
676 amd_dbgapi_debug_printf ("scope_ptid = %s", scope_ptid.to_string ().c_str ());
678 /* The amd_dbgapi_exceptions_t matching SIGNO will only be used if the
679 thread which is the target of the signal SIGNO is a GPU thread. If so,
680 make sure that there is a corresponding amd_dbgapi_exceptions_t for SIGNO
681 before we try to resume any thread. */
682 amd_dbgapi_exceptions_t exception = AMD_DBGAPI_EXCEPTION_NONE;
683 if (ptid_is_gpu (inferior_ptid))
685 switch (signo)
687 case GDB_SIGNAL_BUS:
688 exception = AMD_DBGAPI_EXCEPTION_WAVE_APERTURE_VIOLATION;
689 break;
690 case GDB_SIGNAL_SEGV:
691 exception = AMD_DBGAPI_EXCEPTION_WAVE_MEMORY_VIOLATION;
692 break;
693 case GDB_SIGNAL_ILL:
694 exception = AMD_DBGAPI_EXCEPTION_WAVE_ILLEGAL_INSTRUCTION;
695 break;
696 case GDB_SIGNAL_FPE:
697 exception = AMD_DBGAPI_EXCEPTION_WAVE_MATH_ERROR;
698 break;
699 case GDB_SIGNAL_ABRT:
700 exception = AMD_DBGAPI_EXCEPTION_WAVE_ABORT;
701 break;
702 case GDB_SIGNAL_TRAP:
703 exception = AMD_DBGAPI_EXCEPTION_WAVE_TRAP;
704 break;
705 case GDB_SIGNAL_0:
706 exception = AMD_DBGAPI_EXCEPTION_NONE;
707 break;
708 default:
709 error (_("Resuming with signal %s is not supported by this agent."),
710 gdb_signal_to_name (signo));
714 if (!ptid_is_gpu (inferior_ptid) || scope_ptid != inferior_ptid)
716 beneath ()->resume (scope_ptid, step, signo);
718 /* If the request is for a single thread, we are done. */
719 if (scope_ptid == inferior_ptid)
720 return;
723 process_stratum_target *proc_target = current_inferior ()->process_target ();
725 /* Disable forward progress requirement. */
726 require_forward_progress (scope_ptid, proc_target, false);
728 for (thread_info *thread : all_non_exited_threads (proc_target, scope_ptid))
730 if (!ptid_is_gpu (thread->ptid))
731 continue;
733 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid);
734 amd_dbgapi_status_t status;
736 wave_info &wi = get_thread_wave_info (thread);
737 amd_dbgapi_resume_mode_t &resume_mode = wi.last_resume_mode;
738 amd_dbgapi_exceptions_t wave_exception;
739 if (thread->ptid == inferior_ptid)
741 resume_mode = (step
742 ? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
743 : AMD_DBGAPI_RESUME_MODE_NORMAL);
744 wave_exception = exception;
746 else
748 resume_mode = AMD_DBGAPI_RESUME_MODE_NORMAL;
749 wave_exception = AMD_DBGAPI_EXCEPTION_NONE;
752 status = amd_dbgapi_wave_resume (wave_id, resume_mode, wave_exception);
753 if (status != AMD_DBGAPI_STATUS_SUCCESS
754 /* Ignore the error that wave is no longer valid as that could
755 indicate that the process has exited. GDB treats resuming a
756 thread that no longer exists as being successful. */
757 && status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
758 error (_("wave_resume for wave_%ld failed (%s)"), wave_id.handle,
759 get_status_string (status));
761 wi.stopping = false;
765 void
766 amd_dbgapi_target::commit_resumed ()
768 amd_dbgapi_debug_printf ("called");
770 beneath ()->commit_resumed ();
772 process_stratum_target *proc_target = current_inferior ()->process_target ();
773 require_forward_progress (minus_one_ptid, proc_target, true);
776 /* Return a string version of RESUME_MODE, for debug log purposes. */
778 static const char *
779 resume_mode_to_string (amd_dbgapi_resume_mode_t resume_mode)
781 switch (resume_mode)
783 case AMD_DBGAPI_RESUME_MODE_NORMAL:
784 return "normal";
785 case AMD_DBGAPI_RESUME_MODE_SINGLE_STEP:
786 return "step";
788 gdb_assert_not_reached ("invalid amd_dbgapi_resume_mode_t");
791 void
792 amd_dbgapi_target::stop (ptid_t ptid)
794 amd_dbgapi_debug_printf ("ptid = %s", ptid.to_string ().c_str ());
796 bool many_threads = ptid == minus_one_ptid || ptid.is_pid ();
798 if (!ptid_is_gpu (ptid) || many_threads)
800 beneath ()->stop (ptid);
802 /* The request is for a single thread, we are done. */
803 if (!many_threads)
804 return;
807 auto stop_one_thread = [this] (thread_info *thread)
809 gdb_assert (thread != nullptr);
811 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid);
812 amd_dbgapi_wave_state_t state;
813 amd_dbgapi_status_t status
814 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STATE,
815 sizeof (state), &state);
816 if (status == AMD_DBGAPI_STATUS_SUCCESS)
818 /* If the wave is already known to be stopped then do nothing. */
819 if (state == AMD_DBGAPI_WAVE_STATE_STOP)
820 return;
822 status = amd_dbgapi_wave_stop (wave_id);
823 if (status == AMD_DBGAPI_STATUS_SUCCESS)
825 wave_info &wi = get_thread_wave_info (thread);
826 wi.stopping = true;
827 return;
830 if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
831 error (_("wave_stop for wave_%ld failed (%s)"), wave_id.handle,
832 get_status_string (status));
834 else if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
835 error (_("wave_get_info for wave_%ld failed (%s)"), wave_id.handle,
836 get_status_string (status));
838 /* The status is AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID. The wave
839 could have terminated since the last time the wave list was
840 refreshed. */
842 wave_info &wi = get_thread_wave_info (thread);
843 wi.stopping = true;
845 amd_dbgapi_debug_printf ("got AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID "
846 "for wave_%ld, last_resume_mode=%s, "
847 "report_thread_events=%d",
848 wave_id.handle,
849 resume_mode_to_string (wi.last_resume_mode),
850 m_report_thread_events);
852 /* If the wave was stepping when it terminated, then it is
853 guaranteed that we will see a WAVE_COMMAND_TERMINATED event
854 for it. Don't report a thread exit event or delete the
855 thread yet, until we see such event. */
856 if (wi.last_resume_mode == AMD_DBGAPI_RESUME_MODE_SINGLE_STEP)
857 return;
859 if (m_report_thread_events)
861 get_amd_dbgapi_inferior_info (thread->inf)->wave_events.emplace_back
862 (thread->ptid, target_waitstatus ().set_thread_exited (0));
864 if (target_is_async_p ())
865 async_event_handler_mark ();
868 delete_thread_silent (thread);
871 process_stratum_target *proc_target = current_inferior ()->process_target ();
873 /* Disable forward progress requirement. */
874 require_forward_progress (ptid, proc_target, false);
876 if (!many_threads)
878 /* No need to iterate all non-exited threads if the request is to stop a
879 specific thread. */
880 stop_one_thread (proc_target->find_thread (ptid));
881 return;
884 for (auto *inf : all_inferiors (proc_target))
885 /* Use the threads_safe iterator since stop_one_thread may delete the
886 thread if it has exited. */
887 for (auto *thread : inf->threads_safe ())
888 if (thread->state != THREAD_EXITED && thread->ptid.matches (ptid)
889 && ptid_is_gpu (thread->ptid))
890 stop_one_thread (thread);
893 /* Callback for our async event handler. */
895 static void
896 handle_target_event (gdb_client_data client_data)
898 inferior_event_handler (INF_REG_EVENT);
901 struct scoped_amd_dbgapi_event_processed
903 scoped_amd_dbgapi_event_processed (amd_dbgapi_event_id_t event_id)
904 : m_event_id (event_id)
906 gdb_assert (event_id != AMD_DBGAPI_EVENT_NONE);
909 ~scoped_amd_dbgapi_event_processed ()
911 amd_dbgapi_status_t status = amd_dbgapi_event_processed (m_event_id);
912 if (status != AMD_DBGAPI_STATUS_SUCCESS)
913 warning (_("Failed to acknowledge amd-dbgapi event %" PRIu64),
914 m_event_id.handle);
917 DISABLE_COPY_AND_ASSIGN (scoped_amd_dbgapi_event_processed);
919 private:
920 amd_dbgapi_event_id_t m_event_id;
923 /* Called when a dbgapi notifier fd is readable. CLIENT_DATA is the
924 amd_dbgapi_inferior_info object corresponding to the notifier. */
926 static void
927 dbgapi_notifier_handler (int err, gdb_client_data client_data)
929 amd_dbgapi_inferior_info *info = (amd_dbgapi_inferior_info *) client_data;
930 int ret;
932 /* Drain the notifier pipe. */
935 char buf;
936 ret = read (info->notifier, &buf, 1);
938 while (ret >= 0 || (ret == -1 && errno == EINTR));
940 if (info->inf->target_is_pushed (&the_amd_dbgapi_target))
942 /* The amd-dbgapi target is pushed: signal our async handler, the event
943 will be consumed through our wait method. */
945 async_event_handler_mark ();
947 else
949 /* The amd-dbgapi target is not pushed: if there's an event, the only
950 expected one is one of the RUNTIME kind. If the event tells us the
951 inferior as activated the ROCm runtime, push the amd-dbgapi
952 target. */
954 amd_dbgapi_event_id_t event_id;
955 amd_dbgapi_event_kind_t event_kind;
956 amd_dbgapi_status_t status
957 = amd_dbgapi_process_next_pending_event (info->process_id, &event_id,
958 &event_kind);
959 if (status != AMD_DBGAPI_STATUS_SUCCESS)
960 error (_("next_pending_event failed (%s)"), get_status_string (status));
962 if (event_id == AMD_DBGAPI_EVENT_NONE)
963 return;
965 gdb_assert (event_kind == AMD_DBGAPI_EVENT_KIND_RUNTIME);
967 scoped_amd_dbgapi_event_processed mark_event_processed (event_id);
969 amd_dbgapi_runtime_state_t runtime_state;
970 status = amd_dbgapi_event_get_info (event_id,
971 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
972 sizeof (runtime_state),
973 &runtime_state);
974 if (status != AMD_DBGAPI_STATUS_SUCCESS)
975 error (_("event_get_info for event_%ld failed (%s)"),
976 event_id.handle, get_status_string (status));
978 switch (runtime_state)
980 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS:
981 gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
982 info->runtime_state = runtime_state;
983 amd_dbgapi_debug_printf ("pushing amd-dbgapi target");
984 info->inf->push_target (&the_amd_dbgapi_target);
986 /* The underlying target will already be async if we are running, but not if
987 we are attaching. */
988 if (info->inf->process_target ()->is_async_p ())
990 scoped_restore_current_thread restore_thread;
991 switch_to_inferior_no_thread (info->inf);
993 /* Make sure our async event handler is created. */
994 target_async (true);
996 break;
998 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED:
999 gdb_assert (info->runtime_state
1000 == AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION);
1001 info->runtime_state = runtime_state;
1002 break;
1004 case AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION:
1005 gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
1006 info->runtime_state = runtime_state;
1007 warning (_("amd-dbgapi: unable to enable GPU debugging "
1008 "due to a restriction error"));
1009 break;
1014 void
1015 amd_dbgapi_target::async (bool enable)
1017 beneath ()->async (enable);
1019 if (enable)
1021 if (amd_dbgapi_async_event_handler != nullptr)
1023 /* Already enabled. */
1024 return;
1027 /* The library gives us one notifier file descriptor per inferior (even
1028 the ones that have not yet loaded their runtime). Register them
1029 all with the event loop. */
1030 process_stratum_target *proc_target
1031 = current_inferior ()->process_target ();
1033 for (inferior *inf : all_non_exited_inferiors (proc_target))
1035 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1037 if (info->notifier != -1)
1038 add_file_handler (info->notifier, dbgapi_notifier_handler, info,
1039 string_printf ("amd-dbgapi notifier for pid %d",
1040 inf->pid));
1043 amd_dbgapi_async_event_handler
1044 = create_async_event_handler (handle_target_event, nullptr,
1045 "amd-dbgapi");
1047 /* There may be pending events to handle. Tell the event loop to poll
1048 them. */
1049 async_event_handler_mark ();
1051 else
1053 if (amd_dbgapi_async_event_handler == nullptr)
1054 return;
1056 for (inferior *inf : all_inferiors ())
1058 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1060 if (info->notifier != -1)
1061 delete_file_handler (info->notifier);
1064 delete_async_event_handler (&amd_dbgapi_async_event_handler);
1068 /* Make a ptid for a GPU wave. See comment on ptid_is_gpu for more details. */
1070 static ptid_t
1071 make_gpu_ptid (ptid_t::pid_type pid, amd_dbgapi_wave_id_t wave_id)
1073 return ptid_t (pid, 1, wave_id.handle);
1076 /* When a thread is deleted, remove its wave_info from the inferior's
1077 wave_info map. */
1079 static void
1080 amd_dbgapi_thread_deleted (thread_info *tp)
1082 if (tp->inf->target_at (arch_stratum) == &the_amd_dbgapi_target
1083 && ptid_is_gpu (tp->ptid))
1085 amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (tp->inf);
1086 auto wave_id = get_amd_dbgapi_wave_id (tp->ptid);
1087 auto it = info->wave_info_map.find (wave_id.handle);
1088 gdb_assert (it != info->wave_info_map.end ());
1089 info->wave_info_map.erase (it);
1093 /* Register WAVE_PTID as a new thread in INF's thread list, and record
1094 its wave_info in the inferior's wave_info map. */
1096 static thread_info *
1097 add_gpu_thread (inferior *inf, ptid_t wave_ptid)
1099 process_stratum_target *proc_target = inf->process_target ();
1100 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1102 auto wave_id = get_amd_dbgapi_wave_id (wave_ptid);
1104 if (!info->wave_info_map.try_emplace (wave_id.handle,
1105 wave_info (wave_id)).second)
1106 internal_error ("wave ID %ld already in map", wave_id.handle);
1108 /* Create new GPU threads silently to avoid spamming the terminal
1109 with thousands of "[New Thread ...]" messages. */
1110 thread_info *thread = add_thread_silent (proc_target, wave_ptid);
1111 set_running (proc_target, wave_ptid, true);
1112 set_executing (proc_target, wave_ptid, true);
1113 return thread;
1116 /* Process an event that was just pulled out of the amd-dbgapi library. */
1118 static void
1119 process_one_event (amd_dbgapi_event_id_t event_id,
1120 amd_dbgapi_event_kind_t event_kind)
1122 /* Automatically mark this event processed when going out of scope. */
1123 scoped_amd_dbgapi_event_processed mark_event_processed (event_id);
1125 amd_dbgapi_process_id_t process_id;
1126 amd_dbgapi_status_t status
1127 = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_PROCESS,
1128 sizeof (process_id), &process_id);
1129 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1130 error (_("event_get_info for event_%ld failed (%s)"), event_id.handle,
1131 get_status_string (status));
1133 amd_dbgapi_os_process_id_t pid;
1134 status = amd_dbgapi_process_get_info (process_id,
1135 AMD_DBGAPI_PROCESS_INFO_OS_ID,
1136 sizeof (pid), &pid);
1137 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1138 error (_("process_get_info for process_%ld failed (%s)"),
1139 process_id.handle, get_status_string (status));
1141 auto *proc_target = current_inferior ()->process_target ();
1142 inferior *inf = find_inferior_pid (proc_target, pid);
1143 gdb_assert (inf != nullptr);
1144 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
1146 switch (event_kind)
1148 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED:
1149 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
1151 amd_dbgapi_wave_id_t wave_id;
1152 status
1153 = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_WAVE,
1154 sizeof (wave_id), &wave_id);
1155 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1156 error (_("event_get_info for event_%ld failed (%s)"),
1157 event_id.handle, get_status_string (status));
1159 ptid_t event_ptid = make_gpu_ptid (pid, wave_id);
1160 target_waitstatus ws;
1162 amd_dbgapi_wave_stop_reasons_t stop_reason;
1163 status = amd_dbgapi_wave_get_info (wave_id,
1164 AMD_DBGAPI_WAVE_INFO_STOP_REASON,
1165 sizeof (stop_reason), &stop_reason);
1166 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
1167 && event_kind == AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED)
1168 ws.set_thread_exited (0);
1169 else if (status == AMD_DBGAPI_STATUS_SUCCESS)
1171 if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_APERTURE_VIOLATION)
1172 ws.set_stopped (GDB_SIGNAL_BUS);
1173 else if (stop_reason
1174 & AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION)
1175 ws.set_stopped (GDB_SIGNAL_SEGV);
1176 else if (stop_reason
1177 & AMD_DBGAPI_WAVE_STOP_REASON_ILLEGAL_INSTRUCTION)
1178 ws.set_stopped (GDB_SIGNAL_ILL);
1179 else if (stop_reason
1180 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
1181 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
1182 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
1183 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
1184 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
1185 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
1186 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0))
1187 ws.set_stopped (GDB_SIGNAL_FPE);
1188 else if (stop_reason
1189 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
1190 | AMD_DBGAPI_WAVE_STOP_REASON_WATCHPOINT
1191 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
1192 | AMD_DBGAPI_WAVE_STOP_REASON_DEBUG_TRAP
1193 | AMD_DBGAPI_WAVE_STOP_REASON_TRAP))
1194 ws.set_stopped (GDB_SIGNAL_TRAP);
1195 else if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_ASSERT_TRAP)
1196 ws.set_stopped (GDB_SIGNAL_ABRT);
1197 else
1198 ws.set_stopped (GDB_SIGNAL_0);
1200 thread_info *thread = proc_target->find_thread (event_ptid);
1201 if (thread == nullptr)
1202 thread = add_gpu_thread (inf, event_ptid);
1204 /* If the wave is stopped because of a software breakpoint, the
1205 program counter needs to be adjusted so that it points to the
1206 breakpoint instruction. */
1207 if ((stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT) != 0)
1209 regcache *regcache = get_thread_regcache (thread);
1210 gdbarch *gdbarch = regcache->arch ();
1212 CORE_ADDR pc = regcache_read_pc (regcache);
1213 CORE_ADDR adjusted_pc
1214 = pc - gdbarch_decr_pc_after_break (gdbarch);
1216 if (adjusted_pc != pc)
1217 regcache_write_pc (regcache, adjusted_pc);
1220 else
1221 error (_("wave_get_info for wave_%ld failed (%s)"),
1222 wave_id.handle, get_status_string (status));
1224 info->wave_events.emplace_back (event_ptid, ws);
1225 break;
1228 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED:
1229 /* We get here when the following sequence of events happens:
1231 - the inferior hits the amd-dbgapi "r_brk" internal breakpoint
1232 - amd_dbgapi_target_breakpoint::check_status calls
1233 amd_dbgapi_report_breakpoint_hit, which queues an event of this
1234 kind in dbgapi
1235 - amd_dbgapi_target_breakpoint::check_status calls
1236 process_event_queue, which pulls the event out of dbgapi, and
1237 gets us here
1239 When amd_dbgapi_target_breakpoint::check_status is called, the current
1240 inferior is the inferior that hit the breakpoint, which should still be
1241 the case now. */
1242 gdb_assert (inf == current_inferior ());
1243 handle_solib_event ();
1244 break;
1246 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME:
1247 /* Breakpoint resume events should be handled by the breakpoint
1248 action, and this code should not reach this. */
1249 gdb_assert_not_reached ("unhandled event kind");
1250 break;
1252 case AMD_DBGAPI_EVENT_KIND_RUNTIME:
1254 amd_dbgapi_runtime_state_t runtime_state;
1256 status = amd_dbgapi_event_get_info (event_id,
1257 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
1258 sizeof (runtime_state),
1259 &runtime_state);
1260 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1261 error (_("event_get_info for event_%ld failed (%s)"),
1262 event_id.handle, get_status_string (status));
1264 gdb_assert (runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
1265 gdb_assert
1266 (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
1268 info->runtime_state = runtime_state;
1270 gdb_assert (inf->target_is_pushed (&the_amd_dbgapi_target));
1271 inf->unpush_target (&the_amd_dbgapi_target);
1273 break;
1275 default:
1276 error (_("event kind (%d) not supported"), event_kind);
1280 /* Return a textual version of KIND. */
1282 static const char *
1283 event_kind_str (amd_dbgapi_event_kind_t kind)
1285 switch (kind)
1287 case AMD_DBGAPI_EVENT_KIND_NONE:
1288 return "NONE";
1290 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
1291 return "WAVE_STOP";
1293 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED:
1294 return "WAVE_COMMAND_TERMINATED";
1296 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED:
1297 return "CODE_OBJECT_LIST_UPDATED";
1299 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME:
1300 return "BREAKPOINT_RESUME";
1302 case AMD_DBGAPI_EVENT_KIND_RUNTIME:
1303 return "RUNTIME";
1305 case AMD_DBGAPI_EVENT_KIND_QUEUE_ERROR:
1306 return "QUEUE_ERROR";
1309 gdb_assert_not_reached ("unhandled amd_dbgapi_event_kind_t value");
1312 /* Drain the dbgapi event queue of a given process_id, or of all processes if
1313 process_id is AMD_DBGAPI_PROCESS_NONE. Stop processing the events if an
1314 event of a given kind is requested and `process_id` is not
1315 AMD_DBGAPI_PROCESS_NONE. Wave stop events that are not returned are queued
1316 into their inferior's amd_dbgapi_inferior_info pending wave events. */
1318 static amd_dbgapi_event_id_t
1319 process_event_queue (amd_dbgapi_process_id_t process_id,
1320 amd_dbgapi_event_kind_t until_event_kind)
1322 /* An event of a given type can only be requested from a single
1323 process_id. */
1324 gdb_assert (until_event_kind == AMD_DBGAPI_EVENT_KIND_NONE
1325 || process_id != AMD_DBGAPI_PROCESS_NONE);
1327 while (true)
1329 amd_dbgapi_event_id_t event_id;
1330 amd_dbgapi_event_kind_t event_kind;
1332 amd_dbgapi_status_t status
1333 = amd_dbgapi_process_next_pending_event (process_id, &event_id,
1334 &event_kind);
1336 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1337 error (_("next_pending_event failed (%s)"), get_status_string (status));
1339 if (event_kind != AMD_DBGAPI_EVENT_KIND_NONE)
1340 amd_dbgapi_debug_printf ("Pulled event from dbgapi: "
1341 "event_id.handle = %" PRIu64 ", "
1342 "event_kind = %s",
1343 event_id.handle,
1344 event_kind_str (event_kind));
1346 if (event_id == AMD_DBGAPI_EVENT_NONE || event_kind == until_event_kind)
1347 return event_id;
1349 process_one_event (event_id, event_kind);
1353 bool
1354 amd_dbgapi_target::has_pending_events ()
1356 if (amd_dbgapi_async_event_handler != nullptr
1357 && async_event_handler_marked (amd_dbgapi_async_event_handler))
1358 return true;
1360 return beneath ()->has_pending_events ();
1363 /* Pop one pending event from the per-inferior structures.
1365 If PID is not -1, restrict the search to the inferior with that pid. */
1367 static std::pair<ptid_t, target_waitstatus>
1368 consume_one_event (int pid)
1370 auto *target = current_inferior ()->process_target ();
1371 struct amd_dbgapi_inferior_info *info = nullptr;
1373 if (pid == -1)
1375 for (inferior *inf : all_inferiors (target))
1377 info = get_amd_dbgapi_inferior_info (inf);
1378 if (!info->wave_events.empty ())
1379 break;
1382 gdb_assert (info != nullptr);
1384 else
1386 inferior *inf = find_inferior_pid (target, pid);
1388 gdb_assert (inf != nullptr);
1389 info = get_amd_dbgapi_inferior_info (inf);
1392 if (info->wave_events.empty ())
1393 return { minus_one_ptid, {} };
1395 auto event = info->wave_events.front ();
1396 info->wave_events.pop_front ();
1398 return event;
1401 ptid_t
1402 amd_dbgapi_target::wait (ptid_t ptid, struct target_waitstatus *ws,
1403 target_wait_flags target_options)
1405 gdb_assert (!current_inferior ()->process_target ()->commit_resumed_state);
1406 gdb_assert (ptid == minus_one_ptid || ptid.is_pid ());
1408 amd_dbgapi_debug_printf ("ptid = %s", ptid.to_string ().c_str ());
1410 ptid_t event_ptid = beneath ()->wait (ptid, ws, target_options);
1411 if (event_ptid != minus_one_ptid)
1413 if (ws->kind () == TARGET_WAITKIND_EXITED
1414 || ws->kind () == TARGET_WAITKIND_SIGNALLED)
1416 /* This inferior has exited so drain its dbgapi event queue. */
1417 while (consume_one_event (event_ptid.pid ()).first
1418 != minus_one_ptid)
1421 return event_ptid;
1424 gdb_assert (ws->kind () == TARGET_WAITKIND_NO_RESUMED
1425 || ws->kind () == TARGET_WAITKIND_IGNORE);
1427 /* Flush the async handler first. */
1428 if (target_is_async_p ())
1429 async_event_handler_clear ();
1431 /* There may be more events to process (either already in `wave_events` or
1432 that we need to fetch from dbgapi. Mark the async event handler so that
1433 amd_dbgapi_target::wait gets called again and again, until it eventually
1434 returns minus_one_ptid. */
1435 auto more_events = make_scope_exit ([] ()
1437 if (target_is_async_p ())
1438 async_event_handler_mark ();
1441 auto *proc_target = current_inferior ()->process_target ();
1443 /* Disable forward progress for the specified pid in ptid if it isn't
1444 minus_on_ptid, or all attached processes if ptid is minus_one_ptid. */
1445 require_forward_progress (ptid, proc_target, false);
1447 target_waitstatus gpu_waitstatus;
1448 std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
1449 if (event_ptid == minus_one_ptid)
1451 /* Drain the events for the current inferior from the amd_dbgapi and
1452 preserve the ordering. */
1453 auto info = get_amd_dbgapi_inferior_info (current_inferior ());
1454 process_event_queue (info->process_id, AMD_DBGAPI_EVENT_KIND_NONE);
1456 std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
1457 if (event_ptid == minus_one_ptid)
1459 /* If we requested a specific ptid, and nothing came out, assume
1460 another ptid may have more events, otherwise, keep the
1461 async_event_handler flushed. */
1462 if (ptid == minus_one_ptid)
1463 more_events.release ();
1465 if (ws->kind () == TARGET_WAITKIND_NO_RESUMED)
1467 /* We can't easily check that all GPU waves are stopped, and no
1468 new waves can be created (the GPU has fixed function hardware
1469 to create new threads), so even if the target beneath returns
1470 waitkind_no_resumed, we have to report waitkind_ignore if GPU
1471 debugging is enabled for at least one resumed inferior handled
1472 by the amd-dbgapi target. */
1474 for (inferior *inf : all_inferiors ())
1475 if (inf->target_at (arch_stratum) == &the_amd_dbgapi_target
1476 && get_amd_dbgapi_inferior_info (inf)->runtime_state
1477 == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS)
1479 ws->set_ignore ();
1480 break;
1484 /* There are no events to report, return the target beneath's
1485 waitstatus (either IGNORE or NO_RESUMED). */
1486 return minus_one_ptid;
1490 *ws = gpu_waitstatus;
1491 return event_ptid;
1494 bool
1495 amd_dbgapi_target::stopped_by_sw_breakpoint ()
1497 if (!ptid_is_gpu (inferior_ptid))
1498 return beneath ()->stopped_by_sw_breakpoint ();
1500 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid);
1502 amd_dbgapi_wave_stop_reasons_t stop_reason;
1503 amd_dbgapi_status_t status
1504 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STOP_REASON,
1505 sizeof (stop_reason), &stop_reason);
1507 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1508 return false;
1510 return (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT) != 0;
1513 bool
1514 amd_dbgapi_target::stopped_by_hw_breakpoint ()
1516 if (!ptid_is_gpu (inferior_ptid))
1517 return beneath ()->stopped_by_hw_breakpoint ();
1519 return false;
1522 /* Set the process' memory access reporting precision mode.
1524 Warn if the requested mode is not supported on at least one agent in the
1525 process.
1527 Error out if setting the requested mode failed for some other reason. */
1529 static void
1530 set_process_memory_precision (amd_dbgapi_inferior_info &info)
1532 auto mode = (info.precise_memory.requested
1533 ? AMD_DBGAPI_MEMORY_PRECISION_PRECISE
1534 : AMD_DBGAPI_MEMORY_PRECISION_NONE);
1535 amd_dbgapi_status_t status
1536 = amd_dbgapi_set_memory_precision (info.process_id, mode);
1538 if (status == AMD_DBGAPI_STATUS_SUCCESS)
1539 info.precise_memory.enabled = info.precise_memory.requested;
1540 else if (status == AMD_DBGAPI_STATUS_ERROR_NOT_SUPPORTED)
1541 warning (_("AMDGPU precise memory access reporting could not be enabled."));
1542 else if (status != AMD_DBGAPI_STATUS_SUCCESS)
1543 error (_("amd_dbgapi_set_memory_precision failed (%s)"),
1544 get_status_string (status));
1547 /* Make the amd-dbgapi library attach to the process behind INF.
1549 Note that this is unrelated to the "attach" GDB concept / command.
1551 By attaching to the process, we get a notifier fd that tells us when it
1552 activates the ROCm runtime and when there are subsequent debug events. */
1554 static void
1555 attach_amd_dbgapi (inferior *inf)
1557 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num);
1559 if (!target_can_async_p ())
1561 warning (_("The amd-dbgapi target requires the target beneath to be "
1562 "asynchronous, GPU debugging is disabled"));
1563 return;
1566 /* dbgapi can't attach to a vfork child (a process born from a vfork that
1567 hasn't exec'ed yet) while we are still attached to the parent. It would
1568 not be useful for us to attach to vfork children anyway, because vfork
1569 children are very restricted in what they can do (see vfork(2)) and aren't
1570 going to launch some GPU programs that we need to debug. To avoid this
1571 problem, we don't push the amd-dbgapi target / attach dbgapi in vfork
1572 children. If a vfork child execs, we'll try enabling the amd-dbgapi target
1573 through the inferior_execd observer. */
1574 if (inf->vfork_parent != nullptr)
1575 return;
1577 auto *info = get_amd_dbgapi_inferior_info (inf);
1579 /* Are we already attached? */
1580 if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
1582 amd_dbgapi_debug_printf
1583 ("already attached: process_id = %" PRIu64, info->process_id.handle);
1584 return;
1587 amd_dbgapi_status_t status
1588 = amd_dbgapi_process_attach
1589 (reinterpret_cast<amd_dbgapi_client_process_id_t> (inf),
1590 &info->process_id);
1591 if (status == AMD_DBGAPI_STATUS_ERROR_RESTRICTION)
1593 warning (_("amd-dbgapi: unable to enable GPU debugging due to a "
1594 "restriction error"));
1595 return;
1597 else if (status != AMD_DBGAPI_STATUS_SUCCESS)
1599 warning (_("amd-dbgapi: could not attach to process %d (%s), GPU "
1600 "debugging will not be available."), inf->pid,
1601 get_status_string (status));
1602 return;
1605 if (amd_dbgapi_process_get_info (info->process_id,
1606 AMD_DBGAPI_PROCESS_INFO_NOTIFIER,
1607 sizeof (info->notifier), &info->notifier)
1608 != AMD_DBGAPI_STATUS_SUCCESS)
1610 amd_dbgapi_process_detach (info->process_id);
1611 info->process_id = AMD_DBGAPI_PROCESS_NONE;
1612 warning (_("amd-dbgapi: could not retrieve process %d's notifier, GPU "
1613 "debugging will not be available."), inf->pid);
1614 return;
1617 amd_dbgapi_debug_printf ("process_id = %" PRIu64 ", notifier fd = %d",
1618 info->process_id.handle, info->notifier);
1620 set_process_memory_precision (*info);
1622 /* If GDB is attaching to a process that has the runtime loaded, there will
1623 already be a "runtime loaded" event available. Consume it and push the
1624 target. */
1625 dbgapi_notifier_handler (0, info);
1627 add_file_handler (info->notifier, dbgapi_notifier_handler, info,
1628 "amd-dbgapi notifier");
1631 static void maybe_reset_amd_dbgapi ();
1633 /* Make the amd-dbgapi library detach from INF.
1635 Note that this us unrelated to the "detach" GDB concept / command.
1637 This undoes what attach_amd_dbgapi does. */
1639 static void
1640 detach_amd_dbgapi (inferior *inf)
1642 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num);
1644 auto *info = get_amd_dbgapi_inferior_info (inf);
1646 if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
1647 return;
1649 info->runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED;
1651 amd_dbgapi_status_t status = amd_dbgapi_process_detach (info->process_id);
1652 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1653 warning (_("amd-dbgapi: could not detach from process %d (%s)"),
1654 inf->pid, get_status_string (status));
1656 gdb_assert (info->notifier != -1);
1657 delete_file_handler (info->notifier);
1659 /* This is a noop if the target is not pushed. */
1660 inf->unpush_target (&the_amd_dbgapi_target);
1662 /* Delete the breakpoints that are still active. */
1663 for (auto &&value : info->breakpoint_map)
1664 delete_breakpoint (value.second);
1666 /* Reset the amd_dbgapi_inferior_info, except for precise_memory_mode. */
1667 *info = amd_dbgapi_inferior_info (inf, info->precise_memory.requested);
1669 maybe_reset_amd_dbgapi ();
1672 void
1673 amd_dbgapi_target::mourn_inferior ()
1675 detach_amd_dbgapi (current_inferior ());
1676 beneath ()->mourn_inferior ();
1679 void
1680 amd_dbgapi_target::detach (inferior *inf, int from_tty)
1682 /* We're about to resume the waves by detaching the dbgapi library from the
1683 inferior, so we need to remove all breakpoints that are still inserted.
1685 Breakpoints may still be inserted because the inferior may be running in
1686 non-stop mode, or because GDB changed the default setting to leave all
1687 breakpoints inserted in all-stop mode when all threads are stopped. */
1688 remove_breakpoints_inf (inf);
1690 detach_amd_dbgapi (inf);
1691 beneath ()->detach (inf, from_tty);
1694 void
1695 amd_dbgapi_target::fetch_registers (struct regcache *regcache, int regno)
1697 if (!ptid_is_gpu (regcache->ptid ()))
1699 beneath ()->fetch_registers (regcache, regno);
1700 return;
1703 struct gdbarch *gdbarch = regcache->arch ();
1704 gdb_assert (is_amdgpu_arch (gdbarch));
1706 amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch);
1707 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
1708 gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
1709 amd_dbgapi_status_t status
1710 = amd_dbgapi_read_register (wave_id, tdep->register_ids[regno], 0,
1711 register_type (gdbarch, regno)->length (),
1712 raw);
1714 if (status == AMD_DBGAPI_STATUS_SUCCESS)
1715 regcache->raw_supply (regno, raw);
1716 else if (status != AMD_DBGAPI_STATUS_ERROR_REGISTER_NOT_AVAILABLE)
1717 warning (_("Couldn't read register %s (#%d) (%s)."),
1718 gdbarch_register_name (gdbarch, regno), regno,
1719 get_status_string (status));
1722 void
1723 amd_dbgapi_target::store_registers (struct regcache *regcache, int regno)
1725 if (!ptid_is_gpu (regcache->ptid ()))
1727 beneath ()->store_registers (regcache, regno);
1728 return;
1731 struct gdbarch *gdbarch = regcache->arch ();
1732 gdb_assert (is_amdgpu_arch (gdbarch));
1734 gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE];
1735 regcache->raw_collect (regno, &raw);
1737 amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch);
1739 /* If the register has read-only bits, invalidate the value in the regcache
1740 as the value actually written may differ. */
1741 if (tdep->register_properties[regno]
1742 & AMD_DBGAPI_REGISTER_PROPERTY_READONLY_BITS)
1743 regcache->invalidate (regno);
1745 /* Invalidate all volatile registers if this register has the invalidate
1746 volatile property. For example, writing to VCC may change the content
1747 of STATUS.VCCZ. */
1748 if (tdep->register_properties[regno]
1749 & AMD_DBGAPI_REGISTER_PROPERTY_INVALIDATE_VOLATILE)
1751 for (size_t r = 0; r < tdep->register_properties.size (); ++r)
1752 if (tdep->register_properties[r] & AMD_DBGAPI_REGISTER_PROPERTY_VOLATILE)
1753 regcache->invalidate (r);
1756 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
1757 amd_dbgapi_status_t status
1758 = amd_dbgapi_write_register (wave_id, tdep->register_ids[regno], 0,
1759 register_type (gdbarch, regno)->length (),
1760 raw);
1762 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1763 warning (_("Couldn't write register %s (#%d)."),
1764 gdbarch_register_name (gdbarch, regno), regno);
1767 struct gdbarch *
1768 amd_dbgapi_target::thread_architecture (ptid_t ptid)
1770 if (!ptid_is_gpu (ptid))
1771 return beneath ()->thread_architecture (ptid);
1773 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
1774 wave IDs are unique, and aren't reused. */
1775 if (ptid.tid () == m_cached_arch_tid)
1776 return m_cached_arch;
1778 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (ptid);
1779 amd_dbgapi_architecture_id_t architecture_id;
1780 amd_dbgapi_status_t status;
1782 status = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_ARCHITECTURE,
1783 sizeof (architecture_id),
1784 &architecture_id);
1785 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1786 error (_("Couldn't get architecture for wave_%ld"), ptid.tid ());
1788 uint32_t elf_amdgpu_machine;
1789 status = amd_dbgapi_architecture_get_info
1790 (architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE,
1791 sizeof (elf_amdgpu_machine), &elf_amdgpu_machine);
1792 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1793 error (_("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1794 architecture_id.handle);
1796 struct gdbarch_info info;
1797 info.bfd_arch_info = bfd_lookup_arch (bfd_arch_amdgcn, elf_amdgpu_machine);
1798 info.byte_order = BFD_ENDIAN_LITTLE;
1800 m_cached_arch_tid = ptid.tid ();
1801 m_cached_arch = gdbarch_find_by_info (info);
1802 if (m_cached_arch == nullptr)
1803 error (_("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine);
1805 return m_cached_arch;
1808 void
1809 amd_dbgapi_target::thread_events (int enable)
1811 m_report_thread_events = enable;
1812 beneath ()->thread_events (enable);
1815 void
1816 amd_dbgapi_target::update_thread_list ()
1818 for (inferior *inf : all_inferiors ())
1820 amd_dbgapi_process_id_t process_id
1821 = get_amd_dbgapi_process_id (inf);
1822 if (process_id == AMD_DBGAPI_PROCESS_NONE)
1824 /* The inferior may not be attached yet. */
1825 continue;
1828 size_t count;
1829 amd_dbgapi_wave_id_t *wave_list;
1830 amd_dbgapi_changed_t changed;
1831 amd_dbgapi_status_t status
1832 = amd_dbgapi_process_wave_list (process_id, &count, &wave_list,
1833 &changed);
1834 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1835 error (_("amd_dbgapi_wave_list failed (%s)"),
1836 get_status_string (status));
1838 if (changed == AMD_DBGAPI_CHANGED_NO)
1839 continue;
1841 /* Create a set and free the wave list. */
1842 std::set<ptid_t::tid_type> threads;
1843 for (size_t i = 0; i < count; ++i)
1844 threads.emplace (wave_list[i].handle);
1846 xfree (wave_list);
1848 /* Prune the wave_ids that already have a thread_info. Any thread_info
1849 which does not have a corresponding wave_id represents a wave which
1850 is gone at this point and should be deleted. */
1851 for (thread_info *tp : inf->threads_safe ())
1852 if (ptid_is_gpu (tp->ptid) && tp->state != THREAD_EXITED)
1854 auto it = threads.find (tp->ptid.tid ());
1856 if (it == threads.end ())
1858 auto wave_id = get_amd_dbgapi_wave_id (tp->ptid);
1859 wave_info &wi = get_thread_wave_info (tp);
1861 /* Waves that were stepping or in progress of being
1862 stopped are guaranteed to report a
1863 WAVE_COMMAND_TERMINATED event if they terminate.
1864 Don't delete such threads until we see the
1865 event. */
1866 if (wi.last_resume_mode == AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
1867 || wi.stopping)
1869 amd_dbgapi_debug_printf
1870 ("wave_%ld disappeared, keeping it"
1871 " (last_resume_mode=%s, stopping=%d)",
1872 wave_id.handle,
1873 resume_mode_to_string (wi.last_resume_mode),
1874 wi.stopping);
1876 else
1878 amd_dbgapi_debug_printf ("wave_%ld disappeared, deleting it",
1879 wave_id.handle);
1880 delete_thread_silent (tp);
1883 else
1884 threads.erase (it);
1887 /* The wave_ids that are left require a new thread_info. */
1888 for (ptid_t::tid_type tid : threads)
1890 ptid_t wave_ptid
1891 = make_gpu_ptid (inf->pid, amd_dbgapi_wave_id_t {tid});
1892 add_gpu_thread (inf, wave_ptid);
1896 /* Give the beneath target a chance to do extra processing. */
1897 this->beneath ()->update_thread_list ();
1900 /* inferior_created observer. */
1902 static void
1903 amd_dbgapi_target_inferior_created (inferior *inf)
1905 /* If the inferior is not running on the native target (e.g. it is running
1906 on a remote target), we don't want to deal with it. */
1907 if (inf->process_target () != get_native_target ())
1908 return;
1910 attach_amd_dbgapi (inf);
1913 /* Callback called when an inferior is cloned. */
1915 static void
1916 amd_dbgapi_target_inferior_cloned (inferior *original_inferior,
1917 inferior *new_inferior)
1919 auto *orig_info = get_amd_dbgapi_inferior_info (original_inferior);
1920 auto *new_info = get_amd_dbgapi_inferior_info (new_inferior);
1922 /* At this point, the process is not started. Therefore it is sufficient to
1923 copy the precise memory request, it will be applied when the process
1924 starts. */
1925 gdb_assert (new_info->process_id == AMD_DBGAPI_PROCESS_NONE);
1926 new_info->precise_memory.requested = orig_info->precise_memory.requested;
1929 /* inferior_execd observer. */
1931 static void
1932 amd_dbgapi_inferior_execd (inferior *exec_inf, inferior *follow_inf)
1934 /* The inferior has EXEC'd and the process image has changed. The dbgapi is
1935 attached to the old process image, so we need to detach and re-attach to
1936 the new process image. */
1937 detach_amd_dbgapi (exec_inf);
1939 /* If using "follow-exec-mode new", carry over the precise-memory setting
1940 to the new inferior (otherwise, FOLLOW_INF and ORIG_INF point to the same
1941 inferior, so this is a no-op). */
1942 get_amd_dbgapi_inferior_info (follow_inf)->precise_memory.requested
1943 = get_amd_dbgapi_inferior_info (exec_inf)->precise_memory.requested;
1945 attach_amd_dbgapi (follow_inf);
1948 /* inferior_forked observer. */
1950 static void
1951 amd_dbgapi_inferior_forked (inferior *parent_inf, inferior *child_inf,
1952 target_waitkind fork_kind)
1954 if (child_inf != nullptr)
1956 /* Copy precise-memory requested value from parent to child. */
1957 amd_dbgapi_inferior_info *parent_info
1958 = get_amd_dbgapi_inferior_info (parent_inf);
1959 amd_dbgapi_inferior_info *child_info
1960 = get_amd_dbgapi_inferior_info (child_inf);
1961 child_info->precise_memory.requested
1962 = parent_info->precise_memory.requested;
1964 if (fork_kind != TARGET_WAITKIND_VFORKED)
1966 scoped_restore_current_thread restore_thread;
1967 switch_to_thread (*child_inf->threads ().begin ());
1968 attach_amd_dbgapi (child_inf);
1973 /* inferior_exit observer.
1975 This covers normal exits, but also detached inferiors (including detached
1976 fork parents). */
1978 static void
1979 amd_dbgapi_inferior_exited (inferior *inf)
1981 detach_amd_dbgapi (inf);
1984 /* inferior_pre_detach observer. */
1986 static void
1987 amd_dbgapi_inferior_pre_detach (inferior *inf)
1989 /* We need to amd-dbgapi-detach before we ptrace-detach. If the amd-dbgapi
1990 target isn't pushed, do that now. If the amd-dbgapi target is pushed,
1991 we'll do it in amd_dbgapi_target::detach. */
1992 if (!inf->target_is_pushed (&the_amd_dbgapi_target))
1993 detach_amd_dbgapi (inf);
1996 /* get_os_pid callback. */
1998 static amd_dbgapi_status_t
1999 amd_dbgapi_get_os_pid_callback
2000 (amd_dbgapi_client_process_id_t client_process_id, pid_t *pid)
2002 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
2004 if (inf->pid == 0)
2005 return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
2007 *pid = inf->pid;
2008 return AMD_DBGAPI_STATUS_SUCCESS;
2011 /* insert_breakpoint callback. */
2013 static amd_dbgapi_status_t
2014 amd_dbgapi_insert_breakpoint_callback
2015 (amd_dbgapi_client_process_id_t client_process_id,
2016 amd_dbgapi_global_address_t address,
2017 amd_dbgapi_breakpoint_id_t breakpoint_id)
2019 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
2020 struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
2022 auto it = info->breakpoint_map.find (breakpoint_id.handle);
2023 if (it != info->breakpoint_map.end ())
2024 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
2026 /* We need to find the address in the given inferior's program space. */
2027 scoped_restore_current_thread restore_thread;
2028 switch_to_inferior_no_thread (inf);
2030 /* Create a new breakpoint. */
2031 struct obj_section *section = find_pc_section (address);
2032 if (section == nullptr || section->objfile == nullptr)
2033 return AMD_DBGAPI_STATUS_ERROR;
2035 std::unique_ptr<breakpoint> bp_up
2036 (new amd_dbgapi_target_breakpoint (section->objfile->arch (), address));
2038 breakpoint *bp = install_breakpoint (true, std::move (bp_up), 1);
2040 info->breakpoint_map.emplace (breakpoint_id.handle, bp);
2041 return AMD_DBGAPI_STATUS_SUCCESS;
2044 /* remove_breakpoint callback. */
2046 static amd_dbgapi_status_t
2047 amd_dbgapi_remove_breakpoint_callback
2048 (amd_dbgapi_client_process_id_t client_process_id,
2049 amd_dbgapi_breakpoint_id_t breakpoint_id)
2051 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
2052 struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
2054 auto it = info->breakpoint_map.find (breakpoint_id.handle);
2055 if (it == info->breakpoint_map.end ())
2056 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
2058 delete_breakpoint (it->second);
2059 info->breakpoint_map.erase (it);
2061 return AMD_DBGAPI_STATUS_SUCCESS;
2064 /* signal_received observer. */
2066 static void
2067 amd_dbgapi_target_signal_received (gdb_signal sig)
2069 amd_dbgapi_inferior_info *info
2070 = get_amd_dbgapi_inferior_info (current_inferior ());
2072 if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
2073 return;
2075 if (!ptid_is_gpu (inferior_thread ()->ptid))
2076 return;
2078 if (sig != GDB_SIGNAL_SEGV && sig != GDB_SIGNAL_BUS)
2079 return;
2081 if (!info->precise_memory.enabled)
2082 gdb_printf (_("\
2083 Warning: precise memory violation signal reporting is not enabled, reported\n\
2084 location may not be accurate. See \"show amdgpu precise-memory\".\n"));
2087 /* Style for some kinds of messages. */
2089 static cli_style_option fatal_error_style
2090 ("amd_dbgapi_fatal_error", ui_file_style::RED);
2091 static cli_style_option warning_style
2092 ("amd_dbgapi_warning", ui_file_style::YELLOW);
2094 /* BLACK + BOLD means dark gray. */
2095 static cli_style_option trace_style
2096 ("amd_dbgapi_trace", ui_file_style::BLACK, ui_file_style::BOLD);
2098 /* log_message callback. */
2100 static void
2101 amd_dbgapi_log_message_callback (amd_dbgapi_log_level_t level,
2102 const char *message)
2104 std::optional<target_terminal::scoped_restore_terminal_state> tstate;
2106 if (target_supports_terminal_ours ())
2108 tstate.emplace ();
2109 target_terminal::ours_for_output ();
2112 /* Error and warning messages are meant to be printed to the user. */
2113 if (level == AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
2114 || level == AMD_DBGAPI_LOG_LEVEL_WARNING)
2116 begin_line ();
2117 ui_file_style style = (level == AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
2118 ? fatal_error_style : warning_style).style ();
2119 gdb_printf (gdb_stderr, "%ps\n", styled_string (style, message));
2120 return;
2123 /* Print other messages as debug logs. TRACE and VERBOSE messages are
2124 very verbose, print them dark grey so it's easier to spot other messages
2125 through the flood. */
2126 if (level >= AMD_DBGAPI_LOG_LEVEL_TRACE)
2128 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%ps",
2129 styled_string (trace_style.style (), message));
2130 return;
2133 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%s",
2134 message);
2137 /* Callbacks passed to amd_dbgapi_initialize. */
2139 static amd_dbgapi_callbacks_t dbgapi_callbacks = {
2140 .allocate_memory = malloc,
2141 .deallocate_memory = free,
2142 .get_os_pid = amd_dbgapi_get_os_pid_callback,
2143 .insert_breakpoint = amd_dbgapi_insert_breakpoint_callback,
2144 .remove_breakpoint = amd_dbgapi_remove_breakpoint_callback,
2145 .log_message = amd_dbgapi_log_message_callback,
2148 void
2149 amd_dbgapi_target::close ()
2151 if (amd_dbgapi_async_event_handler != nullptr)
2152 delete_async_event_handler (&amd_dbgapi_async_event_handler);
2155 /* Callback for "show amdgpu precise-memory". */
2157 static void
2158 show_precise_memory_mode (struct ui_file *file, int from_tty,
2159 struct cmd_list_element *c, const char *value)
2161 amd_dbgapi_inferior_info *info
2162 = get_amd_dbgapi_inferior_info (current_inferior ());
2164 gdb_printf (file,
2165 _("AMDGPU precise memory access reporting is %s "
2166 "(currently %s).\n"),
2167 info->precise_memory.requested ? "on" : "off",
2168 info->precise_memory.enabled ? "enabled" : "disabled");
2171 /* Callback for "set amdgpu precise-memory". */
2173 static void
2174 set_precise_memory_mode (bool value)
2176 amd_dbgapi_inferior_info *info
2177 = get_amd_dbgapi_inferior_info (current_inferior ());
2179 info->precise_memory.requested = value;
2181 if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
2182 set_process_memory_precision (*info);
2185 /* Return whether precise-memory is requested for the current inferior. */
2187 static bool
2188 get_precise_memory_mode ()
2190 amd_dbgapi_inferior_info *info
2191 = get_amd_dbgapi_inferior_info (current_inferior ());
2193 return info->precise_memory.requested;
2196 /* List of set/show amdgpu commands. */
2197 struct cmd_list_element *set_amdgpu_list;
2198 struct cmd_list_element *show_amdgpu_list;
2200 /* List of set/show debug amd-dbgapi-lib commands. */
2201 struct cmd_list_element *set_debug_amd_dbgapi_lib_list;
2202 struct cmd_list_element *show_debug_amd_dbgapi_lib_list;
2204 /* Mapping from amd-dbgapi log level enum values to text. */
2206 static constexpr const char *debug_amd_dbgapi_lib_log_level_enums[] =
2208 /* [AMD_DBGAPI_LOG_LEVEL_NONE] = */ "off",
2209 /* [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR] = */ "error",
2210 /* [AMD_DBGAPI_LOG_LEVEL_WARNING] = */ "warning",
2211 /* [AMD_DBGAPI_LOG_LEVEL_INFO] = */ "info",
2212 /* [AMD_DBGAPI_LOG_LEVEL_TRACE] = */ "trace",
2213 /* [AMD_DBGAPI_LOG_LEVEL_VERBOSE] = */ "verbose",
2214 nullptr
2217 /* Storage for "set debug amd-dbgapi-lib log-level". */
2219 static const char *debug_amd_dbgapi_lib_log_level
2220 = debug_amd_dbgapi_lib_log_level_enums[AMD_DBGAPI_LOG_LEVEL_WARNING];
2222 /* Get the amd-dbgapi library log level requested by the user. */
2224 static amd_dbgapi_log_level_t
2225 get_debug_amd_dbgapi_lib_log_level ()
2227 for (size_t pos = 0;
2228 debug_amd_dbgapi_lib_log_level_enums[pos] != nullptr;
2229 ++pos)
2230 if (debug_amd_dbgapi_lib_log_level
2231 == debug_amd_dbgapi_lib_log_level_enums[pos])
2232 return static_cast<amd_dbgapi_log_level_t> (pos);
2234 gdb_assert_not_reached ("invalid log level");
2237 /* Callback for "set debug amd-dbgapi log-level", apply the selected log level
2238 to the library. */
2240 static void
2241 set_debug_amd_dbgapi_lib_log_level (const char *args, int from_tty,
2242 struct cmd_list_element *c)
2244 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ());
2247 /* Callback for "show debug amd-dbgapi log-level". */
2249 static void
2250 show_debug_amd_dbgapi_lib_log_level (struct ui_file *file, int from_tty,
2251 struct cmd_list_element *c,
2252 const char *value)
2254 gdb_printf (file, _("The amd-dbgapi library log level is %s.\n"), value);
2257 /* If the amd-dbgapi library is not attached to any process, finalize and
2258 re-initialize it so that the handle ID numbers will all start from the
2259 beginning again. This is only for convenience, not essential. */
2261 static void
2262 maybe_reset_amd_dbgapi ()
2264 for (inferior *inf : all_non_exited_inferiors ())
2266 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
2268 if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
2269 return;
2272 amd_dbgapi_status_t status = amd_dbgapi_finalize ();
2273 if (status != AMD_DBGAPI_STATUS_SUCCESS)
2274 error (_("amd-dbgapi failed to finalize (%s)"),
2275 get_status_string (status));
2277 status = amd_dbgapi_initialize (&dbgapi_callbacks);
2278 if (status != AMD_DBGAPI_STATUS_SUCCESS)
2279 error (_("amd-dbgapi failed to initialize (%s)"),
2280 get_status_string (status));
2283 extern initialize_file_ftype _initialize_amd_dbgapi_target;
2285 void
2286 _initialize_amd_dbgapi_target ()
2288 /* Make sure the loaded debugger library version is greater than or equal to
2289 the one used to build GDB. */
2290 uint32_t major, minor, patch;
2291 amd_dbgapi_get_version (&major, &minor, &patch);
2292 if (major != AMD_DBGAPI_VERSION_MAJOR || minor < AMD_DBGAPI_VERSION_MINOR)
2293 error (_("amd-dbgapi library version mismatch, got %d.%d.%d, need %d.%d+"),
2294 major, minor, patch, AMD_DBGAPI_VERSION_MAJOR,
2295 AMD_DBGAPI_VERSION_MINOR);
2297 /* Initialize the AMD Debugger API. */
2298 amd_dbgapi_status_t status = amd_dbgapi_initialize (&dbgapi_callbacks);
2299 if (status != AMD_DBGAPI_STATUS_SUCCESS)
2300 error (_("amd-dbgapi failed to initialize (%s)"),
2301 get_status_string (status));
2303 /* Set the initial log level. */
2304 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ());
2306 /* Install observers. */
2307 gdb::observers::inferior_cloned.attach (amd_dbgapi_target_inferior_cloned,
2308 "amd-dbgapi");
2309 gdb::observers::signal_received.attach (amd_dbgapi_target_signal_received,
2310 "amd-dbgapi");
2311 gdb::observers::inferior_created.attach
2312 (amd_dbgapi_target_inferior_created,
2313 amd_dbgapi_target_inferior_created_observer_token, "amd-dbgapi");
2314 gdb::observers::inferior_execd.attach (amd_dbgapi_inferior_execd, "amd-dbgapi");
2315 gdb::observers::inferior_forked.attach (amd_dbgapi_inferior_forked, "amd-dbgapi");
2316 gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi");
2317 gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi");
2318 gdb::observers::thread_deleted.attach (amd_dbgapi_thread_deleted, "amd-dbgapi");
2320 add_basic_prefix_cmd ("amdgpu", no_class,
2321 _("Generic command for setting amdgpu flags."),
2322 &set_amdgpu_list, 0, &setlist);
2324 add_show_prefix_cmd ("amdgpu", no_class,
2325 _("Generic command for showing amdgpu flags."),
2326 &show_amdgpu_list, 0, &showlist);
2328 add_setshow_boolean_cmd ("precise-memory", no_class,
2329 _("Set precise-memory mode."),
2330 _("Show precise-memory mode."), _("\
2331 If on, precise memory reporting is enabled if/when the inferior is running.\n\
2332 If off (default), precise memory reporting is disabled."),
2333 set_precise_memory_mode,
2334 get_precise_memory_mode,
2335 show_precise_memory_mode,
2336 &set_amdgpu_list, &show_amdgpu_list);
2338 add_basic_prefix_cmd ("amd-dbgapi-lib", no_class,
2339 _("Generic command for setting amd-dbgapi library "
2340 "debugging flags."),
2341 &set_debug_amd_dbgapi_lib_list, 0, &setdebuglist);
2343 add_show_prefix_cmd ("amd-dbgapi-lib", no_class,
2344 _("Generic command for showing amd-dbgapi library "
2345 "debugging flags."),
2346 &show_debug_amd_dbgapi_lib_list, 0, &showdebuglist);
2348 add_setshow_enum_cmd ("log-level", class_maintenance,
2349 debug_amd_dbgapi_lib_log_level_enums,
2350 &debug_amd_dbgapi_lib_log_level,
2351 _("Set the amd-dbgapi library log level."),
2352 _("Show the amd-dbgapi library log level."),
2353 _("off == no logging is enabled\n"
2354 "error == fatal errors are reported\n"
2355 "warning == fatal errors and warnings are reported\n"
2356 "info == fatal errors, warnings, and info "
2357 "messages are reported\n"
2358 "trace == fatal errors, warnings, info, and "
2359 "API tracing messages are reported\n"
2360 "verbose == all messages are reported"),
2361 set_debug_amd_dbgapi_lib_log_level,
2362 show_debug_amd_dbgapi_lib_log_level,
2363 &set_debug_amd_dbgapi_lib_list,
2364 &show_debug_amd_dbgapi_lib_list);
2366 add_setshow_boolean_cmd ("amd-dbgapi", class_maintenance,
2367 &debug_amd_dbgapi,
2368 _("Set debugging of amd-dbgapi target."),
2369 _("Show debugging of amd-dbgapi target."),
2370 _("\
2371 When on, print debug messages relating to the amd-dbgapi target."),
2372 nullptr, nullptr,
2373 &setdebuglist, &showdebuglist);