1 /* Target-dependent code for ROCm.
3 Copyright (C) 2019-2020 Free Software Foundation, Inc.
4 Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "amdgcn-rocm-tdep.h"
24 #include "arch-utils.h"
25 #include "cli/cli-style.h"
27 #include "event-loop.h"
28 #include "filenames.h"
31 #include "gdbsupport/filestuff.h"
32 #include "gdbsupport/scoped_fd.h"
33 #include "gdbthread.h"
39 #include "observable.h"
40 #include "progspace-and-thread.h"
42 #include "rocm-tdep.h"
52 #include <unordered_map>
54 #include <amd-dbgapi.h>
56 /* Big enough to hold the size of the largest register in bytes. */
57 #define AMDGCN_MAX_REGISTER_SIZE 256
59 #define DEFINE_OBSERVABLE(name) decltype (name) name (#name)
61 DEFINE_OBSERVABLE (amd_dbgapi_activated
);
62 DEFINE_OBSERVABLE (amd_dbgapi_deactivated
);
63 DEFINE_OBSERVABLE (amd_dbgapi_code_object_list_updated
);
65 #undef DEFINE_OBSERVABLE
67 struct rocm_notify_shared_library_info
69 std::string compare
; /* Compare loaded library names with this string. */
70 struct so_list
*solib
;
74 /* ROCm-specific inferior data. */
76 struct rocm_inferior_info
78 /* The amd_dbgapi_process_id for this inferior. */
79 amd_dbgapi_process_id_t process_id
{ AMD_DBGAPI_PROCESS_NONE
};
81 /* The amd_dbgapi_notifier_t for this inferior. */
82 amd_dbgapi_notifier_t notifier
{ -1 };
84 /* True if commit_resume should all-start the GPU queues. */
85 bool commit_resume_all_start
;
87 /* True is the inferior has exited. */
88 bool has_exited
{ false };
90 std::unordered_map
<decltype (amd_dbgapi_breakpoint_id_t::handle
),
94 /* List of pending events the rocm target retrieved from the dbgapi. */
95 std::list
<std::pair
<amd_dbgapi_wave_id_t
, amd_dbgapi_wave_stop_reason_t
>>
98 /* Map of rocm_notify_shared_library_info's for libraries that have been
99 registered to receive notifications when loading/unloading. */
100 std::unordered_map
<decltype (amd_dbgapi_shared_library_id_t::handle
),
101 struct rocm_notify_shared_library_info
>
105 static amd_dbgapi_event_id_t
106 rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind
107 = AMD_DBGAPI_EVENT_KIND_NONE
);
109 /* Return the inferior's rocm_inferior_info struct. */
110 static struct rocm_inferior_info
*
111 get_rocm_inferior_info (struct inferior
*inferior
= nullptr);
113 static const target_info rocm_ops_info
114 = { "rocm", N_ ("ROCm GPU debugging support"),
115 N_ ("ROCm GPU debugging support") };
117 static amd_dbgapi_log_level_t
get_debug_amd_dbgapi_log_level ();
119 struct rocm_target_ops final
: public target_ops
122 info () const override
124 return rocm_ops_info
;
127 stratum () const override
132 void mourn_inferior () override
;
134 void async (int enable
) override
;
136 ptid_t
wait (ptid_t
, struct target_waitstatus
*, int) override
;
137 void resume (ptid_t
, int, enum gdb_signal
) override
;
138 void commit_resume () override
;
139 void stop (ptid_t ptid
) override
;
141 void fetch_registers (struct regcache
*, int) override
;
142 void store_registers (struct regcache
*, int) override
;
144 void update_thread_list () override
;
146 struct gdbarch
*thread_architecture (ptid_t
) override
;
148 std::string
pid_to_str (ptid_t ptid
) override
;
150 const char *thread_name (thread_info
*tp
) override
;
152 const char *extra_thread_info (thread_info
*tp
) override
;
154 bool thread_alive (ptid_t ptid
) override
;
156 enum target_xfer_status
xfer_partial (enum target_object object
,
157 const char *annex
, gdb_byte
*readbuf
,
158 const gdb_byte
*writebuf
,
159 ULONGEST offset
, ULONGEST len
,
160 ULONGEST
*xfered_len
) override
;
163 stopped_by_watchpoint () override
165 return !ptid_is_gpu (inferior_ptid
)
166 && beneath ()->stopped_by_watchpoint ();
170 stopped_data_address (CORE_ADDR
*addr_p
) override
172 return !ptid_is_gpu (inferior_ptid
)
173 && beneath ()->stopped_data_address (addr_p
);
177 supports_stopped_by_sw_breakpoint () override
182 bool stopped_by_sw_breakpoint () override
;
185 stopped_by_hw_breakpoint () override
187 return !ptid_is_gpu (inferior_ptid
)
188 && beneath ()->stopped_by_hw_breakpoint ();
192 /* ROCm's target vector. */
193 static struct rocm_target_ops rocm_ops
;
195 /* ROCm breakpoint ops. */
196 static struct breakpoint_ops rocm_breakpoint_ops
;
198 /* Per-inferior data key. */
199 static const struct inferior_key
<rocm_inferior_info
> rocm_inferior_data
;
201 /* The read/write ends of the pipe registered as waitable file in the
203 static int rocm_event_pipe
[2] = { -1, -1 };
205 /* Flush the event pipe. */
208 async_file_flush (void)
215 ret
= read (rocm_event_pipe
[0], &buf
, 1);
217 while (ret
>= 0 || (ret
== -1 && errno
== EINTR
));
220 /* Put something (anything, doesn't matter what, or how much) in event
221 pipe, so that the select/poll in the event-loop realizes we have
222 something to process. */
225 async_file_mark (void)
229 /* It doesn't really matter what the pipe contains, as long we end
230 up with something in it. Might as well flush the previous
236 ret
= write (rocm_event_pipe
[1], "+", 1);
238 while (ret
== -1 && errno
== EINTR
);
240 /* Ignore EAGAIN. If the pipe is full, the event loop will already
241 be awakened anyway. */
244 /* Fetch the rocm_inferior_info data for the given inferior. */
246 static struct rocm_inferior_info
*
247 get_rocm_inferior_info (struct inferior
*inferior
)
250 inferior
= current_inferior ();
252 struct rocm_inferior_info
*info
= rocm_inferior_data
.get (inferior
);
255 info
= rocm_inferior_data
.emplace (inferior
);
260 /* Fetch the amd_dbgapi_process_id for the given inferior. */
262 amd_dbgapi_process_id_t
263 get_amd_dbgapi_process_id (struct inferior
*inferior
)
265 return get_rocm_inferior_info (inferior
)->process_id
;
269 rocm_breakpoint_re_set (struct breakpoint
*b
)
274 rocm_breakpoint_check_status (struct bpstats
*bs
)
276 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
277 amd_dbgapi_process_id_t process_id
= info
->process_id
;
278 amd_dbgapi_status_t status
;
281 bs
->print_it
= print_it_noop
;
283 /* Find the address the breakpoint is set at. */
284 auto it
= std::find_if (
285 info
->breakpoint_map
.begin (), info
->breakpoint_map
.end (),
286 [=] (const decltype (info
->breakpoint_map
)::value_type
&value
) {
287 return value
.second
== bs
->breakpoint_at
;
290 if (it
== info
->breakpoint_map
.end ())
291 error (_ ("Could not find breakpoint_id for breakpoint at %#lx"),
292 bs
->bp_location_at
->address
);
294 amd_dbgapi_breakpoint_id_t breakpoint_id
{ it
->first
};
295 amd_dbgapi_breakpoint_action_t action
;
297 status
= amd_dbgapi_report_breakpoint_hit (process_id
, breakpoint_id
,
298 inferior_thread (), &action
);
300 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
301 error (_ ("amd_dbgapi_report_breakpoint_hit failed: breakpoint_%ld "
303 breakpoint_id
.handle
, bs
->bp_location_at
->address
, status
);
305 if (action
== AMD_DBGAPI_BREAKPOINT_ACTION_RESUME
)
308 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
309 a breakpoint resume event for this breakpoint_id is seen. */
311 amd_dbgapi_event_id_t resume_event_id
312 = rocm_process_event_queue (AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
);
314 /* We should always get a breakpoint_resume event after processing all
315 events generated by reporting the breakpoint was hit. */
316 gdb_assert (resume_event_id
.handle
!= AMD_DBGAPI_EVENT_NONE
.handle
);
318 amd_dbgapi_breakpoint_id_t resume_breakpoint_id
;
319 status
= amd_dbgapi_event_get_info (
320 process_id
, resume_event_id
, AMD_DBGAPI_EVENT_INFO_BREAKPOINT
,
321 sizeof (resume_breakpoint_id
), &resume_breakpoint_id
);
323 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
324 error (_ ("amd_dbgapi_event_get_info failed (rc=%d)"), status
);
326 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint]
327 sequences cannot interleave, so this breakpoint resume event must be
328 for our breakpoint_id. */
329 if (resume_breakpoint_id
.handle
!= breakpoint_id
.handle
)
330 error (_ ("breakpoint resume event is not for this breakpoint. "
331 "Expected breakpoint_%ld, got breakpoint_%ld"),
332 breakpoint_id
.handle
, resume_breakpoint_id
.handle
);
334 amd_dbgapi_event_processed (process_id
, resume_event_id
);
338 rocm_target_dbgapi_activated ()
340 /* FIXME: only push on the first activation. */
341 /* Engage the ROCm target_ops and so_ops. */
342 push_target (&rocm_ops
);
346 rocm_target_dbgapi_deactivated ()
348 /* FIXME: only unpush on the last activation. */
349 /* Disengage the ROCm target_ops. */
350 unpush_target (&rocm_ops
);
354 rocm_target_ops::thread_alive (ptid_t ptid
)
356 if (!ptid_is_gpu (ptid
))
357 return beneath ()->thread_alive (ptid
);
359 /* Check that the wave_id is valid. */
361 inferior
*inf
= find_inferior_ptid (ptid
);
365 amd_dbgapi_wave_state_t state
;
366 return amd_dbgapi_wave_get_info (
367 get_amd_dbgapi_process_id (inf
), get_amd_dbgapi_wave_id (ptid
),
368 AMD_DBGAPI_WAVE_INFO_STATE
, sizeof (state
), &state
)
369 == AMD_DBGAPI_STATUS_SUCCESS
;
373 rocm_target_ops::thread_name (thread_info
*tp
)
375 if (!ptid_is_gpu (tp
->ptid
))
376 return beneath ()->thread_name (tp
);
378 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (tp
->inf
);
379 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (tp
->ptid
);
380 amd_dbgapi_dispatch_id_t dispatch_id
;
381 amd_dbgapi_global_address_t kernel_addr
;
383 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
384 AMD_DBGAPI_WAVE_INFO_DISPATCH
,
385 sizeof (dispatch_id
), &dispatch_id
)
386 != AMD_DBGAPI_STATUS_SUCCESS
387 || amd_dbgapi_dispatch_get_info (
388 process_id
, dispatch_id
,
389 AMD_DBGAPI_DISPATCH_INFO_KERNEL_ENTRY_ADDRESS
,
390 sizeof (kernel_addr
), &kernel_addr
)
391 != AMD_DBGAPI_STATUS_SUCCESS
)
394 struct bound_minimal_symbol msymbol
395 = lookup_minimal_symbol_by_pc_section (kernel_addr
, nullptr);
397 if (msymbol
.minsym
!= NULL
)
399 static char buf
[256];
402 xsnprintf (buf
, sizeof (buf
), "%s", msymbol
.minsym
->print_name ());
404 /* Strip the arguments from the demangled function name. */
405 if ((endp
= strchr (buf
, '(')))
415 rocm_target_ops::pid_to_str (ptid_t ptid
)
417 if (!ptid_is_gpu (ptid
))
419 return beneath ()->pid_to_str (ptid
);
422 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
423 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
424 amd_dbgapi_dispatch_id_t dispatch_id
;
425 uint32_t group_ids
[3], wave_in_group
;
427 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
428 AMD_DBGAPI_WAVE_INFO_DISPATCH
,
429 sizeof (dispatch_id
), &dispatch_id
)
430 != AMD_DBGAPI_STATUS_SUCCESS
431 || amd_dbgapi_wave_get_info (process_id
, wave_id
,
432 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD
,
433 sizeof (group_ids
), &group_ids
)
434 != AMD_DBGAPI_STATUS_SUCCESS
435 || amd_dbgapi_wave_get_info (
437 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP
,
438 sizeof (wave_in_group
), &wave_in_group
)
439 != AMD_DBGAPI_STATUS_SUCCESS
)
440 return std::string ("AMDGPU Thread");
442 return string_printf ("AMDGPU Thread %ld.%ld (%d,%d,%d)/%d",
443 dispatch_id
.handle
, wave_id
.handle
, group_ids
[2],
444 group_ids
[1], group_ids
[0], wave_in_group
);
448 rocm_target_ops::extra_thread_info (thread_info
*tp
)
450 if (!ptid_is_gpu (tp
->ptid
))
451 beneath ()->extra_thread_info (tp
);
456 enum target_xfer_status
457 rocm_target_ops::xfer_partial (enum target_object object
, const char *annex
,
458 gdb_byte
*readbuf
, const gdb_byte
*writebuf
,
459 ULONGEST offset
, ULONGEST requested_len
,
460 ULONGEST
*xfered_len
)
462 gdb::optional
<scoped_restore_current_thread
> maybe_restore_thread
;
464 if (ptid_is_gpu (inferior_ptid
))
466 gdb_assert (requested_len
&& xfered_len
&& "checking invariants");
468 if (object
!= TARGET_OBJECT_MEMORY
)
469 return TARGET_XFER_E_IO
;
471 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
472 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
474 amd_dbgapi_architecture_id_t architecture_id
;
475 amd_dbgapi_address_space_id_t address_space_id
;
477 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
478 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
479 sizeof (architecture_id
), &architecture_id
)
480 != AMD_DBGAPI_STATUS_SUCCESS
481 || amd_dbgapi_architecture_get_info (
483 AMD_DBGAPI_ARCHITECTURE_INFO_DEFAULT_GLOBAL_ADDRESS_SPACE
,
484 sizeof (address_space_id
), &address_space_id
)
485 != AMD_DBGAPI_STATUS_SUCCESS
)
486 return TARGET_XFER_EOF
;
488 size_t len
= requested_len
;
489 amd_dbgapi_status_t status
;
492 status
= amd_dbgapi_read_memory (
493 process_id
, wave_id
, 0, address_space_id
, offset
, &len
, readbuf
);
495 status
= amd_dbgapi_write_memory (
496 process_id
, wave_id
, 0, address_space_id
, offset
, &len
, writebuf
);
498 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
499 return TARGET_XFER_EOF
;
502 return TARGET_XFER_OK
;
505 return beneath ()->xfer_partial (object
, annex
, readbuf
, writebuf
, offset
,
506 requested_len
, xfered_len
);
510 rocm_target_ops::resume (ptid_t ptid
, int step
, enum gdb_signal signo
)
512 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
517 "\e[1;34minfrun: rocm_target_ops::resume ([%d,%ld,%ld])\e[0m\n",
518 ptid
.pid (), ptid
.lwp (), ptid
.tid ());
520 /* Check if the thread focus is on the GPU device. */
521 if (ptid
== minus_one_ptid
|| !ptid_is_gpu (ptid
))
523 beneath ()->resume (ptid
, step
, signo
);
524 if (ptid
!= minus_one_ptid
)
528 /* A specific PTID means `step only this process id'. */
529 bool resume_one
= ptid
!= minus_one_ptid
&& !ptid
.is_pid ();
530 gdb_assert (resume_one
|| !step
);
533 error (_ ("internal error - unimplemented "));
535 amd_dbgapi_process_set_progress (info
->process_id
,
536 AMD_DBGAPI_PROGRESS_NO_FORWARD
);
538 amd_dbgapi_status_t status
= amd_dbgapi_wave_resume (
539 info
->process_id
, get_amd_dbgapi_wave_id (ptid
),
540 step
? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
541 : AMD_DBGAPI_RESUME_MODE_NORMAL
);
542 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
543 warning (_ ("Could not resume %s (rc=%d)"),
544 target_pid_to_str (ptid
).c_str (), status
);
546 info
->commit_resume_all_start
= true;
550 rocm_target_ops::commit_resume ()
552 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
557 "\e[1;34minfrun: rocm_target_ops::commit_resume ()\e[0m\n");
559 beneath ()->commit_resume ();
561 if (info
->commit_resume_all_start
)
563 amd_dbgapi_process_set_progress (info
->process_id
,
564 AMD_DBGAPI_PROGRESS_NORMAL
);
565 info
->commit_resume_all_start
= false;
568 if (target_can_async_p ())
573 rocm_target_stop_one_wave (ptid_t ptid
)
575 amd_dbgapi_status_t status
;
577 status
= amd_dbgapi_wave_stop (get_amd_dbgapi_process_id (),
578 get_amd_dbgapi_wave_id (ptid
));
580 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
582 /* the wave must have exited, set the thread status to reflect that. */
583 auto *tp
= find_thread_ptid (ptid
);
586 tp
->state
= THREAD_EXITED
;
588 else if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
589 warning (_ ("Could not stop %s (rc=%d)"),
590 target_pid_to_str (ptid
).c_str (), status
);
594 rocm_target_ops::stop (ptid_t ptid
)
599 "\e[1;34minfrun: rocm_target_ops::stop ([%d,%ld,%ld])\e[0m\n",
600 ptid
.pid (), ptid
.lwp (), ptid
.tid ());
602 if (ptid
== minus_one_ptid
|| !ptid_is_gpu (ptid
))
604 beneath ()->stop (ptid
);
605 if (ptid
!= minus_one_ptid
)
609 if (ptid
== minus_one_ptid
)
610 error (_ ("internal error - unimplemented "));
612 rocm_target_stop_one_wave (ptid
);
616 handle_target_event (int error
, gdb_client_data client_data
)
618 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
619 amd_dbgapi_process_id_t process_id
= info
->process_id
;
621 amd_dbgapi_process_set_progress (process_id
, AMD_DBGAPI_PROGRESS_NO_FORWARD
);
623 /* Flush the async file first. */
624 if (target_is_async_p ())
627 rocm_process_event_queue ();
629 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
630 we can keep the process in progress_no_forward mode. The infrun loop
631 will enable forward progress when a thread is resumed. */
632 if (non_stop
|| info
->wave_stop_events
.empty ())
633 amd_dbgapi_process_set_progress (process_id
, AMD_DBGAPI_PROGRESS_NORMAL
);
635 if (!info
->wave_stop_events
.empty ())
636 inferior_event_handler (INF_REG_EVENT
, nullptr);
640 rocm_target_ops::async (int enable
)
642 beneath ()->async (enable
);
646 if (rocm_event_pipe
[0] != -1)
649 if (gdb_pipe_cloexec (rocm_event_pipe
) == -1)
650 internal_error (__FILE__
, __LINE__
, "creating event pipe failed.");
652 ::fcntl (rocm_event_pipe
[0], F_SETFL
, O_NONBLOCK
);
653 ::fcntl (rocm_event_pipe
[1], F_SETFL
, O_NONBLOCK
);
655 add_file_handler (rocm_event_pipe
[0], handle_target_event
, nullptr);
657 /* There may be pending events to handle. Tell the event loop
663 delete_file_handler (rocm_event_pipe
[0]);
665 if (rocm_event_pipe
[0] == -1)
668 ::close (rocm_event_pipe
[0]);
669 ::close (rocm_event_pipe
[1]);
670 rocm_event_pipe
[0] = -1;
671 rocm_event_pipe
[1] = -1;
676 rocm_process_one_event (amd_dbgapi_event_id_t event_id
,
677 amd_dbgapi_event_kind_t event_kind
)
679 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
680 amd_dbgapi_process_id_t process_id
= info
->process_id
;
681 amd_dbgapi_status_t status
;
685 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP
:
687 amd_dbgapi_wave_id_t wave_id
;
688 if ((status
= amd_dbgapi_event_get_info (process_id
, event_id
,
689 AMD_DBGAPI_EVENT_INFO_WAVE
,
690 sizeof (wave_id
), &wave_id
))
691 != AMD_DBGAPI_STATUS_SUCCESS
)
692 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
693 event_id
.handle
, status
);
695 amd_dbgapi_wave_stop_reason_t stop_reason
;
696 status
= amd_dbgapi_wave_get_info (process_id
, wave_id
,
697 AMD_DBGAPI_WAVE_INFO_STOP_REASON
,
698 sizeof (stop_reason
), &stop_reason
);
700 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
701 && status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
702 error (_ ("wave_get_info for wave_%ld failed (rc=%d)"),
703 wave_id
.handle
, status
);
705 /* The wave may have exited, or the queue went into an error
706 state. In such cases, we will see another wave command
707 terminated event, and handle the wave termination then. */
709 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
710 info
->wave_stop_events
.emplace_back (
711 std::make_pair (wave_id
, stop_reason
));
715 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED
:
716 amd_dbgapi_code_object_list_updated
.notify ();
719 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
:
720 /* Breakpoint resume events should be handled by the breakpoint
721 action, and this code should not reach this. */
722 gdb_assert_not_reached (_ ("unhandled event kind"));
725 case AMD_DBGAPI_EVENT_KIND_RUNTIME
:
727 amd_dbgapi_runtime_state_t runtime_state
;
729 if ((status
= amd_dbgapi_event_get_info (
730 process_id
, event_id
, AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE
,
731 sizeof (runtime_state
), &runtime_state
))
732 != AMD_DBGAPI_STATUS_SUCCESS
)
733 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
734 event_id
.handle
, status
);
736 switch (runtime_state
)
738 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUPPORTED
:
739 amd_dbgapi_activated
.notify ();
741 case AMD_DBGAPI_RUNTIME_STATE_LOADED_UNSUPPORTED
:
742 warning (_ ("ROCm-GDB: low-level runtime version not supported"));
745 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED
:
746 amd_dbgapi_deactivated
.notify ();
753 error (_ ("event kind (%d) not supported"), event_kind
);
756 amd_dbgapi_event_processed (process_id
, event_id
);
759 /* Drain the amd_dbgapi event queue until an event of the given type is seen.
760 If no particular event kind is specified (AMD_DBGAPI_EVENT_KIND_NONE), the
761 event queue is completely drained. Wave stop events that are not returned
762 are re-queued into the current's process pending wave events. */
763 static amd_dbgapi_event_id_t
764 rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind
)
766 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
770 amd_dbgapi_event_id_t event_id
;
771 amd_dbgapi_event_kind_t event_kind
;
773 amd_dbgapi_status_t status
= amd_dbgapi_next_pending_event (
774 info
->process_id
, &event_id
, &event_kind
);
776 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
777 error (_ ("next_pending_event failed (rc=%d)"), status
);
779 if (event_id
.handle
== AMD_DBGAPI_EVENT_NONE
.handle
780 || event_kind
== until_event_kind
)
783 rocm_process_one_event (event_id
, event_kind
);
788 rocm_target_ops::wait (ptid_t ptid
, struct target_waitstatus
*ws
,
792 fprintf_unfiltered (gdb_stdlog
,
793 "\e[1;34minfrun: rocm_target_ops::wait\e[0m\n");
795 if (!ptid_is_gpu (ptid
))
797 ptid_t event_ptid
= beneath ()->wait (ptid
, ws
, target_options
);
798 if (event_ptid
!= minus_one_ptid
)
802 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
803 amd_dbgapi_process_id_t process_id
= info
->process_id
;
805 /* Drain all the events from the amd_dbgapi, and preserve the ordering. */
806 if (info
->wave_stop_events
.empty ())
808 amd_dbgapi_process_set_progress (process_id
,
809 AMD_DBGAPI_PROGRESS_NO_FORWARD
);
811 /* Flush the async file first. */
812 if (target_is_async_p ())
815 rocm_process_event_queue ();
817 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
818 we can keep the process in progress_no_forward mode. The infrun loop
819 will enable forward progress when a thread is resumed. */
820 if (non_stop
|| info
->wave_stop_events
.empty ())
821 amd_dbgapi_process_set_progress (process_id
,
822 AMD_DBGAPI_PROGRESS_NORMAL
);
825 if (info
->wave_stop_events
.empty ())
826 return minus_one_ptid
;
828 amd_dbgapi_wave_id_t event_wave_id
;
829 amd_dbgapi_wave_stop_reason_t stop_reason
;
831 std::tie (event_wave_id
, stop_reason
) = info
->wave_stop_events
.front ();
832 info
->wave_stop_events
.pop_front ();
834 ptid_t
event_ptid (current_inferior ()->pid
, 1, event_wave_id
.handle
);
836 if (!find_thread_ptid (event_ptid
))
838 add_thread_silent (event_ptid
);
839 set_running (event_ptid
, 1);
840 set_executing (event_ptid
, 1);
843 /* Since we are manipulating the register cache for the event thread,
844 make sure it is the current thread. */
845 switch_to_thread (event_ptid
);
847 /* By caching the PC now, we avoid having to suspend/resume the queue
848 later when we need to access it. */
849 amd_dbgapi_global_address_t stop_pc
;
850 if (amd_dbgapi_wave_get_info (process_id
, event_wave_id
,
851 AMD_DBGAPI_WAVE_INFO_PC
, sizeof (stop_pc
),
853 == AMD_DBGAPI_STATUS_SUCCESS
)
855 struct regcache
*regcache
= get_thread_regcache (event_ptid
);
856 regcache
->raw_supply (gdbarch_pc_regnum (regcache
->arch ()), &stop_pc
);
858 ws
->kind
= TARGET_WAITKIND_STOPPED
;
861 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
862 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
))
863 ws
->value
.sig
= GDB_SIGNAL_TRAP
;
864 else if (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION
)
865 ws
->value
.sig
= GDB_SIGNAL_SEGV
;
867 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
868 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
869 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
870 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
871 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
872 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
873 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0
))
874 ws
->value
.sig
= GDB_SIGNAL_FPE
;
876 ws
->value
.sig
= GDB_SIGNAL_0
;
878 /* If there are more events in the list, mark the async file so that
879 rocm_target_ops::wait gets called again. */
880 if (target_is_async_p () && !info
->wave_stop_events
.empty ())
887 rocm_target_ops::stopped_by_sw_breakpoint ()
889 if (!ptid_is_gpu (inferior_ptid
))
890 return beneath ()->supports_stopped_by_sw_breakpoint ()
891 && beneath ()->stopped_by_sw_breakpoint ();
893 /* FIXME: we should check that the wave is not single-stepping. */
895 struct regcache
*regcache
= get_thread_regcache (inferior_ptid
);
897 CORE_ADDR bkpt_pc
= regcache_read_pc (regcache
)
898 - gdbarch_decr_pc_after_break (regcache
->arch ());
900 return software_breakpoint_inserted_here_p (regcache
->aspace (), bkpt_pc
);
904 rocm_target_ops::mourn_inferior ()
906 /* FIXME: only unpush on the last activation. */
907 /* Disengage the ROCm target_ops. */
908 unpush_target (&rocm_ops
);
910 beneath ()->mourn_inferior ();
914 rocm_target_ops::fetch_registers (struct regcache
*regcache
, int regno
)
916 struct gdbarch
*gdbarch
= regcache
->arch ();
917 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
919 /* delegate to the host routines when not on the device */
921 if (!rocm_is_amdgcn_gdbarch (gdbarch
))
923 beneath ()->fetch_registers (regcache
, regno
);
927 inferior
*inf
= find_inferior_ptid (regcache
->ptid ());
928 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (inf
);
929 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
931 gdb_byte raw
[AMDGCN_MAX_REGISTER_SIZE
];
933 amd_dbgapi_status_t status
= amd_dbgapi_read_register (
934 process_id
, wave_id
, tdep
->register_ids
[regno
], 0,
935 TYPE_LENGTH (register_type (gdbarch
, regno
)), raw
);
937 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
939 regcache
->raw_supply (regno
, raw
);
941 else if (status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_REGISTER_ID
)
943 warning (_ ("Couldn't read register %s (#%d)."),
944 gdbarch_register_name (gdbarch
, regno
), regno
);
949 rocm_target_ops::store_registers (struct regcache
*regcache
, int regno
)
951 struct gdbarch
*gdbarch
= regcache
->arch ();
952 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
953 gdb_byte raw
[AMDGCN_MAX_REGISTER_SIZE
];
955 if (!rocm_is_amdgcn_gdbarch (gdbarch
))
957 beneath ()->store_registers (regcache
, regno
);
961 inferior
*inf
= find_inferior_ptid (regcache
->ptid ());
962 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (inf
);
963 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
965 regcache
->raw_collect (regno
, &raw
);
967 amd_dbgapi_status_t status
= amd_dbgapi_write_register (
968 process_id
, wave_id
, tdep
->register_ids
[regno
], 0,
969 TYPE_LENGTH (register_type (gdbarch
, regno
)), raw
);
971 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
973 warning (_ ("Couldn't write register %s (#%d)."),
974 gdbarch_register_name (gdbarch
, regno
), regno
);
978 /* Fix breakpoints created with an address location while the
979 architecture was set to the host (could be fixed in core GDB). */
982 rocm_target_breakpoint_fixup (struct breakpoint
*b
)
984 if (b
->location
.get ()
985 && event_location_type (b
->location
.get ()) == ADDRESS_LOCATION
986 && gdbarch_bfd_arch_info (b
->loc
->gdbarch
)->arch
== bfd_arch_amdgcn
987 && gdbarch_bfd_arch_info (b
->gdbarch
)->arch
!= bfd_arch_amdgcn
)
989 b
->gdbarch
= b
->loc
->gdbarch
;
994 rocm_target_ops::thread_architecture (ptid_t ptid
)
996 static std::result_of
<decltype (&ptid_t::tid
) (ptid_t
)>::type last_tid
= 0;
997 static struct gdbarch
*cached_arch
= nullptr;
999 if (!ptid_is_gpu (ptid
))
1000 return beneath ()->thread_architecture (ptid
);
1002 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
1003 wave IDs are unique, and aren't reused. */
1004 if (ptid
.tid () == last_tid
)
1007 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1008 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
1009 amd_dbgapi_architecture_id_t architecture_id
;
1011 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
1012 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
1013 sizeof (architecture_id
), &architecture_id
)
1014 != AMD_DBGAPI_STATUS_SUCCESS
)
1015 error (_ ("Couldn't get architecture for wave_%ld"), ptid
.tid ());
1017 uint32_t elf_amdgpu_machine
;
1018 if (amd_dbgapi_architecture_get_info (
1019 architecture_id
, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE
,
1020 sizeof (elf_amdgpu_machine
), &elf_amdgpu_machine
)
1021 != AMD_DBGAPI_STATUS_SUCCESS
)
1022 error (_ ("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1023 architecture_id
.handle
);
1025 struct gdbarch_info info
;
1026 gdbarch_info_init (&info
);
1028 info
.bfd_arch_info
= bfd_lookup_arch (bfd_arch_amdgcn
, elf_amdgpu_machine
);
1029 info
.byte_order
= BFD_ENDIAN_LITTLE
;
1030 info
.osabi
= GDB_OSABI_AMDGPU_HSA
;
1032 last_tid
= ptid
.tid ();
1033 if (!(cached_arch
= gdbarch_find_by_info (info
)))
1034 error (_ ("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine
);
1040 rocm_target_ops::update_thread_list ()
1042 for (inferior
*inf
: all_inferiors ())
1044 amd_dbgapi_process_id_t process_id
;
1045 amd_dbgapi_wave_id_t
*wave_list
;
1048 process_id
= get_amd_dbgapi_process_id (inf
);
1049 if (process_id
.handle
== AMD_DBGAPI_PROCESS_NONE
.handle
)
1051 /* The inferior may not be attached yet. */
1055 amd_dbgapi_changed_t changed
;
1056 amd_dbgapi_status_t status
;
1058 = amd_dbgapi_wave_list (process_id
, &count
, &wave_list
, &changed
))
1059 != AMD_DBGAPI_STATUS_SUCCESS
)
1060 error (_ ("amd_dbgapi_wave_list failed (rc=%d)"), status
);
1062 if (changed
== AMD_DBGAPI_CHANGED_NO
)
1065 /* Create a set and free the wave list. */
1066 std::set
<std::result_of
<decltype (&ptid_t::tid
) (ptid_t
)>::type
> threads
;
1067 for (size_t i
= 0; i
< count
; ++i
)
1068 threads
.emplace (wave_list
[i
].handle
);
1071 /* Then prune the wave_ids that already have a thread_info. */
1072 for (thread_info
*tp
: inf
->non_exited_threads ())
1073 if (ptid_is_gpu (tp
->ptid
))
1074 threads
.erase (tp
->ptid
.tid ());
1076 /* The wave_ids that are left require a new thread_info. */
1077 for (auto &&tid
: threads
)
1079 ptid_t
wave_ptid (inf
->pid
, 1, tid
);
1080 /* FIXME: is this really needed?
1081 amd_dbgapi_wave_state_t state;
1083 if (amd_dbgapi_wave_get_info (
1084 process_id, get_amd_dbgapi_wave_id (wave_ptid),
1085 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state), &state)
1086 != AMD_DBGAPI_STATUS_SUCCESS)
1089 add_thread_silent (wave_ptid
);
1090 set_running (wave_ptid
, 1);
1091 set_executing (wave_ptid
, 1);
1095 /* Give the beneath target a chance to do extra processing. */
1096 this->beneath ()->update_thread_list ();
1100 rocm_target_solib_loaded (struct so_list
*solib
)
1102 /* Notify the amd_dbgapi that a shared library has been loaded. */
1103 for (auto &&value
: get_rocm_inferior_info ()->notify_solib_map
)
1104 /* TODO: If we want to support file name wildcards, change this code. */
1105 if (::strstr (solib
->so_original_name
, value
.second
.compare
.c_str ())
1106 && !value
.second
.is_loaded
)
1108 value
.second
.solib
= solib
;
1109 value
.second
.is_loaded
= true;
1111 amd_dbgapi_report_shared_library (
1112 get_amd_dbgapi_process_id (),
1113 amd_dbgapi_shared_library_id_t
{ value
.first
},
1114 AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
);
1119 rocm_target_solib_unloaded (struct so_list
*solib
)
1121 /* Notify the amd_dbgapi that a shared library will unload. */
1122 for (auto &&value
: get_rocm_inferior_info ()->notify_solib_map
)
1123 /* TODO: If we want to support file name wildcards, change this code. */
1124 if (::strstr (solib
->so_original_name
, value
.second
.compare
.c_str ())
1125 && value
.second
.is_loaded
)
1127 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
1129 amd_dbgapi_report_shared_library (
1130 info
->process_id
, amd_dbgapi_shared_library_id_t
{ value
.first
},
1131 AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED
);
1133 /* Delete breakpoints that were left inserted in this shared library.
1135 for (auto it
= info
->breakpoint_map
.begin ();
1136 it
!= info
->breakpoint_map
.end ();)
1137 if (solib_contains_address_p (solib
, it
->second
->loc
->address
))
1139 warning (_ ("breakpoint_%ld is still inserted after "
1140 "shared_library_%ld was unloaded"),
1141 it
->first
, value
.first
);
1142 delete_breakpoint (it
->second
);
1143 it
= info
->breakpoint_map
.erase (it
);
1148 value
.second
.solib
= nullptr;
1149 value
.second
.is_loaded
= false;
1154 rocm_target_inferior_created (struct target_ops
*target
, int from_tty
)
1156 struct inferior
*inf
= current_inferior ();
1157 auto *info
= get_rocm_inferior_info (inf
);
1158 amd_dbgapi_status_t status
;
1160 if (!target_can_async_p ())
1163 _ ("ROCm-GDB requires target-async, GPU debugging is disabled"));
1167 gdb_assert (info
->wave_stop_events
.empty ());
1169 status
= amd_dbgapi_process_attach (inf
, &info
->process_id
);
1171 if (status
== AMD_DBGAPI_STATUS_ERROR_VERSION_MISMATCH
)
1172 warning (_ ("The version of the kernel driver does not match the version "
1173 "required by the ROCm debugger library"));
1175 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1177 warning (_ ("Could not attach to process %d"), inf
->pid
);
1181 if (amd_dbgapi_process_get_info (info
->process_id
,
1182 AMD_DBGAPI_PROCESS_INFO_NOTIFIER
,
1183 sizeof (info
->notifier
), &info
->notifier
)
1184 != AMD_DBGAPI_STATUS_SUCCESS
)
1186 warning (_ ("Could not retrieve process %d's notifier"), inf
->pid
);
1187 amd_dbgapi_process_detach (info
->process_id
);
1191 /* We add a file handler for events returned by the debugger api. We'll use
1192 this handler to signal our async handler that events are available. */
1195 [] (int error
, gdb_client_data client_data
) {
1196 auto info_
= static_cast<struct rocm_inferior_info
*> (client_data
);
1199 /* Drain the notifier pipe. */
1203 ret
= read (info_
->notifier
, &buf
, 1);
1205 while (ret
>= 0 || (ret
== -1 && errno
== EINTR
));
1207 /* Signal our async handler. */
1212 /* Attaching to the inferior may have generated runtime events, process
1214 rocm_process_event_queue ();
1218 rocm_target_inferior_exit (struct inferior
*inf
)
1220 auto *info
= get_rocm_inferior_info (inf
);
1221 info
->has_exited
= true;
1223 amd_dbgapi_deactivated
.notify ();
1225 if (info
->notifier
!= -1)
1226 delete_file_handler (info
->notifier
);
1228 amd_dbgapi_process_detach (info
->process_id
);
1230 /* Delete the breakpoints that are still active. */
1231 for (auto &&value
: info
->breakpoint_map
)
1232 delete_breakpoint (value
.second
);
1234 rocm_inferior_data
.clear (inf
);
1237 static cli_style_option
warning_style ("rocm_warning", ui_file_style::RED
);
1238 static cli_style_option
info_style ("rocm_info", ui_file_style::GREEN
);
1239 static cli_style_option
verbose_style ("rocm_verbose", ui_file_style::BLUE
);
1241 static amd_dbgapi_callbacks_t dbgapi_callbacks
= {
1242 /* allocate_memory. */
1243 .allocate_memory
= malloc
,
1245 /* deallocate_memory. */
1246 .deallocate_memory
= free
,
1249 .get_os_pid
= [] (amd_dbgapi_client_process_id_t client_process_id
,
1250 pid_t
*pid
) -> amd_dbgapi_status_t
{
1251 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1252 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1254 if (info
->has_exited
)
1255 return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED
;
1258 return AMD_DBGAPI_STATUS_SUCCESS
;
1261 /* enable_notify_shared_library callback. */
1262 .enable_notify_shared_library
1263 = [] (amd_dbgapi_client_process_id_t client_process_id
,
1264 const char *library_name
, amd_dbgapi_shared_library_id_t library_id
,
1265 amd_dbgapi_shared_library_state_t
*library_state
)
1266 -> amd_dbgapi_status_t
{
1267 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1268 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1270 if (!library_name
|| !library_state
)
1271 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1273 if (info
->notify_solib_map
.find (library_id
.handle
)
1274 != info
->notify_solib_map
.end ())
1276 /* This library id is already registered. */
1277 return AMD_DBGAPI_STATUS_ERROR
;
1280 /* Check whether the library is already loaded. */
1281 bool is_loaded
= false;
1282 struct so_list
*solib
;
1283 for (solib
= inf
->pspace
->so_list
; solib
; solib
= solib
->next
)
1284 if (::strstr (solib
->so_original_name
, library_name
))
1290 /* Check that the library_name is valid. If must not be empty, and
1291 should not have wildcard characters. */
1292 if (*library_name
== '\0'
1293 || std::string (library_name
).find_first_of ("*?[]")
1294 != std::string::npos
)
1295 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1297 /* Add a new entry in the notify_solib_map. */
1298 if (!info
->notify_solib_map
1299 .emplace (std::piecewise_construct
,
1300 std::forward_as_tuple (library_id
.handle
),
1301 std::forward_as_tuple (rocm_notify_shared_library_info
{
1302 library_name
, solib
, is_loaded
}))
1304 return AMD_DBGAPI_STATUS_ERROR
;
1306 *library_state
= is_loaded
? AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
1307 : AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED
;
1309 return AMD_DBGAPI_STATUS_SUCCESS
;
1312 /* disable_notify_shared_library callback. */
1313 .disable_notify_shared_library
1314 = [] (amd_dbgapi_client_process_id_t client_process_id
,
1315 amd_dbgapi_shared_library_id_t library_id
) -> amd_dbgapi_status_t
{
1316 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1317 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1319 auto it
= info
->notify_solib_map
.find (library_id
.handle
);
1320 if (it
== info
->notify_solib_map
.end ())
1321 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID
;
1323 info
->notify_solib_map
.erase (it
);
1324 return AMD_DBGAPI_STATUS_SUCCESS
;
1327 /* get_symbol_address callback. */
1328 .get_symbol_address
=
1329 [] (amd_dbgapi_client_process_id_t client_process_id
,
1330 amd_dbgapi_shared_library_id_t library_id
, const char *symbol_name
,
1331 amd_dbgapi_global_address_t
*address
) {
1332 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1333 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1335 auto it
= info
->notify_solib_map
.find (library_id
.handle
);
1336 if (it
== info
->notify_solib_map
.end ())
1337 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID
;
1339 struct so_list
*solib
= it
->second
.solib
;
1341 return AMD_DBGAPI_STATUS_ERROR_LIBRARY_NOT_LOADED
;
1343 solib_read_symbols (solib
, 0);
1344 gdb_assert (solib
->objfile
);
1346 struct bound_minimal_symbol msymbol
1347 = lookup_minimal_symbol (symbol_name
, NULL
, solib
->objfile
);
1349 if (!msymbol
.minsym
|| BMSYMBOL_VALUE_ADDRESS (msymbol
) == 0)
1350 return AMD_DBGAPI_STATUS_ERROR_SYMBOL_NOT_FOUND
;
1352 *address
= BMSYMBOL_VALUE_ADDRESS (msymbol
);
1353 return AMD_DBGAPI_STATUS_SUCCESS
;
1356 /* set_breakpoint callback. */
1358 [] (amd_dbgapi_client_process_id_t client_process_id
,
1359 amd_dbgapi_shared_library_id_t shared_library_id
,
1360 amd_dbgapi_global_address_t address
,
1361 amd_dbgapi_breakpoint_id_t breakpoint_id
) {
1362 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1363 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1365 /* Initialize the breakpoint ops lazily since we depend on
1366 bkpt_breakpoint_ops and we can't control the order in which
1367 initializers are called. */
1368 if (rocm_breakpoint_ops
.check_status
== NULL
)
1370 rocm_breakpoint_ops
= bkpt_breakpoint_ops
;
1371 rocm_breakpoint_ops
.check_status
= rocm_breakpoint_check_status
;
1372 rocm_breakpoint_ops
.re_set
= rocm_breakpoint_re_set
;
1375 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1376 if (it
!= info
->breakpoint_map
.end ())
1377 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1379 /* Create a new breakpoint. */
1380 struct obj_section
*section
= find_pc_section (address
);
1381 if (!section
|| !section
->objfile
)
1382 return AMD_DBGAPI_STATUS_ERROR
;
1384 event_location_up location
1385 = new_address_location (address
, nullptr, 0);
1386 if (!create_breakpoint (
1387 get_objfile_arch (section
->objfile
), location
.get (),
1388 /*cond_string*/ NULL
, /*thread*/ -1, /*extra_sring*/ NULL
,
1389 /*parse_extra*/ 0, /*tempflag*/ 0, /*bptype*/ bp_breakpoint
,
1390 /*ignore_count*/ 0, /*pending_break*/ AUTO_BOOLEAN_FALSE
,
1391 /*ops*/ &rocm_breakpoint_ops
, /*from_tty*/ 0,
1392 /*enabled*/ 1, /*internal*/ 1, /*flags*/ 0))
1393 return AMD_DBGAPI_STATUS_ERROR
;
1395 /* Find our breakpoint in the breakpoint list. */
1396 auto bp_loc
= std::make_pair (inf
->aspace
, address
);
1397 auto bp
= breakpoint_find_if (
1398 [] (struct breakpoint
*b
, void *data
) {
1399 auto *arg
= static_cast<decltype (&bp_loc
)> (data
);
1400 if (b
->ops
== &rocm_breakpoint_ops
&& b
->loc
1401 && b
->loc
->pspace
->aspace
== arg
->first
1402 && b
->loc
->address
== arg
->second
)
1406 reinterpret_cast<void *> (&bp_loc
));
1409 error (_ ("Could not find breakpoint"));
1411 info
->breakpoint_map
.emplace (breakpoint_id
.handle
, bp
);
1412 return AMD_DBGAPI_STATUS_SUCCESS
;
1415 /* remove_breakpoint callback. */
1416 .remove_breakpoint
=
1417 [] (amd_dbgapi_client_process_id_t client_process_id
,
1418 amd_dbgapi_breakpoint_id_t breakpoint_id
) {
1419 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1420 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1422 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1423 if (it
== info
->breakpoint_map
.end ())
1424 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1426 delete_breakpoint (it
->second
);
1427 info
->breakpoint_map
.erase (it
);
1429 return AMD_DBGAPI_STATUS_SUCCESS
;
1432 /* set_breakpoint_state callback. */
1433 .set_breakpoint_state
=
1434 [] (amd_dbgapi_client_process_id_t client_process_id
,
1435 amd_dbgapi_breakpoint_id_t breakpoint_id
,
1436 amd_dbgapi_breakpoint_state_t breakpoint_state
) {
1437 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1438 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1440 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1441 if (it
== info
->breakpoint_map
.end ())
1442 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1444 if (breakpoint_state
== AMD_DBGAPI_BREAKPOINT_STATE_ENABLE
)
1445 it
->second
->enable_state
= bp_enabled
;
1446 else if (breakpoint_state
== AMD_DBGAPI_BREAKPOINT_STATE_DISABLE
)
1447 it
->second
->enable_state
= bp_disabled
;
1449 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1451 return AMD_DBGAPI_STATUS_SUCCESS
;
1455 = [] (amd_dbgapi_log_level_t level
, const char *message
) -> void {
1456 gdb::optional
<target_terminal::scoped_restore_terminal_state
> tstate
;
1458 if (level
> get_debug_amd_dbgapi_log_level ())
1461 if (target_supports_terminal_ours ())
1464 target_terminal::ours_for_output ();
1467 if (filtered_printing_initialized ())
1470 struct ui_file
*out_file
1471 = (level
>= AMD_DBGAPI_LOG_LEVEL_INFO
) ? gdb_stdlog
: gdb_stderr
;
1475 case AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
:
1476 fputs_unfiltered ("[amd-dbgapi]: ", out_file
);
1478 case AMD_DBGAPI_LOG_LEVEL_WARNING
:
1479 fputs_styled ("[amd-dbgapi]: ", warning_style
.style (), out_file
);
1481 case AMD_DBGAPI_LOG_LEVEL_INFO
:
1482 fputs_styled ("[amd-dbgapi]: ", info_style
.style (), out_file
);
1484 case AMD_DBGAPI_LOG_LEVEL_VERBOSE
:
1485 fputs_styled ("[amd-dbgapi]: ", verbose_style
.style (), out_file
);
1489 fputs_unfiltered (message
, out_file
);
1490 fputs_unfiltered ("\n", out_file
);
1494 /* Implementation of `_wave_id' variable. */
1496 static struct value
*
1497 rocm_wave_id_make_value (struct gdbarch
*gdbarch
, struct internalvar
*var
,
1500 if (ptid_is_gpu (inferior_ptid
))
1502 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1503 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
1504 uint32_t group_ids
[3], wave_in_group
;
1506 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
1507 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD
,
1508 sizeof (group_ids
), &group_ids
)
1509 == AMD_DBGAPI_STATUS_SUCCESS
1510 && amd_dbgapi_wave_get_info (
1511 process_id
, wave_id
,
1512 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP
,
1513 sizeof (wave_in_group
), &wave_in_group
)
1514 == AMD_DBGAPI_STATUS_SUCCESS
)
1516 std::string wave_id_str
1517 = string_printf ("(%d,%d,%d)/%d", group_ids
[2], group_ids
[1],
1518 group_ids
[0], wave_in_group
);
1520 return value_cstring (wave_id_str
.data (), wave_id_str
.length () + 1,
1521 builtin_type (gdbarch
)->builtin_char
);
1525 return allocate_value (builtin_type (gdbarch
)->builtin_void
);
1528 static const struct internalvar_funcs rocm_wave_id_funcs
1529 = { rocm_wave_id_make_value
, NULL
, NULL
};
1531 /* List of set/show debug amd_dbgapi commands. */
1532 struct cmd_list_element
*set_debug_amd_dbgapi_list
;
1533 struct cmd_list_element
*show_debug_amd_dbgapi_list
;
1536 set_debug_amd_dbgapi (const char *arg
, int from_tty
)
1538 help_list (set_debug_amd_dbgapi_list
, "set debug amd-dbgapi ",
1539 (enum command_class
) - 1, gdb_stdout
);
1543 show_debug_amd_dbgapi (const char *args
, int from_tty
)
1545 cmd_show_list (show_debug_amd_dbgapi_list
, from_tty
, "");
1548 constexpr char amd_dbgapi_log_level_off
[] = "off";
1549 constexpr char amd_dbgapi_log_level_error
[] = "error";
1550 constexpr char amd_dbgapi_log_level_warning
[] = "warning";
1551 constexpr char amd_dbgapi_log_level_info
[] = "info";
1552 constexpr char amd_dbgapi_log_level_verbose
[] = "verbose";
1554 constexpr const char *debug_amd_dbgapi_log_level_enums
[]
1555 = { [AMD_DBGAPI_LOG_LEVEL_NONE
] = amd_dbgapi_log_level_off
,
1556 [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
] = amd_dbgapi_log_level_error
,
1557 [AMD_DBGAPI_LOG_LEVEL_WARNING
] = amd_dbgapi_log_level_warning
,
1558 [AMD_DBGAPI_LOG_LEVEL_INFO
] = amd_dbgapi_log_level_info
,
1559 [AMD_DBGAPI_LOG_LEVEL_VERBOSE
] = amd_dbgapi_log_level_verbose
,
1562 static const char *debug_amd_dbgapi_log_level
= amd_dbgapi_log_level_error
;
1564 static amd_dbgapi_log_level_t
1565 get_debug_amd_dbgapi_log_level ()
1568 for (pos
= 0; debug_amd_dbgapi_log_level_enums
[pos
]; ++pos
)
1569 if (debug_amd_dbgapi_log_level
== debug_amd_dbgapi_log_level_enums
[pos
])
1572 gdb_assert (debug_amd_dbgapi_log_level_enums
[pos
]);
1573 return static_cast<amd_dbgapi_log_level_t
> (pos
);
1577 set_debug_amd_dbgapi_log_level (const char *args
, int from_tty
,
1578 struct cmd_list_element
*c
)
1580 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1584 show_debug_amd_dbgapi_log_level (struct ui_file
*file
, int from_tty
,
1585 struct cmd_list_element
*c
,
1588 fprintf_filtered (file
, _ ("The amd-dbgapi log level is %s.\n"), value
);
1592 info_agents_command (const char *args
, int from_tty
)
1594 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1595 struct ui_out
*uiout
= current_uiout
;
1596 amd_dbgapi_status_t status
;
1598 amd_dbgapi_agent_id_t
*agent_list
;
1601 if (process_id
.handle
!= AMD_DBGAPI_PROCESS_NONE
.handle
1603 = amd_dbgapi_agent_list (process_id
, &count
, &agent_list
, nullptr))
1604 != AMD_DBGAPI_STATUS_SUCCESS
)
1605 error (_ ("amd_dbgapi_agent_list failed (rc=%d)"), status
);
1607 if (!count
&& !uiout
->is_mi_like_p ())
1609 uiout
->field_string (NULL
,
1610 _ ("No agents are currently active.\n"));
1614 /* Calculate the maximum size needed to print the agents names. */
1615 std::vector
<std::string
> agent_names (count
);
1617 size_t max_name_len
= 0;
1618 for (size_t i
= 0; i
< count
; ++i
)
1622 if ((status
= amd_dbgapi_agent_get_info (
1623 process_id
, agent_list
[i
], AMD_DBGAPI_AGENT_INFO_NAME
,
1624 sizeof (agent_name
), &agent_name
))
1625 != AMD_DBGAPI_STATUS_SUCCESS
)
1627 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID
)
1628 agent_names
[i
] = "N/A";
1630 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status
);
1634 agent_names
[i
] = agent_name
;
1638 max_name_len
= std::max (max_name_len
, agent_names
[i
].size ());
1642 ui_out_emit_table
table_emmitter (uiout
, 7, count
, "InfoRocmDevicesTable");
1644 uiout
->table_header (2, ui_left
, "agent_id", "Id");
1645 uiout
->table_header (8, ui_left
, "location_id", "PCI Slot");
1646 uiout
->table_header (std::max (11ul, max_name_len
), ui_left
, "name",
1648 uiout
->table_header (14, ui_left
, "num_se", "Shader Engines");
1649 uiout
->table_header (13, ui_left
, "num_cu", "Compute Units");
1650 uiout
->table_header (7, ui_left
, "simd", "SIMD/CU");
1651 uiout
->table_header (15, ui_left
, "waves", "Wavefronts/SIMD");
1652 uiout
->table_body ();
1655 for (size_t i
= 0; i
< count
; ++i
)
1657 ui_out_emit_tuple
tuple_emitter (uiout
, "InfoRocmDevicesRow");
1660 uiout
->field_signed ("agent_id", agent_list
[i
].handle
);
1663 uint32_t location_id
;
1664 if ((status
= amd_dbgapi_agent_get_info (
1665 process_id
, agent_list
[i
], AMD_DBGAPI_AGENT_INFO_PCIE_SLOT
,
1666 sizeof (location_id
), &location_id
))
1667 != AMD_DBGAPI_STATUS_SUCCESS
)
1669 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID
)
1670 uiout
->field_string ("location_id", "N/A");
1672 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status
);
1675 uiout
->field_string (
1677 string_printf ("%02x:%02x.%d", (location_id
>> 8) & 0xFF,
1678 (location_id
>> 3) & 0x1F, location_id
& 0x7));
1681 uiout
->field_string ("name", agent_names
[i
]);
1683 /* num_se, num_cu, simd, waves */
1685 #define UIOUT_FIELD_INT(name, query) \
1687 if ((status = amd_dbgapi_agent_get_info (process_id, agent_list[i], query, \
1688 sizeof (name), &name)) \
1689 != AMD_DBGAPI_STATUS_SUCCESS) \
1691 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID) \
1692 uiout->field_string (#name, "N/A"); \
1694 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status); \
1697 uiout->field_signed (#name, name);
1699 UIOUT_FIELD_INT (num_se
, AMD_DBGAPI_AGENT_INFO_SHADER_ENGINE_COUNT
);
1700 UIOUT_FIELD_INT (num_cu
, AMD_DBGAPI_AGENT_INFO_COMPUTE_UNIT_COUNT
);
1701 UIOUT_FIELD_INT (simd
, AMD_DBGAPI_AGENT_INFO_NUM_SIMD_PER_COMPUTE_UNIT
);
1702 UIOUT_FIELD_INT (waves
, AMD_DBGAPI_AGENT_INFO_MAX_WAVES_PER_SIMD
);
1704 #undef UIOUT_FIELD_INT
1710 gdb_flush (gdb_stdout
);
1713 /* -Wmissing-prototypes */
1714 extern initialize_file_ftype _initialize_rocm_tdep
;
1717 _initialize_rocm_tdep (void)
1719 /* Make sure the loaded debugger library version is greater than or equal to
1720 the one used to build ROCgdb. */
1721 uint32_t major
, minor
, patch
;
1722 amd_dbgapi_get_version (&major
, &minor
, &patch
);
1723 if (major
!= AMD_DBGAPI_VERSION_MAJOR
|| minor
< AMD_DBGAPI_VERSION_MINOR
)
1725 _ ("amd-dbgapi library version mismatch, got %d.%d.%d, need %d.%d+"),
1726 major
, minor
, patch
, AMD_DBGAPI_VERSION_MAJOR
,
1727 AMD_DBGAPI_VERSION_MINOR
);
1729 /* Initialize the ROCm Debug API. */
1730 amd_dbgapi_status_t status
= amd_dbgapi_initialize (&dbgapi_callbacks
);
1731 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1732 error (_ ("amd-dbgapi failed to initialize (rc=%d)"), status
);
1734 /* Set the initial log level. */
1735 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1737 /* Install observers. */
1738 gdb::observers::breakpoint_created
.attach (rocm_target_breakpoint_fixup
);
1739 gdb::observers::solib_loaded
.attach (rocm_target_solib_loaded
);
1740 gdb::observers::solib_unloaded
.attach (rocm_target_solib_unloaded
);
1741 gdb::observers::inferior_created
.attach (rocm_target_inferior_created
);
1742 gdb::observers::inferior_exit
.attach (rocm_target_inferior_exit
);
1744 amd_dbgapi_activated
.attach (rocm_target_dbgapi_activated
);
1745 amd_dbgapi_deactivated
.attach (rocm_target_dbgapi_deactivated
);
1747 create_internalvar_type_lazy ("_wave_id", &rocm_wave_id_funcs
, NULL
);
1750 "amd-dbgapi", no_class
, set_debug_amd_dbgapi
,
1751 _ ("Generic command for setting amd-dbgapi debugging flags"),
1752 &set_debug_amd_dbgapi_list
, "set debug amd-dbgapi ", 0, &setdebuglist
);
1755 "amd-dbgapi", no_class
, show_debug_amd_dbgapi
,
1756 _ ("Generic command for showing amd-dbgapi debugging flags"),
1757 &show_debug_amd_dbgapi_list
, "show debug amd-dbgapi ", 0,
1760 add_setshow_enum_cmd (
1761 "log-level", class_maintenance
, debug_amd_dbgapi_log_level_enums
,
1762 &debug_amd_dbgapi_log_level
, _ ("Set the amd-dbgapi log level."),
1763 _ ("Show the amd-dbgapi log level."),
1764 _ ("off == no logging is enabled\n"
1765 "error == fatal errors are reported\n"
1766 "warning == fatal errors and warnings are reported\n"
1767 "info == fatal errors, warnings, and info messages are reported\n"
1768 "verbose == all messages are reported"),
1769 set_debug_amd_dbgapi_log_level
, show_debug_amd_dbgapi_log_level
,
1770 &set_debug_amd_dbgapi_list
, &show_debug_amd_dbgapi_list
);
1772 add_cmd ("agents", class_info
, info_agents_command
,
1773 _ ("Info about currently active agents."), &infolist
);