1 /* Target used to communicate with the AMD Debugger API.
3 Copyright (C) 2019-2023 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/>. */
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"
31 #include "observable.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. */
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
));
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
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. */
70 amd_dbgapi_debug_module ()
72 if (gdb_stdlog
->can_emit_style_escape ())
73 return amd_dbgapi_debug_module_styled
.c_str ();
75 return amd_dbgapi_debug_module_unstyled
;
78 /* Same as the above, but for the amd-dbgapi-lib module name. */
81 amd_dbgapi_lib_debug_module ()
83 if (gdb_stdlog
->can_emit_style_escape ())
84 return amd_dbgapi_lib_debug_module_styled
.c_str ();
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 (), \
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 (), \
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
;
113 /* Big enough to hold the size of the largest register in bytes. */
114 #define AMDGPU_MAX_REGISTER_SIZE 256
116 /* amd-dbgapi-specific inferior data. */
118 struct amd_dbgapi_inferior_info
120 explicit amd_dbgapi_inferior_info (inferior
*inf
,
121 bool precise_memory_requested
= false)
124 precise_memory
.requested
= precise_memory_requested
;
127 /* Backlink to inferior. */
130 /* The amd_dbgapi_process_id for this inferior. */
131 amd_dbgapi_process_id_t process_id
= AMD_DBGAPI_PROCESS_NONE
;
133 /* The amd_dbgapi_notifier_t for this inferior. */
134 amd_dbgapi_notifier_t notifier
= -1;
136 /* The status of the inferior's runtime support. */
137 amd_dbgapi_runtime_state_t runtime_state
= AMD_DBGAPI_RUNTIME_STATE_UNLOADED
;
139 /* This value mirrors the current "forward progress needed" value for this
140 process in amd-dbgapi. It is used to avoid unnecessary calls to
141 amd_dbgapi_process_set_progress, to reduce the noise in the logs.
143 Initialized to true, since that's the default in amd-dbgapi too. */
144 bool forward_progress_required
= true;
148 /* Whether precise memory reporting is requested. */
151 /* Whether precise memory was requested and successfully enabled by
152 dbgapi (it may not be available for the current hardware, for
154 bool enabled
= false;
157 std::unordered_map
<decltype (amd_dbgapi_breakpoint_id_t::handle
),
161 /* List of pending events the amd-dbgapi target retrieved from the dbgapi. */
162 std::list
<std::pair
<ptid_t
, target_waitstatus
>> wave_events
;
165 static amd_dbgapi_event_id_t process_event_queue
166 (amd_dbgapi_process_id_t process_id
,
167 amd_dbgapi_event_kind_t until_event_kind
= AMD_DBGAPI_EVENT_KIND_NONE
);
169 static const target_info amd_dbgapi_target_info
= {
171 N_("AMD Debugger API"),
172 N_("GPU debugging using the AMD Debugger API")
175 static amd_dbgapi_log_level_t
get_debug_amd_dbgapi_lib_log_level ();
177 struct amd_dbgapi_target final
: public target_ops
180 info () const override
182 return amd_dbgapi_target_info
;
185 stratum () const override
190 void close () override
;
191 void mourn_inferior () override
;
192 void detach (inferior
*inf
, int from_tty
) override
;
194 void async (bool enable
) override
;
196 bool has_pending_events () override
;
197 ptid_t
wait (ptid_t
, struct target_waitstatus
*, target_wait_flags
) override
;
198 void resume (ptid_t
, int, enum gdb_signal
) override
;
199 void commit_resumed () override
;
200 void stop (ptid_t ptid
) override
;
202 void fetch_registers (struct regcache
*, int) override
;
203 void store_registers (struct regcache
*, int) override
;
205 void update_thread_list () override
;
207 struct gdbarch
*thread_architecture (ptid_t
) override
;
209 void thread_events (int enable
) override
;
211 std::string
pid_to_str (ptid_t ptid
) override
;
213 const char *thread_name (thread_info
*tp
) override
;
215 const char *extra_thread_info (thread_info
*tp
) override
;
217 bool thread_alive (ptid_t ptid
) override
;
219 enum target_xfer_status
xfer_partial (enum target_object object
,
220 const char *annex
, gdb_byte
*readbuf
,
221 const gdb_byte
*writebuf
,
222 ULONGEST offset
, ULONGEST len
,
223 ULONGEST
*xfered_len
) override
;
225 bool stopped_by_watchpoint () override
;
227 bool stopped_by_sw_breakpoint () override
;
228 bool stopped_by_hw_breakpoint () override
;
231 /* True if we must report thread events. */
232 bool m_report_thread_events
= false;
234 /* Cache for the last value returned by thread_architecture. */
235 gdbarch
*m_cached_arch
= nullptr;
236 ptid_t::tid_type m_cached_arch_tid
= 0;
239 static struct amd_dbgapi_target the_amd_dbgapi_target
;
241 /* Per-inferior data key. */
243 static const registry
<inferior
>::key
<amd_dbgapi_inferior_info
>
244 amd_dbgapi_inferior_data
;
246 /* The async event handler registered with the event loop, indicating that we
247 might have events to report to the core and that we'd like our wait method
250 This is nullptr when async is disabled and non-nullptr when async is
253 It is marked when a notifier fd tells us there's an event available. The
254 callback triggers handle_inferior_event in order to pull the event from
255 amd-dbgapi and handle it. */
257 static async_event_handler
*amd_dbgapi_async_event_handler
= nullptr;
259 /* Return the target id string for a given wave. */
262 wave_target_id_string (amd_dbgapi_wave_id_t wave_id
)
264 amd_dbgapi_dispatch_id_t dispatch_id
;
265 amd_dbgapi_queue_id_t queue_id
;
266 amd_dbgapi_agent_id_t agent_id
;
267 uint32_t group_ids
[3], wave_in_group
;
268 std::string str
= "AMDGPU Wave";
270 amd_dbgapi_status_t status
271 = amd_dbgapi_wave_get_info (wave_id
, AMD_DBGAPI_WAVE_INFO_AGENT
,
272 sizeof (agent_id
), &agent_id
);
273 str
+= (status
== AMD_DBGAPI_STATUS_SUCCESS
274 ? string_printf (" %ld", agent_id
.handle
)
277 status
= amd_dbgapi_wave_get_info (wave_id
, AMD_DBGAPI_WAVE_INFO_QUEUE
,
278 sizeof (queue_id
), &queue_id
);
279 str
+= (status
== AMD_DBGAPI_STATUS_SUCCESS
280 ? string_printf (":%ld", queue_id
.handle
)
283 status
= amd_dbgapi_wave_get_info (wave_id
, AMD_DBGAPI_WAVE_INFO_DISPATCH
,
284 sizeof (dispatch_id
), &dispatch_id
);
285 str
+= (status
== AMD_DBGAPI_STATUS_SUCCESS
286 ? string_printf (":%ld", dispatch_id
.handle
)
289 str
+= string_printf (":%ld", wave_id
.handle
);
291 status
= amd_dbgapi_wave_get_info (wave_id
,
292 AMD_DBGAPI_WAVE_INFO_WORKGROUP_COORD
,
293 sizeof (group_ids
), &group_ids
);
294 str
+= (status
== AMD_DBGAPI_STATUS_SUCCESS
295 ? string_printf (" (%d,%d,%d)", group_ids
[0], group_ids
[1],
299 status
= amd_dbgapi_wave_get_info
300 (wave_id
, AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORKGROUP
,
301 sizeof (wave_in_group
), &wave_in_group
);
302 str
+= (status
== AMD_DBGAPI_STATUS_SUCCESS
303 ? string_printf ("/%d", wave_in_group
)
309 /* Clear our async event handler. */
312 async_event_handler_clear ()
314 gdb_assert (amd_dbgapi_async_event_handler
!= nullptr);
315 clear_async_event_handler (amd_dbgapi_async_event_handler
);
318 /* Mark our async event handler. */
321 async_event_handler_mark ()
323 gdb_assert (amd_dbgapi_async_event_handler
!= nullptr);
324 mark_async_event_handler (amd_dbgapi_async_event_handler
);
327 /* Fetch the amd_dbgapi_inferior_info data for the given inferior. */
329 static struct amd_dbgapi_inferior_info
*
330 get_amd_dbgapi_inferior_info (struct inferior
*inferior
)
332 amd_dbgapi_inferior_info
*info
= amd_dbgapi_inferior_data
.get (inferior
);
335 info
= amd_dbgapi_inferior_data
.emplace (inferior
, inferior
);
340 /* Set forward progress requirement to REQUIRE for all processes of PROC_TARGET
344 require_forward_progress (ptid_t ptid
, process_stratum_target
*proc_target
,
347 for (inferior
*inf
: all_inferiors (proc_target
))
349 if (ptid
!= minus_one_ptid
&& inf
->pid
!= ptid
.pid ())
352 amd_dbgapi_inferior_info
*info
= get_amd_dbgapi_inferior_info (inf
);
354 if (info
->process_id
== AMD_DBGAPI_PROCESS_NONE
)
357 /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */
358 if (info
->forward_progress_required
== require
)
361 amd_dbgapi_status_t status
362 = amd_dbgapi_process_set_progress
363 (info
->process_id
, (require
364 ? AMD_DBGAPI_PROGRESS_NORMAL
365 : AMD_DBGAPI_PROGRESS_NO_FORWARD
));
366 gdb_assert (status
== AMD_DBGAPI_STATUS_SUCCESS
);
368 info
->forward_progress_required
= require
;
370 /* If ptid targets a single inferior and we have found it, no need to
372 if (ptid
!= minus_one_ptid
)
377 /* See amd-dbgapi-target.h. */
379 amd_dbgapi_process_id_t
380 get_amd_dbgapi_process_id (inferior
*inf
)
382 return get_amd_dbgapi_inferior_info (inf
)->process_id
;
385 /* A breakpoint dbgapi wants us to insert, to handle shared library
386 loading/unloading. */
388 struct amd_dbgapi_target_breakpoint
: public code_breakpoint
390 amd_dbgapi_target_breakpoint (struct gdbarch
*gdbarch
, CORE_ADDR address
)
391 : code_breakpoint (gdbarch
, bp_breakpoint
)
395 sal
.section
= find_pc_overlay (sal
.pc
);
396 sal
.pspace
= current_program_space
;
399 pspace
= current_program_space
;
400 disposition
= disp_donttouch
;
403 void re_set () override
;
404 void check_status (struct bpstat
*bs
) override
;
408 amd_dbgapi_target_breakpoint::re_set ()
414 amd_dbgapi_target_breakpoint::check_status (struct bpstat
*bs
)
416 struct inferior
*inf
= current_inferior ();
417 amd_dbgapi_inferior_info
*info
= get_amd_dbgapi_inferior_info (inf
);
418 amd_dbgapi_status_t status
;
421 bs
->print_it
= print_it_noop
;
423 /* Find the address the breakpoint is set at. */
424 auto match_breakpoint
425 = [bs
] (const decltype (info
->breakpoint_map
)::value_type
&value
)
426 { return value
.second
== bs
->breakpoint_at
; };
428 = std::find_if (info
->breakpoint_map
.begin (), info
->breakpoint_map
.end (),
431 if (it
== info
->breakpoint_map
.end ())
432 error (_("Could not find breakpoint_id for breakpoint at %s"),
433 paddress (inf
->arch (), bs
->bp_location_at
->address
));
435 amd_dbgapi_breakpoint_id_t breakpoint_id
{ it
->first
};
436 amd_dbgapi_breakpoint_action_t action
;
438 status
= amd_dbgapi_report_breakpoint_hit
440 reinterpret_cast<amd_dbgapi_client_thread_id_t
> (inferior_thread ()),
443 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
444 error (_("amd_dbgapi_report_breakpoint_hit failed for breakpoint %ld "
446 breakpoint_id
.handle
, paddress (inf
->arch (), bs
->bp_location_at
->address
),
447 get_status_string (status
));
449 if (action
== AMD_DBGAPI_BREAKPOINT_ACTION_RESUME
)
452 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
453 a breakpoint resume event for this breakpoint_id is seen. */
454 amd_dbgapi_event_id_t resume_event_id
455 = process_event_queue (info
->process_id
,
456 AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
);
458 /* We should always get a breakpoint_resume event after processing all
459 events generated by reporting the breakpoint hit. */
460 gdb_assert (resume_event_id
!= AMD_DBGAPI_EVENT_NONE
);
462 amd_dbgapi_breakpoint_id_t resume_breakpoint_id
;
463 status
= amd_dbgapi_event_get_info (resume_event_id
,
464 AMD_DBGAPI_EVENT_INFO_BREAKPOINT
,
465 sizeof (resume_breakpoint_id
),
466 &resume_breakpoint_id
);
468 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
469 error (_("amd_dbgapi_event_get_info failed (%s)"), get_status_string (status
));
471 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint]
472 sequences cannot interleave, so this breakpoint resume event must be
473 for our breakpoint_id. */
474 if (resume_breakpoint_id
!= breakpoint_id
)
475 error (_("breakpoint resume event is not for this breakpoint. "
476 "Expected breakpoint_%ld, got breakpoint_%ld"),
477 breakpoint_id
.handle
, resume_breakpoint_id
.handle
);
479 amd_dbgapi_event_processed (resume_event_id
);
483 amd_dbgapi_target::thread_alive (ptid_t ptid
)
485 if (!ptid_is_gpu (ptid
))
486 return beneath ()->thread_alive (ptid
);
488 /* Check that the wave_id is valid. */
490 amd_dbgapi_wave_state_t state
;
491 amd_dbgapi_status_t status
492 = amd_dbgapi_wave_get_info (get_amd_dbgapi_wave_id (ptid
),
493 AMD_DBGAPI_WAVE_INFO_STATE
, sizeof (state
),
495 return status
== AMD_DBGAPI_STATUS_SUCCESS
;
499 amd_dbgapi_target::thread_name (thread_info
*tp
)
501 if (!ptid_is_gpu (tp
->ptid
))
502 return beneath ()->thread_name (tp
);
508 amd_dbgapi_target::pid_to_str (ptid_t ptid
)
510 if (!ptid_is_gpu (ptid
))
511 return beneath ()->pid_to_str (ptid
);
513 return wave_target_id_string (get_amd_dbgapi_wave_id (ptid
));
517 amd_dbgapi_target::extra_thread_info (thread_info
*tp
)
519 if (!ptid_is_gpu (tp
->ptid
))
520 beneath ()->extra_thread_info (tp
);
526 amd_dbgapi_target::xfer_partial (enum target_object object
, const char *annex
,
527 gdb_byte
*readbuf
, const gdb_byte
*writebuf
,
528 ULONGEST offset
, ULONGEST requested_len
,
529 ULONGEST
*xfered_len
)
531 std::optional
<scoped_restore_current_thread
> maybe_restore_thread
;
533 if (!ptid_is_gpu (inferior_ptid
))
534 return beneath ()->xfer_partial (object
, annex
, readbuf
, writebuf
, offset
,
535 requested_len
, xfered_len
);
537 gdb_assert (requested_len
> 0);
538 gdb_assert (xfered_len
!= nullptr);
540 if (object
!= TARGET_OBJECT_MEMORY
)
541 return TARGET_XFER_E_IO
;
543 amd_dbgapi_process_id_t process_id
544 = get_amd_dbgapi_process_id (current_inferior ());
545 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
547 size_t len
= requested_len
;
548 amd_dbgapi_status_t status
;
550 if (readbuf
!= nullptr)
551 status
= amd_dbgapi_read_memory (process_id
, wave_id
, 0,
552 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL
,
553 offset
, &len
, readbuf
);
555 status
= amd_dbgapi_write_memory (process_id
, wave_id
, 0,
556 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL
,
557 offset
, &len
, writebuf
);
559 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
560 return TARGET_XFER_E_IO
;
563 return TARGET_XFER_OK
;
567 amd_dbgapi_target::stopped_by_watchpoint ()
569 if (!ptid_is_gpu (inferior_ptid
))
570 return beneath ()->stopped_by_watchpoint ();
576 amd_dbgapi_target::resume (ptid_t scope_ptid
, int step
, enum gdb_signal signo
)
578 amd_dbgapi_debug_printf ("scope_ptid = %s", scope_ptid
.to_string ().c_str ());
580 /* The amd_dbgapi_exceptions_t matching SIGNO will only be used if the
581 thread which is the target of the signal SIGNO is a GPU thread. If so,
582 make sure that there is a corresponding amd_dbgapi_exceptions_t for SIGNO
583 before we try to resume any thread. */
584 amd_dbgapi_exceptions_t exception
= AMD_DBGAPI_EXCEPTION_NONE
;
585 if (ptid_is_gpu (inferior_ptid
))
590 exception
= AMD_DBGAPI_EXCEPTION_WAVE_APERTURE_VIOLATION
;
592 case GDB_SIGNAL_SEGV
:
593 exception
= AMD_DBGAPI_EXCEPTION_WAVE_MEMORY_VIOLATION
;
596 exception
= AMD_DBGAPI_EXCEPTION_WAVE_ILLEGAL_INSTRUCTION
;
599 exception
= AMD_DBGAPI_EXCEPTION_WAVE_MATH_ERROR
;
601 case GDB_SIGNAL_ABRT
:
602 exception
= AMD_DBGAPI_EXCEPTION_WAVE_ABORT
;
604 case GDB_SIGNAL_TRAP
:
605 exception
= AMD_DBGAPI_EXCEPTION_WAVE_TRAP
;
608 exception
= AMD_DBGAPI_EXCEPTION_NONE
;
611 error (_("Resuming with signal %s is not supported by this agent."),
612 gdb_signal_to_name (signo
));
616 if (!ptid_is_gpu (inferior_ptid
) || scope_ptid
!= inferior_ptid
)
618 beneath ()->resume (scope_ptid
, step
, signo
);
620 /* If the request is for a single thread, we are done. */
621 if (scope_ptid
== inferior_ptid
)
625 process_stratum_target
*proc_target
= current_inferior ()->process_target ();
627 /* Disable forward progress requirement. */
628 require_forward_progress (scope_ptid
, proc_target
, false);
630 for (thread_info
*thread
: all_non_exited_threads (proc_target
, scope_ptid
))
632 if (!ptid_is_gpu (thread
->ptid
))
635 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (thread
->ptid
);
636 amd_dbgapi_status_t status
;
637 if (thread
->ptid
== inferior_ptid
)
638 status
= amd_dbgapi_wave_resume (wave_id
,
640 ? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
641 : AMD_DBGAPI_RESUME_MODE_NORMAL
),
644 status
= amd_dbgapi_wave_resume (wave_id
, AMD_DBGAPI_RESUME_MODE_NORMAL
,
645 AMD_DBGAPI_EXCEPTION_NONE
);
647 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
648 /* Ignore the error that wave is no longer valid as that could
649 indicate that the process has exited. GDB treats resuming a
650 thread that no longer exists as being successful. */
651 && status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
652 error (_("wave_resume for wave_%ld failed (%s)"), wave_id
.handle
,
653 get_status_string (status
));
658 amd_dbgapi_target::commit_resumed ()
660 amd_dbgapi_debug_printf ("called");
662 beneath ()->commit_resumed ();
664 process_stratum_target
*proc_target
= current_inferior ()->process_target ();
665 require_forward_progress (minus_one_ptid
, proc_target
, true);
669 amd_dbgapi_target::stop (ptid_t ptid
)
671 amd_dbgapi_debug_printf ("ptid = %s", ptid
.to_string ().c_str ());
673 bool many_threads
= ptid
== minus_one_ptid
|| ptid
.is_pid ();
675 if (!ptid_is_gpu (ptid
) || many_threads
)
677 beneath ()->stop (ptid
);
679 /* The request is for a single thread, we are done. */
684 auto stop_one_thread
= [this] (thread_info
*thread
)
686 gdb_assert (thread
!= nullptr);
688 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (thread
->ptid
);
689 amd_dbgapi_wave_state_t state
;
690 amd_dbgapi_status_t status
691 = amd_dbgapi_wave_get_info (wave_id
, AMD_DBGAPI_WAVE_INFO_STATE
,
692 sizeof (state
), &state
);
693 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
695 /* If the wave is already known to be stopped then do nothing. */
696 if (state
== AMD_DBGAPI_WAVE_STATE_STOP
)
699 status
= amd_dbgapi_wave_stop (wave_id
);
700 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
703 if (status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
704 error (_("wave_stop for wave_%ld failed (%s)"), wave_id
.handle
,
705 get_status_string (status
));
707 else if (status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
708 error (_("wave_get_info for wave_%ld failed (%s)"), wave_id
.handle
,
709 get_status_string (status
));
711 /* The status is AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID. The wave
712 could have terminated since the last time the wave list was
715 if (m_report_thread_events
)
717 get_amd_dbgapi_inferior_info (thread
->inf
)->wave_events
.emplace_back
718 (thread
->ptid
, target_waitstatus ().set_thread_exited (0));
720 if (target_is_async_p ())
721 async_event_handler_mark ();
724 delete_thread_silent (thread
);
727 process_stratum_target
*proc_target
= current_inferior ()->process_target ();
729 /* Disable forward progress requirement. */
730 require_forward_progress (ptid
, proc_target
, false);
734 /* No need to iterate all non-exited threads if the request is to stop a
736 stop_one_thread (proc_target
->find_thread (ptid
));
740 for (auto *inf
: all_inferiors (proc_target
))
741 /* Use the threads_safe iterator since stop_one_thread may delete the
742 thread if it has exited. */
743 for (auto *thread
: inf
->threads_safe ())
744 if (thread
->state
!= THREAD_EXITED
&& thread
->ptid
.matches (ptid
)
745 && ptid_is_gpu (thread
->ptid
))
746 stop_one_thread (thread
);
749 /* Callback for our async event handler. */
752 handle_target_event (gdb_client_data client_data
)
754 inferior_event_handler (INF_REG_EVENT
);
757 struct scoped_amd_dbgapi_event_processed
759 scoped_amd_dbgapi_event_processed (amd_dbgapi_event_id_t event_id
)
760 : m_event_id (event_id
)
762 gdb_assert (event_id
!= AMD_DBGAPI_EVENT_NONE
);
765 ~scoped_amd_dbgapi_event_processed ()
767 amd_dbgapi_status_t status
= amd_dbgapi_event_processed (m_event_id
);
768 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
769 warning (_("Failed to acknowledge amd-dbgapi event %" PRIu64
),
773 DISABLE_COPY_AND_ASSIGN (scoped_amd_dbgapi_event_processed
);
776 amd_dbgapi_event_id_t m_event_id
;
779 /* Called when a dbgapi notifier fd is readable. CLIENT_DATA is the
780 amd_dbgapi_inferior_info object corresponding to the notifier. */
783 dbgapi_notifier_handler (int err
, gdb_client_data client_data
)
785 amd_dbgapi_inferior_info
*info
= (amd_dbgapi_inferior_info
*) client_data
;
788 /* Drain the notifier pipe. */
792 ret
= read (info
->notifier
, &buf
, 1);
794 while (ret
>= 0 || (ret
== -1 && errno
== EINTR
));
796 if (info
->inf
->target_is_pushed (&the_amd_dbgapi_target
))
798 /* The amd-dbgapi target is pushed: signal our async handler, the event
799 will be consumed through our wait method. */
801 async_event_handler_mark ();
805 /* The amd-dbgapi target is not pushed: if there's an event, the only
806 expected one is one of the RUNTIME kind. If the event tells us the
807 inferior as activated the ROCm runtime, push the amd-dbgapi
810 amd_dbgapi_event_id_t event_id
;
811 amd_dbgapi_event_kind_t event_kind
;
812 amd_dbgapi_status_t status
813 = amd_dbgapi_process_next_pending_event (info
->process_id
, &event_id
,
815 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
816 error (_("next_pending_event failed (%s)"), get_status_string (status
));
818 if (event_id
== AMD_DBGAPI_EVENT_NONE
)
821 gdb_assert (event_kind
== AMD_DBGAPI_EVENT_KIND_RUNTIME
);
823 scoped_amd_dbgapi_event_processed
mark_event_processed (event_id
);
825 amd_dbgapi_runtime_state_t runtime_state
;
826 status
= amd_dbgapi_event_get_info (event_id
,
827 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE
,
828 sizeof (runtime_state
),
830 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
831 error (_("event_get_info for event_%ld failed (%s)"),
832 event_id
.handle
, get_status_string (status
));
834 switch (runtime_state
)
836 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS
:
837 gdb_assert (info
->runtime_state
== AMD_DBGAPI_RUNTIME_STATE_UNLOADED
);
838 info
->runtime_state
= runtime_state
;
839 amd_dbgapi_debug_printf ("pushing amd-dbgapi target");
840 info
->inf
->push_target (&the_amd_dbgapi_target
);
842 /* The underlying target will already be async if we are running, but not if
844 if (info
->inf
->process_target ()->is_async_p ())
846 scoped_restore_current_thread restore_thread
;
847 switch_to_inferior_no_thread (info
->inf
);
849 /* Make sure our async event handler is created. */
854 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED
:
855 gdb_assert (info
->runtime_state
856 == AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION
);
857 info
->runtime_state
= runtime_state
;
860 case AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION
:
861 gdb_assert (info
->runtime_state
== AMD_DBGAPI_RUNTIME_STATE_UNLOADED
);
862 info
->runtime_state
= runtime_state
;
863 warning (_("amd-dbgapi: unable to enable GPU debugging "
864 "due to a restriction error"));
871 amd_dbgapi_target::async (bool enable
)
873 beneath ()->async (enable
);
877 if (amd_dbgapi_async_event_handler
!= nullptr)
879 /* Already enabled. */
883 /* The library gives us one notifier file descriptor per inferior (even
884 the ones that have not yet loaded their runtime). Register them
885 all with the event loop. */
886 process_stratum_target
*proc_target
887 = current_inferior ()->process_target ();
889 for (inferior
*inf
: all_non_exited_inferiors (proc_target
))
891 amd_dbgapi_inferior_info
*info
= get_amd_dbgapi_inferior_info (inf
);
893 if (info
->notifier
!= -1)
894 add_file_handler (info
->notifier
, dbgapi_notifier_handler
, info
,
895 string_printf ("amd-dbgapi notifier for pid %d",
899 amd_dbgapi_async_event_handler
900 = create_async_event_handler (handle_target_event
, nullptr,
903 /* There may be pending events to handle. Tell the event loop to poll
905 async_event_handler_mark ();
909 if (amd_dbgapi_async_event_handler
== nullptr)
912 for (inferior
*inf
: all_inferiors ())
914 amd_dbgapi_inferior_info
*info
= get_amd_dbgapi_inferior_info (inf
);
916 if (info
->notifier
!= -1)
917 delete_file_handler (info
->notifier
);
920 delete_async_event_handler (&amd_dbgapi_async_event_handler
);
924 /* Make a ptid for a GPU wave. See comment on ptid_is_gpu for more details. */
927 make_gpu_ptid (ptid_t::pid_type pid
, amd_dbgapi_wave_id_t wave_id
)
929 return ptid_t (pid
, 1, wave_id
.handle
);
932 /* Process an event that was just pulled out of the amd-dbgapi library. */
935 process_one_event (amd_dbgapi_event_id_t event_id
,
936 amd_dbgapi_event_kind_t event_kind
)
938 /* Automatically mark this event processed when going out of scope. */
939 scoped_amd_dbgapi_event_processed
mark_event_processed (event_id
);
941 amd_dbgapi_process_id_t process_id
;
942 amd_dbgapi_status_t status
943 = amd_dbgapi_event_get_info (event_id
, AMD_DBGAPI_EVENT_INFO_PROCESS
,
944 sizeof (process_id
), &process_id
);
945 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
946 error (_("event_get_info for event_%ld failed (%s)"), event_id
.handle
,
947 get_status_string (status
));
949 amd_dbgapi_os_process_id_t pid
;
950 status
= amd_dbgapi_process_get_info (process_id
,
951 AMD_DBGAPI_PROCESS_INFO_OS_ID
,
953 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
954 error (_("process_get_info for process_%ld failed (%s)"),
955 process_id
.handle
, get_status_string (status
));
957 auto *proc_target
= current_inferior ()->process_target ();
958 inferior
*inf
= find_inferior_pid (proc_target
, pid
);
959 gdb_assert (inf
!= nullptr);
960 amd_dbgapi_inferior_info
*info
= get_amd_dbgapi_inferior_info (inf
);
964 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED
:
965 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP
:
967 amd_dbgapi_wave_id_t wave_id
;
969 = amd_dbgapi_event_get_info (event_id
, AMD_DBGAPI_EVENT_INFO_WAVE
,
970 sizeof (wave_id
), &wave_id
);
971 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
972 error (_("event_get_info for event_%ld failed (%s)"),
973 event_id
.handle
, get_status_string (status
));
975 ptid_t event_ptid
= make_gpu_ptid (pid
, wave_id
);
976 target_waitstatus ws
;
978 amd_dbgapi_wave_stop_reasons_t stop_reason
;
979 status
= amd_dbgapi_wave_get_info (wave_id
,
980 AMD_DBGAPI_WAVE_INFO_STOP_REASON
,
981 sizeof (stop_reason
), &stop_reason
);
982 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
983 && event_kind
== AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED
)
984 ws
.set_thread_exited (0);
985 else if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
987 if (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_APERTURE_VIOLATION
)
988 ws
.set_stopped (GDB_SIGNAL_BUS
);
990 & AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION
)
991 ws
.set_stopped (GDB_SIGNAL_SEGV
);
993 & AMD_DBGAPI_WAVE_STOP_REASON_ILLEGAL_INSTRUCTION
)
994 ws
.set_stopped (GDB_SIGNAL_ILL
);
996 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
997 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
998 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
999 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
1000 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
1001 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
1002 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0
))
1003 ws
.set_stopped (GDB_SIGNAL_FPE
);
1004 else if (stop_reason
1005 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
1006 | AMD_DBGAPI_WAVE_STOP_REASON_WATCHPOINT
1007 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
1008 | AMD_DBGAPI_WAVE_STOP_REASON_DEBUG_TRAP
1009 | AMD_DBGAPI_WAVE_STOP_REASON_TRAP
))
1010 ws
.set_stopped (GDB_SIGNAL_TRAP
);
1011 else if (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_ASSERT_TRAP
)
1012 ws
.set_stopped (GDB_SIGNAL_ABRT
);
1014 ws
.set_stopped (GDB_SIGNAL_0
);
1016 thread_info
*thread
= proc_target
->find_thread (event_ptid
);
1017 if (thread
== nullptr)
1019 /* Silently create new GPU threads to avoid spamming the
1020 terminal with thousands of "[New Thread ...]" messages. */
1021 thread
= add_thread_silent (proc_target
, event_ptid
);
1022 set_running (proc_target
, event_ptid
, true);
1023 set_executing (proc_target
, event_ptid
, true);
1026 /* If the wave is stopped because of a software breakpoint, the
1027 program counter needs to be adjusted so that it points to the
1028 breakpoint instruction. */
1029 if ((stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
) != 0)
1031 regcache
*regcache
= get_thread_regcache (thread
);
1032 gdbarch
*gdbarch
= regcache
->arch ();
1034 CORE_ADDR pc
= regcache_read_pc (regcache
);
1035 CORE_ADDR adjusted_pc
1036 = pc
- gdbarch_decr_pc_after_break (gdbarch
);
1038 if (adjusted_pc
!= pc
)
1039 regcache_write_pc (regcache
, adjusted_pc
);
1043 error (_("wave_get_info for wave_%ld failed (%s)"),
1044 wave_id
.handle
, get_status_string (status
));
1046 info
->wave_events
.emplace_back (event_ptid
, ws
);
1050 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED
:
1051 /* We get here when the following sequence of events happens:
1053 - the inferior hits the amd-dbgapi "r_brk" internal breakpoint
1054 - amd_dbgapi_target_breakpoint::check_status calls
1055 amd_dbgapi_report_breakpoint_hit, which queues an event of this
1057 - amd_dbgapi_target_breakpoint::check_status calls
1058 process_event_queue, which pulls the event out of dbgapi, and
1061 When amd_dbgapi_target_breakpoint::check_status is called, the current
1062 inferior is the inferior that hit the breakpoint, which should still be
1064 gdb_assert (inf
== current_inferior ());
1065 handle_solib_event ();
1068 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
:
1069 /* Breakpoint resume events should be handled by the breakpoint
1070 action, and this code should not reach this. */
1071 gdb_assert_not_reached ("unhandled event kind");
1074 case AMD_DBGAPI_EVENT_KIND_RUNTIME
:
1076 amd_dbgapi_runtime_state_t runtime_state
;
1078 status
= amd_dbgapi_event_get_info (event_id
,
1079 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE
,
1080 sizeof (runtime_state
),
1082 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1083 error (_("event_get_info for event_%ld failed (%s)"),
1084 event_id
.handle
, get_status_string (status
));
1086 gdb_assert (runtime_state
== AMD_DBGAPI_RUNTIME_STATE_UNLOADED
);
1088 (info
->runtime_state
== AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS
);
1090 info
->runtime_state
= runtime_state
;
1092 gdb_assert (inf
->target_is_pushed (&the_amd_dbgapi_target
));
1093 inf
->unpush_target (&the_amd_dbgapi_target
);
1098 error (_("event kind (%d) not supported"), event_kind
);
1102 /* Return a textual version of KIND. */
1105 event_kind_str (amd_dbgapi_event_kind_t kind
)
1109 case AMD_DBGAPI_EVENT_KIND_NONE
:
1112 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP
:
1115 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED
:
1116 return "WAVE_COMMAND_TERMINATED";
1118 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED
:
1119 return "CODE_OBJECT_LIST_UPDATED";
1121 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
:
1122 return "BREAKPOINT_RESUME";
1124 case AMD_DBGAPI_EVENT_KIND_RUNTIME
:
1127 case AMD_DBGAPI_EVENT_KIND_QUEUE_ERROR
:
1128 return "QUEUE_ERROR";
1131 gdb_assert_not_reached ("unhandled amd_dbgapi_event_kind_t value");
1134 /* Drain the dbgapi event queue of a given process_id, or of all processes if
1135 process_id is AMD_DBGAPI_PROCESS_NONE. Stop processing the events if an
1136 event of a given kind is requested and `process_id` is not
1137 AMD_DBGAPI_PROCESS_NONE. Wave stop events that are not returned are queued
1138 into their inferior's amd_dbgapi_inferior_info pending wave events. */
1140 static amd_dbgapi_event_id_t
1141 process_event_queue (amd_dbgapi_process_id_t process_id
,
1142 amd_dbgapi_event_kind_t until_event_kind
)
1144 /* An event of a given type can only be requested from a single
1146 gdb_assert (until_event_kind
== AMD_DBGAPI_EVENT_KIND_NONE
1147 || process_id
!= AMD_DBGAPI_PROCESS_NONE
);
1151 amd_dbgapi_event_id_t event_id
;
1152 amd_dbgapi_event_kind_t event_kind
;
1154 amd_dbgapi_status_t status
1155 = amd_dbgapi_process_next_pending_event (process_id
, &event_id
,
1158 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1159 error (_("next_pending_event failed (%s)"), get_status_string (status
));
1161 if (event_kind
!= AMD_DBGAPI_EVENT_KIND_NONE
)
1162 amd_dbgapi_debug_printf ("Pulled event from dbgapi: "
1163 "event_id.handle = %" PRIu64
", "
1166 event_kind_str (event_kind
));
1168 if (event_id
== AMD_DBGAPI_EVENT_NONE
|| event_kind
== until_event_kind
)
1171 process_one_event (event_id
, event_kind
);
1176 amd_dbgapi_target::has_pending_events ()
1178 if (amd_dbgapi_async_event_handler
!= nullptr
1179 && async_event_handler_marked (amd_dbgapi_async_event_handler
))
1182 return beneath ()->has_pending_events ();
1185 /* Pop one pending event from the per-inferior structures.
1187 If PID is not -1, restrict the search to the inferior with that pid. */
1189 static std::pair
<ptid_t
, target_waitstatus
>
1190 consume_one_event (int pid
)
1192 auto *target
= current_inferior ()->process_target ();
1193 struct amd_dbgapi_inferior_info
*info
= nullptr;
1197 for (inferior
*inf
: all_inferiors (target
))
1199 info
= get_amd_dbgapi_inferior_info (inf
);
1200 if (!info
->wave_events
.empty ())
1204 gdb_assert (info
!= nullptr);
1208 inferior
*inf
= find_inferior_pid (target
, pid
);
1210 gdb_assert (inf
!= nullptr);
1211 info
= get_amd_dbgapi_inferior_info (inf
);
1214 if (info
->wave_events
.empty ())
1215 return { minus_one_ptid
, {} };
1217 auto event
= info
->wave_events
.front ();
1218 info
->wave_events
.pop_front ();
1224 amd_dbgapi_target::wait (ptid_t ptid
, struct target_waitstatus
*ws
,
1225 target_wait_flags target_options
)
1227 gdb_assert (!current_inferior ()->process_target ()->commit_resumed_state
);
1228 gdb_assert (ptid
== minus_one_ptid
|| ptid
.is_pid ());
1230 amd_dbgapi_debug_printf ("ptid = %s", ptid
.to_string ().c_str ());
1232 ptid_t event_ptid
= beneath ()->wait (ptid
, ws
, target_options
);
1233 if (event_ptid
!= minus_one_ptid
)
1235 if (ws
->kind () == TARGET_WAITKIND_EXITED
1236 || ws
->kind () == TARGET_WAITKIND_SIGNALLED
)
1238 /* This inferior has exited so drain its dbgapi event queue. */
1239 while (consume_one_event (event_ptid
.pid ()).first
1246 gdb_assert (ws
->kind () == TARGET_WAITKIND_NO_RESUMED
1247 || ws
->kind () == TARGET_WAITKIND_IGNORE
);
1249 /* Flush the async handler first. */
1250 if (target_is_async_p ())
1251 async_event_handler_clear ();
1253 /* There may be more events to process (either already in `wave_events` or
1254 that we need to fetch from dbgapi. Mark the async event handler so that
1255 amd_dbgapi_target::wait gets called again and again, until it eventually
1256 returns minus_one_ptid. */
1257 auto more_events
= make_scope_exit ([] ()
1259 if (target_is_async_p ())
1260 async_event_handler_mark ();
1263 auto *proc_target
= current_inferior ()->process_target ();
1265 /* Disable forward progress for the specified pid in ptid if it isn't
1266 minus_on_ptid, or all attached processes if ptid is minus_one_ptid. */
1267 require_forward_progress (ptid
, proc_target
, false);
1269 target_waitstatus gpu_waitstatus
;
1270 std::tie (event_ptid
, gpu_waitstatus
) = consume_one_event (ptid
.pid ());
1271 if (event_ptid
== minus_one_ptid
)
1273 /* Drain the events for the current inferior from the amd_dbgapi and
1274 preserve the ordering. */
1275 auto info
= get_amd_dbgapi_inferior_info (current_inferior ());
1276 process_event_queue (info
->process_id
, AMD_DBGAPI_EVENT_KIND_NONE
);
1278 std::tie (event_ptid
, gpu_waitstatus
) = consume_one_event (ptid
.pid ());
1279 if (event_ptid
== minus_one_ptid
)
1281 /* If we requested a specific ptid, and nothing came out, assume
1282 another ptid may have more events, otherwise, keep the
1283 async_event_handler flushed. */
1284 if (ptid
== minus_one_ptid
)
1285 more_events
.release ();
1287 if (ws
->kind () == TARGET_WAITKIND_NO_RESUMED
)
1289 /* We can't easily check that all GPU waves are stopped, and no
1290 new waves can be created (the GPU has fixed function hardware
1291 to create new threads), so even if the target beneath returns
1292 waitkind_no_resumed, we have to report waitkind_ignore if GPU
1293 debugging is enabled for at least one resumed inferior handled
1294 by the amd-dbgapi target. */
1296 for (inferior
*inf
: all_inferiors ())
1297 if (inf
->target_at (arch_stratum
) == &the_amd_dbgapi_target
1298 && get_amd_dbgapi_inferior_info (inf
)->runtime_state
1299 == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS
)
1306 /* There are no events to report, return the target beneath's
1307 waitstatus (either IGNORE or NO_RESUMED). */
1308 return minus_one_ptid
;
1312 *ws
= gpu_waitstatus
;
1317 amd_dbgapi_target::stopped_by_sw_breakpoint ()
1319 if (!ptid_is_gpu (inferior_ptid
))
1320 return beneath ()->stopped_by_sw_breakpoint ();
1322 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
1324 amd_dbgapi_wave_stop_reasons_t stop_reason
;
1325 amd_dbgapi_status_t status
1326 = amd_dbgapi_wave_get_info (wave_id
, AMD_DBGAPI_WAVE_INFO_STOP_REASON
,
1327 sizeof (stop_reason
), &stop_reason
);
1329 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1332 return (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
) != 0;
1336 amd_dbgapi_target::stopped_by_hw_breakpoint ()
1338 if (!ptid_is_gpu (inferior_ptid
))
1339 return beneath ()->stopped_by_hw_breakpoint ();
1344 /* Set the process' memory access reporting precision mode.
1346 Warn if the requested mode is not supported on at least one agent in the
1349 Error out if setting the requested mode failed for some other reason. */
1352 set_process_memory_precision (amd_dbgapi_inferior_info
&info
)
1354 auto mode
= (info
.precise_memory
.requested
1355 ? AMD_DBGAPI_MEMORY_PRECISION_PRECISE
1356 : AMD_DBGAPI_MEMORY_PRECISION_NONE
);
1357 amd_dbgapi_status_t status
1358 = amd_dbgapi_set_memory_precision (info
.process_id
, mode
);
1360 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
1361 info
.precise_memory
.enabled
= info
.precise_memory
.requested
;
1362 else if (status
== AMD_DBGAPI_STATUS_ERROR_NOT_SUPPORTED
)
1363 warning (_("AMDGPU precise memory access reporting could not be enabled."));
1364 else if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1365 error (_("amd_dbgapi_set_memory_precision failed (%s)"),
1366 get_status_string (status
));
1369 /* Make the amd-dbgapi library attach to the process behind INF.
1371 Note that this is unrelated to the "attach" GDB concept / command.
1373 By attaching to the process, we get a notifier fd that tells us when it
1374 activates the ROCm runtime and when there are subsequent debug events. */
1377 attach_amd_dbgapi (inferior
*inf
)
1379 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf
->num
);
1381 if (!target_can_async_p ())
1383 warning (_("The amd-dbgapi target requires the target beneath to be "
1384 "asynchronous, GPU debugging is disabled"));
1388 /* dbgapi can't attach to a vfork child (a process born from a vfork that
1389 hasn't exec'ed yet) while we are still attached to the parent. It would
1390 not be useful for us to attach to vfork children anyway, because vfork
1391 children are very restricted in what they can do (see vfork(2)) and aren't
1392 going to launch some GPU programs that we need to debug. To avoid this
1393 problem, we don't push the amd-dbgapi target / attach dbgapi in vfork
1394 children. If a vfork child execs, we'll try enabling the amd-dbgapi target
1395 through the inferior_execd observer. */
1396 if (inf
->vfork_parent
!= nullptr)
1399 auto *info
= get_amd_dbgapi_inferior_info (inf
);
1401 /* Are we already attached? */
1402 if (info
->process_id
!= AMD_DBGAPI_PROCESS_NONE
)
1404 amd_dbgapi_debug_printf
1405 ("already attached: process_id = %" PRIu64
, info
->process_id
.handle
);
1409 amd_dbgapi_status_t status
1410 = amd_dbgapi_process_attach
1411 (reinterpret_cast<amd_dbgapi_client_process_id_t
> (inf
),
1413 if (status
== AMD_DBGAPI_STATUS_ERROR_RESTRICTION
)
1415 warning (_("amd-dbgapi: unable to enable GPU debugging due to a "
1416 "restriction error"));
1419 else if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1421 warning (_("amd-dbgapi: could not attach to process %d (%s), GPU "
1422 "debugging will not be available."), inf
->pid
,
1423 get_status_string (status
));
1427 if (amd_dbgapi_process_get_info (info
->process_id
,
1428 AMD_DBGAPI_PROCESS_INFO_NOTIFIER
,
1429 sizeof (info
->notifier
), &info
->notifier
)
1430 != AMD_DBGAPI_STATUS_SUCCESS
)
1432 amd_dbgapi_process_detach (info
->process_id
);
1433 info
->process_id
= AMD_DBGAPI_PROCESS_NONE
;
1434 warning (_("amd-dbgapi: could not retrieve process %d's notifier, GPU "
1435 "debugging will not be available."), inf
->pid
);
1439 amd_dbgapi_debug_printf ("process_id = %" PRIu64
", notifier fd = %d",
1440 info
->process_id
.handle
, info
->notifier
);
1442 set_process_memory_precision (*info
);
1444 /* If GDB is attaching to a process that has the runtime loaded, there will
1445 already be a "runtime loaded" event available. Consume it and push the
1447 dbgapi_notifier_handler (0, info
);
1449 add_file_handler (info
->notifier
, dbgapi_notifier_handler
, info
,
1450 "amd-dbgapi notifier");
1453 static void maybe_reset_amd_dbgapi ();
1455 /* Make the amd-dbgapi library detach from INF.
1457 Note that this us unrelated to the "detach" GDB concept / command.
1459 This undoes what attach_amd_dbgapi does. */
1462 detach_amd_dbgapi (inferior
*inf
)
1464 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf
->num
);
1466 auto *info
= get_amd_dbgapi_inferior_info (inf
);
1468 if (info
->process_id
== AMD_DBGAPI_PROCESS_NONE
)
1471 info
->runtime_state
= AMD_DBGAPI_RUNTIME_STATE_UNLOADED
;
1473 amd_dbgapi_status_t status
= amd_dbgapi_process_detach (info
->process_id
);
1474 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1475 warning (_("amd-dbgapi: could not detach from process %d (%s)"),
1476 inf
->pid
, get_status_string (status
));
1478 gdb_assert (info
->notifier
!= -1);
1479 delete_file_handler (info
->notifier
);
1481 /* This is a noop if the target is not pushed. */
1482 inf
->unpush_target (&the_amd_dbgapi_target
);
1484 /* Delete the breakpoints that are still active. */
1485 for (auto &&value
: info
->breakpoint_map
)
1486 delete_breakpoint (value
.second
);
1488 /* Reset the amd_dbgapi_inferior_info, except for precise_memory_mode. */
1489 *info
= amd_dbgapi_inferior_info (inf
, info
->precise_memory
.requested
);
1491 maybe_reset_amd_dbgapi ();
1495 amd_dbgapi_target::mourn_inferior ()
1497 detach_amd_dbgapi (current_inferior ());
1498 beneath ()->mourn_inferior ();
1502 amd_dbgapi_target::detach (inferior
*inf
, int from_tty
)
1504 /* We're about to resume the waves by detaching the dbgapi library from the
1505 inferior, so we need to remove all breakpoints that are still inserted.
1507 Breakpoints may still be inserted because the inferior may be running in
1508 non-stop mode, or because GDB changed the default setting to leave all
1509 breakpoints inserted in all-stop mode when all threads are stopped. */
1510 remove_breakpoints_inf (inf
);
1512 detach_amd_dbgapi (inf
);
1513 beneath ()->detach (inf
, from_tty
);
1517 amd_dbgapi_target::fetch_registers (struct regcache
*regcache
, int regno
)
1519 if (!ptid_is_gpu (regcache
->ptid ()))
1521 beneath ()->fetch_registers (regcache
, regno
);
1525 struct gdbarch
*gdbarch
= regcache
->arch ();
1526 gdb_assert (is_amdgpu_arch (gdbarch
));
1528 amdgpu_gdbarch_tdep
*tdep
= get_amdgpu_gdbarch_tdep (gdbarch
);
1529 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
1530 gdb_byte raw
[AMDGPU_MAX_REGISTER_SIZE
];
1531 amd_dbgapi_status_t status
1532 = amd_dbgapi_read_register (wave_id
, tdep
->register_ids
[regno
], 0,
1533 register_type (gdbarch
, regno
)->length (),
1536 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
1537 regcache
->raw_supply (regno
, raw
);
1538 else if (status
!= AMD_DBGAPI_STATUS_ERROR_REGISTER_NOT_AVAILABLE
)
1539 warning (_("Couldn't read register %s (#%d) (%s)."),
1540 gdbarch_register_name (gdbarch
, regno
), regno
,
1541 get_status_string (status
));
1545 amd_dbgapi_target::store_registers (struct regcache
*regcache
, int regno
)
1547 if (!ptid_is_gpu (regcache
->ptid ()))
1549 beneath ()->store_registers (regcache
, regno
);
1553 struct gdbarch
*gdbarch
= regcache
->arch ();
1554 gdb_assert (is_amdgpu_arch (gdbarch
));
1556 gdb_byte raw
[AMDGPU_MAX_REGISTER_SIZE
];
1557 regcache
->raw_collect (regno
, &raw
);
1559 amdgpu_gdbarch_tdep
*tdep
= get_amdgpu_gdbarch_tdep (gdbarch
);
1561 /* If the register has read-only bits, invalidate the value in the regcache
1562 as the value actually written may differ. */
1563 if (tdep
->register_properties
[regno
]
1564 & AMD_DBGAPI_REGISTER_PROPERTY_READONLY_BITS
)
1565 regcache
->invalidate (regno
);
1567 /* Invalidate all volatile registers if this register has the invalidate
1568 volatile property. For example, writing to VCC may change the content
1570 if (tdep
->register_properties
[regno
]
1571 & AMD_DBGAPI_REGISTER_PROPERTY_INVALIDATE_VOLATILE
)
1573 for (size_t r
= 0; r
< tdep
->register_properties
.size (); ++r
)
1574 if (tdep
->register_properties
[r
] & AMD_DBGAPI_REGISTER_PROPERTY_VOLATILE
)
1575 regcache
->invalidate (r
);
1578 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
1579 amd_dbgapi_status_t status
1580 = amd_dbgapi_write_register (wave_id
, tdep
->register_ids
[regno
], 0,
1581 register_type (gdbarch
, regno
)->length (),
1584 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1585 warning (_("Couldn't write register %s (#%d)."),
1586 gdbarch_register_name (gdbarch
, regno
), regno
);
1590 amd_dbgapi_target::thread_architecture (ptid_t ptid
)
1592 if (!ptid_is_gpu (ptid
))
1593 return beneath ()->thread_architecture (ptid
);
1595 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
1596 wave IDs are unique, and aren't reused. */
1597 if (ptid
.tid () == m_cached_arch_tid
)
1598 return m_cached_arch
;
1600 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
1601 amd_dbgapi_architecture_id_t architecture_id
;
1602 amd_dbgapi_status_t status
;
1604 status
= amd_dbgapi_wave_get_info (wave_id
, AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
1605 sizeof (architecture_id
),
1607 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1608 error (_("Couldn't get architecture for wave_%ld"), ptid
.tid ());
1610 uint32_t elf_amdgpu_machine
;
1611 status
= amd_dbgapi_architecture_get_info
1612 (architecture_id
, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE
,
1613 sizeof (elf_amdgpu_machine
), &elf_amdgpu_machine
);
1614 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1615 error (_("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1616 architecture_id
.handle
);
1618 struct gdbarch_info info
;
1619 info
.bfd_arch_info
= bfd_lookup_arch (bfd_arch_amdgcn
, elf_amdgpu_machine
);
1620 info
.byte_order
= BFD_ENDIAN_LITTLE
;
1622 m_cached_arch_tid
= ptid
.tid ();
1623 m_cached_arch
= gdbarch_find_by_info (info
);
1624 if (m_cached_arch
== nullptr)
1625 error (_("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine
);
1627 return m_cached_arch
;
1631 amd_dbgapi_target::thread_events (int enable
)
1633 m_report_thread_events
= enable
;
1634 beneath ()->thread_events (enable
);
1638 amd_dbgapi_target::update_thread_list ()
1640 for (inferior
*inf
: all_inferiors ())
1642 amd_dbgapi_process_id_t process_id
1643 = get_amd_dbgapi_process_id (inf
);
1644 if (process_id
== AMD_DBGAPI_PROCESS_NONE
)
1646 /* The inferior may not be attached yet. */
1651 amd_dbgapi_wave_id_t
*wave_list
;
1652 amd_dbgapi_changed_t changed
;
1653 amd_dbgapi_status_t status
1654 = amd_dbgapi_process_wave_list (process_id
, &count
, &wave_list
,
1656 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1657 error (_("amd_dbgapi_wave_list failed (%s)"),
1658 get_status_string (status
));
1660 if (changed
== AMD_DBGAPI_CHANGED_NO
)
1663 /* Create a set and free the wave list. */
1664 std::set
<ptid_t::tid_type
> threads
;
1665 for (size_t i
= 0; i
< count
; ++i
)
1666 threads
.emplace (wave_list
[i
].handle
);
1670 /* Prune the wave_ids that already have a thread_info. Any thread_info
1671 which does not have a corresponding wave_id represents a wave which
1672 is gone at this point and should be deleted. */
1673 for (thread_info
*tp
: inf
->threads_safe ())
1674 if (ptid_is_gpu (tp
->ptid
) && tp
->state
!= THREAD_EXITED
)
1676 auto it
= threads
.find (tp
->ptid
.tid ());
1678 if (it
== threads
.end ())
1679 delete_thread_silent (tp
);
1684 /* The wave_ids that are left require a new thread_info. */
1685 for (ptid_t::tid_type tid
: threads
)
1688 = make_gpu_ptid (inf
->pid
, amd_dbgapi_wave_id_t
{tid
});
1690 add_thread_silent (inf
->process_target (), wave_ptid
);
1691 set_running (inf
->process_target (), wave_ptid
, true);
1692 set_executing (inf
->process_target (), wave_ptid
, true);
1696 /* Give the beneath target a chance to do extra processing. */
1697 this->beneath ()->update_thread_list ();
1700 /* inferior_created observer. */
1703 amd_dbgapi_target_inferior_created (inferior
*inf
)
1705 /* If the inferior is not running on the native target (e.g. it is running
1706 on a remote target), we don't want to deal with it. */
1707 if (inf
->process_target () != get_native_target ())
1710 attach_amd_dbgapi (inf
);
1713 /* Callback called when an inferior is cloned. */
1716 amd_dbgapi_target_inferior_cloned (inferior
*original_inferior
,
1717 inferior
*new_inferior
)
1719 auto *orig_info
= get_amd_dbgapi_inferior_info (original_inferior
);
1720 auto *new_info
= get_amd_dbgapi_inferior_info (new_inferior
);
1722 /* At this point, the process is not started. Therefore it is sufficient to
1723 copy the precise memory request, it will be applied when the process
1725 gdb_assert (new_info
->process_id
== AMD_DBGAPI_PROCESS_NONE
);
1726 new_info
->precise_memory
.requested
= orig_info
->precise_memory
.requested
;
1729 /* inferior_execd observer. */
1732 amd_dbgapi_inferior_execd (inferior
*exec_inf
, inferior
*follow_inf
)
1734 /* The inferior has EXEC'd and the process image has changed. The dbgapi is
1735 attached to the old process image, so we need to detach and re-attach to
1736 the new process image. */
1737 detach_amd_dbgapi (exec_inf
);
1739 /* If using "follow-exec-mode new", carry over the precise-memory setting
1740 to the new inferior (otherwise, FOLLOW_INF and ORIG_INF point to the same
1741 inferior, so this is a no-op). */
1742 get_amd_dbgapi_inferior_info (follow_inf
)->precise_memory
.requested
1743 = get_amd_dbgapi_inferior_info (exec_inf
)->precise_memory
.requested
;
1745 attach_amd_dbgapi (follow_inf
);
1748 /* inferior_forked observer. */
1751 amd_dbgapi_inferior_forked (inferior
*parent_inf
, inferior
*child_inf
,
1752 target_waitkind fork_kind
)
1754 if (child_inf
!= nullptr)
1756 /* Copy precise-memory requested value from parent to child. */
1757 amd_dbgapi_inferior_info
*parent_info
1758 = get_amd_dbgapi_inferior_info (parent_inf
);
1759 amd_dbgapi_inferior_info
*child_info
1760 = get_amd_dbgapi_inferior_info (child_inf
);
1761 child_info
->precise_memory
.requested
1762 = parent_info
->precise_memory
.requested
;
1764 if (fork_kind
!= TARGET_WAITKIND_VFORKED
)
1766 scoped_restore_current_thread restore_thread
;
1767 switch_to_thread (*child_inf
->threads ().begin ());
1768 attach_amd_dbgapi (child_inf
);
1773 /* inferior_exit observer.
1775 This covers normal exits, but also detached inferiors (including detached
1779 amd_dbgapi_inferior_exited (inferior
*inf
)
1781 detach_amd_dbgapi (inf
);
1784 /* inferior_pre_detach observer. */
1787 amd_dbgapi_inferior_pre_detach (inferior
*inf
)
1789 /* We need to amd-dbgapi-detach before we ptrace-detach. If the amd-dbgapi
1790 target isn't pushed, do that now. If the amd-dbgapi target is pushed,
1791 we'll do it in amd_dbgapi_target::detach. */
1792 if (!inf
->target_is_pushed (&the_amd_dbgapi_target
))
1793 detach_amd_dbgapi (inf
);
1796 /* get_os_pid callback. */
1798 static amd_dbgapi_status_t
1799 amd_dbgapi_get_os_pid_callback
1800 (amd_dbgapi_client_process_id_t client_process_id
, pid_t
*pid
)
1802 inferior
*inf
= reinterpret_cast<inferior
*> (client_process_id
);
1805 return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED
;
1808 return AMD_DBGAPI_STATUS_SUCCESS
;
1811 /* insert_breakpoint callback. */
1813 static amd_dbgapi_status_t
1814 amd_dbgapi_insert_breakpoint_callback
1815 (amd_dbgapi_client_process_id_t client_process_id
,
1816 amd_dbgapi_global_address_t address
,
1817 amd_dbgapi_breakpoint_id_t breakpoint_id
)
1819 inferior
*inf
= reinterpret_cast<inferior
*> (client_process_id
);
1820 struct amd_dbgapi_inferior_info
*info
= get_amd_dbgapi_inferior_info (inf
);
1822 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1823 if (it
!= info
->breakpoint_map
.end ())
1824 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1826 /* We need to find the address in the given inferior's program space. */
1827 scoped_restore_current_thread restore_thread
;
1828 switch_to_inferior_no_thread (inf
);
1830 /* Create a new breakpoint. */
1831 struct obj_section
*section
= find_pc_section (address
);
1832 if (section
== nullptr || section
->objfile
== nullptr)
1833 return AMD_DBGAPI_STATUS_ERROR
;
1835 std::unique_ptr
<breakpoint
> bp_up
1836 (new amd_dbgapi_target_breakpoint (section
->objfile
->arch (), address
));
1838 breakpoint
*bp
= install_breakpoint (true, std::move (bp_up
), 1);
1840 info
->breakpoint_map
.emplace (breakpoint_id
.handle
, bp
);
1841 return AMD_DBGAPI_STATUS_SUCCESS
;
1844 /* remove_breakpoint callback. */
1846 static amd_dbgapi_status_t
1847 amd_dbgapi_remove_breakpoint_callback
1848 (amd_dbgapi_client_process_id_t client_process_id
,
1849 amd_dbgapi_breakpoint_id_t breakpoint_id
)
1851 inferior
*inf
= reinterpret_cast<inferior
*> (client_process_id
);
1852 struct amd_dbgapi_inferior_info
*info
= get_amd_dbgapi_inferior_info (inf
);
1854 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1855 if (it
== info
->breakpoint_map
.end ())
1856 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1858 delete_breakpoint (it
->second
);
1859 info
->breakpoint_map
.erase (it
);
1861 return AMD_DBGAPI_STATUS_SUCCESS
;
1864 /* signal_received observer. */
1867 amd_dbgapi_target_signal_received (gdb_signal sig
)
1869 amd_dbgapi_inferior_info
*info
1870 = get_amd_dbgapi_inferior_info (current_inferior ());
1872 if (info
->process_id
== AMD_DBGAPI_PROCESS_NONE
)
1875 if (!ptid_is_gpu (inferior_thread ()->ptid
))
1878 if (sig
!= GDB_SIGNAL_SEGV
&& sig
!= GDB_SIGNAL_BUS
)
1881 if (!info
->precise_memory
.enabled
)
1883 Warning: precise memory violation signal reporting is not enabled, reported\n\
1884 location may not be accurate. See \"show amdgpu precise-memory\".\n"));
1887 /* Style for some kinds of messages. */
1889 static cli_style_option fatal_error_style
1890 ("amd_dbgapi_fatal_error", ui_file_style::RED
);
1891 static cli_style_option warning_style
1892 ("amd_dbgapi_warning", ui_file_style::YELLOW
);
1894 /* BLACK + BOLD means dark gray. */
1895 static cli_style_option trace_style
1896 ("amd_dbgapi_trace", ui_file_style::BLACK
, ui_file_style::BOLD
);
1898 /* log_message callback. */
1901 amd_dbgapi_log_message_callback (amd_dbgapi_log_level_t level
,
1902 const char *message
)
1904 std::optional
<target_terminal::scoped_restore_terminal_state
> tstate
;
1906 if (target_supports_terminal_ours ())
1909 target_terminal::ours_for_output ();
1912 /* Error and warning messages are meant to be printed to the user. */
1913 if (level
== AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
1914 || level
== AMD_DBGAPI_LOG_LEVEL_WARNING
)
1917 ui_file_style style
= (level
== AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
1918 ? fatal_error_style
: warning_style
).style ();
1919 gdb_printf (gdb_stderr
, "%ps\n", styled_string (style
, message
));
1923 /* Print other messages as debug logs. TRACE and VERBOSE messages are
1924 very verbose, print them dark grey so it's easier to spot other messages
1925 through the flood. */
1926 if (level
>= AMD_DBGAPI_LOG_LEVEL_TRACE
)
1928 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%ps",
1929 styled_string (trace_style
.style (), message
));
1933 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%s",
1937 /* Callbacks passed to amd_dbgapi_initialize. */
1939 static amd_dbgapi_callbacks_t dbgapi_callbacks
= {
1940 .allocate_memory
= malloc
,
1941 .deallocate_memory
= free
,
1942 .get_os_pid
= amd_dbgapi_get_os_pid_callback
,
1943 .insert_breakpoint
= amd_dbgapi_insert_breakpoint_callback
,
1944 .remove_breakpoint
= amd_dbgapi_remove_breakpoint_callback
,
1945 .log_message
= amd_dbgapi_log_message_callback
,
1949 amd_dbgapi_target::close ()
1951 if (amd_dbgapi_async_event_handler
!= nullptr)
1952 delete_async_event_handler (&amd_dbgapi_async_event_handler
);
1955 /* Callback for "show amdgpu precise-memory". */
1958 show_precise_memory_mode (struct ui_file
*file
, int from_tty
,
1959 struct cmd_list_element
*c
, const char *value
)
1961 amd_dbgapi_inferior_info
*info
1962 = get_amd_dbgapi_inferior_info (current_inferior ());
1965 _("AMDGPU precise memory access reporting is %s "
1966 "(currently %s).\n"),
1967 info
->precise_memory
.requested
? "on" : "off",
1968 info
->precise_memory
.enabled
? "enabled" : "disabled");
1971 /* Callback for "set amdgpu precise-memory". */
1974 set_precise_memory_mode (bool value
)
1976 amd_dbgapi_inferior_info
*info
1977 = get_amd_dbgapi_inferior_info (current_inferior ());
1979 info
->precise_memory
.requested
= value
;
1981 if (info
->process_id
!= AMD_DBGAPI_PROCESS_NONE
)
1982 set_process_memory_precision (*info
);
1985 /* Return whether precise-memory is requested for the current inferior. */
1988 get_precise_memory_mode ()
1990 amd_dbgapi_inferior_info
*info
1991 = get_amd_dbgapi_inferior_info (current_inferior ());
1993 return info
->precise_memory
.requested
;
1996 /* List of set/show amdgpu commands. */
1997 struct cmd_list_element
*set_amdgpu_list
;
1998 struct cmd_list_element
*show_amdgpu_list
;
2000 /* List of set/show debug amd-dbgapi-lib commands. */
2001 struct cmd_list_element
*set_debug_amd_dbgapi_lib_list
;
2002 struct cmd_list_element
*show_debug_amd_dbgapi_lib_list
;
2004 /* Mapping from amd-dbgapi log level enum values to text. */
2006 static constexpr const char *debug_amd_dbgapi_lib_log_level_enums
[] =
2008 /* [AMD_DBGAPI_LOG_LEVEL_NONE] = */ "off",
2009 /* [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR] = */ "error",
2010 /* [AMD_DBGAPI_LOG_LEVEL_WARNING] = */ "warning",
2011 /* [AMD_DBGAPI_LOG_LEVEL_INFO] = */ "info",
2012 /* [AMD_DBGAPI_LOG_LEVEL_TRACE] = */ "trace",
2013 /* [AMD_DBGAPI_LOG_LEVEL_VERBOSE] = */ "verbose",
2017 /* Storage for "set debug amd-dbgapi-lib log-level". */
2019 static const char *debug_amd_dbgapi_lib_log_level
2020 = debug_amd_dbgapi_lib_log_level_enums
[AMD_DBGAPI_LOG_LEVEL_WARNING
];
2022 /* Get the amd-dbgapi library log level requested by the user. */
2024 static amd_dbgapi_log_level_t
2025 get_debug_amd_dbgapi_lib_log_level ()
2027 for (size_t pos
= 0;
2028 debug_amd_dbgapi_lib_log_level_enums
[pos
] != nullptr;
2030 if (debug_amd_dbgapi_lib_log_level
2031 == debug_amd_dbgapi_lib_log_level_enums
[pos
])
2032 return static_cast<amd_dbgapi_log_level_t
> (pos
);
2034 gdb_assert_not_reached ("invalid log level");
2037 /* Callback for "set debug amd-dbgapi log-level", apply the selected log level
2041 set_debug_amd_dbgapi_lib_log_level (const char *args
, int from_tty
,
2042 struct cmd_list_element
*c
)
2044 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ());
2047 /* Callback for "show debug amd-dbgapi log-level". */
2050 show_debug_amd_dbgapi_lib_log_level (struct ui_file
*file
, int from_tty
,
2051 struct cmd_list_element
*c
,
2054 gdb_printf (file
, _("The amd-dbgapi library log level is %s.\n"), value
);
2057 /* If the amd-dbgapi library is not attached to any process, finalize and
2058 re-initialize it so that the handle ID numbers will all start from the
2059 beginning again. This is only for convenience, not essential. */
2062 maybe_reset_amd_dbgapi ()
2064 for (inferior
*inf
: all_non_exited_inferiors ())
2066 amd_dbgapi_inferior_info
*info
= get_amd_dbgapi_inferior_info (inf
);
2068 if (info
->process_id
!= AMD_DBGAPI_PROCESS_NONE
)
2072 amd_dbgapi_status_t status
= amd_dbgapi_finalize ();
2073 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
2074 error (_("amd-dbgapi failed to finalize (%s)"),
2075 get_status_string (status
));
2077 status
= amd_dbgapi_initialize (&dbgapi_callbacks
);
2078 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
2079 error (_("amd-dbgapi failed to initialize (%s)"),
2080 get_status_string (status
));
2083 extern initialize_file_ftype _initialize_amd_dbgapi_target
;
2086 _initialize_amd_dbgapi_target ()
2088 /* Make sure the loaded debugger library version is greater than or equal to
2089 the one used to build GDB. */
2090 uint32_t major
, minor
, patch
;
2091 amd_dbgapi_get_version (&major
, &minor
, &patch
);
2092 if (major
!= AMD_DBGAPI_VERSION_MAJOR
|| minor
< AMD_DBGAPI_VERSION_MINOR
)
2093 error (_("amd-dbgapi library version mismatch, got %d.%d.%d, need %d.%d+"),
2094 major
, minor
, patch
, AMD_DBGAPI_VERSION_MAJOR
,
2095 AMD_DBGAPI_VERSION_MINOR
);
2097 /* Initialize the AMD Debugger API. */
2098 amd_dbgapi_status_t status
= amd_dbgapi_initialize (&dbgapi_callbacks
);
2099 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
2100 error (_("amd-dbgapi failed to initialize (%s)"),
2101 get_status_string (status
));
2103 /* Set the initial log level. */
2104 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ());
2106 /* Install observers. */
2107 gdb::observers::inferior_cloned
.attach (amd_dbgapi_target_inferior_cloned
,
2109 gdb::observers::signal_received
.attach (amd_dbgapi_target_signal_received
,
2111 gdb::observers::inferior_created
.attach
2112 (amd_dbgapi_target_inferior_created
,
2113 amd_dbgapi_target_inferior_created_observer_token
, "amd-dbgapi");
2114 gdb::observers::inferior_execd
.attach (amd_dbgapi_inferior_execd
, "amd-dbgapi");
2115 gdb::observers::inferior_forked
.attach (amd_dbgapi_inferior_forked
, "amd-dbgapi");
2116 gdb::observers::inferior_exit
.attach (amd_dbgapi_inferior_exited
, "amd-dbgapi");
2117 gdb::observers::inferior_pre_detach
.attach (amd_dbgapi_inferior_pre_detach
, "amd-dbgapi");
2119 add_basic_prefix_cmd ("amdgpu", no_class
,
2120 _("Generic command for setting amdgpu flags."),
2121 &set_amdgpu_list
, 0, &setlist
);
2123 add_show_prefix_cmd ("amdgpu", no_class
,
2124 _("Generic command for showing amdgpu flags."),
2125 &show_amdgpu_list
, 0, &showlist
);
2127 add_setshow_boolean_cmd ("precise-memory", no_class
,
2128 _("Set precise-memory mode."),
2129 _("Show precise-memory mode."), _("\
2130 If on, precise memory reporting is enabled if/when the inferior is running.\n\
2131 If off (default), precise memory reporting is disabled."),
2132 set_precise_memory_mode
,
2133 get_precise_memory_mode
,
2134 show_precise_memory_mode
,
2135 &set_amdgpu_list
, &show_amdgpu_list
);
2137 add_basic_prefix_cmd ("amd-dbgapi-lib", no_class
,
2138 _("Generic command for setting amd-dbgapi library "
2139 "debugging flags."),
2140 &set_debug_amd_dbgapi_lib_list
, 0, &setdebuglist
);
2142 add_show_prefix_cmd ("amd-dbgapi-lib", no_class
,
2143 _("Generic command for showing amd-dbgapi library "
2144 "debugging flags."),
2145 &show_debug_amd_dbgapi_lib_list
, 0, &showdebuglist
);
2147 add_setshow_enum_cmd ("log-level", class_maintenance
,
2148 debug_amd_dbgapi_lib_log_level_enums
,
2149 &debug_amd_dbgapi_lib_log_level
,
2150 _("Set the amd-dbgapi library log level."),
2151 _("Show the amd-dbgapi library log level."),
2152 _("off == no logging is enabled\n"
2153 "error == fatal errors are reported\n"
2154 "warning == fatal errors and warnings are reported\n"
2155 "info == fatal errors, warnings, and info "
2156 "messages are reported\n"
2157 "trace == fatal errors, warnings, info, and "
2158 "API tracing messages are reported\n"
2159 "verbose == all messages are reported"),
2160 set_debug_amd_dbgapi_lib_log_level
,
2161 show_debug_amd_dbgapi_lib_log_level
,
2162 &set_debug_amd_dbgapi_lib_list
,
2163 &show_debug_amd_dbgapi_lib_list
);
2165 add_setshow_boolean_cmd ("amd-dbgapi", class_maintenance
,
2167 _("Set debugging of amd-dbgapi target."),
2168 _("Show debugging of amd-dbgapi target."),
2170 When on, print debug messages relating to the amd-dbgapi target."),
2172 &setdebuglist
, &showdebuglist
);