1 /* Target-dependent code for ROCm.
3 Copyright (C) 2019 Free Software Foundation, Inc.
4 Copyright (C) 2019 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
;
81 /* The amd_dbgapi_notifier_t for this inferior. */
82 amd_dbgapi_notifier_t notifier
;
84 /* True if commit_resume should all-start the GPU queues. */
85 bool commit_resume_all_start
;
87 std::unordered_map
<decltype (amd_dbgapi_breakpoint_id_t::handle
),
91 /* List of pending events the rocm target retrieved from the dbgapi. */
92 std::list
<std::pair
<amd_dbgapi_wave_id_t
, amd_dbgapi_wave_stop_reason_t
>>
95 /* Map of rocm_notify_shared_library_info's for libraries that have been
96 registered to receive notifications when loading/unloading. */
97 std::unordered_map
<decltype (amd_dbgapi_shared_library_id_t::handle
),
98 struct rocm_notify_shared_library_info
>
102 static amd_dbgapi_event_id_t
103 rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind
104 = AMD_DBGAPI_EVENT_KIND_NONE
);
106 /* Return the inferior's rocm_inferior_info struct. */
107 static struct rocm_inferior_info
*
108 get_rocm_inferior_info (struct inferior
*inferior
= nullptr);
110 static const target_info rocm_ops_info
111 = { "rocm", N_ ("ROCm GPU debugging support"),
112 N_ ("ROCm GPU debugging support") };
114 static amd_dbgapi_log_level_t
get_debug_amd_dbgapi_log_level ();
116 struct rocm_target_ops final
: public target_ops
119 info () const override
121 return rocm_ops_info
;
124 stratum () const override
129 void mourn_inferior () override
;
131 void async (int enable
) override
;
133 ptid_t
wait (ptid_t
, struct target_waitstatus
*, int) override
;
134 void resume (ptid_t
, int, enum gdb_signal
) override
;
135 void commit_resume () override
;
136 void stop (ptid_t ptid
) override
;
138 void fetch_registers (struct regcache
*, int) override
;
139 void store_registers (struct regcache
*, int) override
;
141 void update_thread_list () override
;
143 struct gdbarch
*thread_architecture (ptid_t
) override
;
145 std::string
pid_to_str (ptid_t ptid
) override
;
147 const char *thread_name (thread_info
*tp
) override
;
149 const char *extra_thread_info (thread_info
*tp
) override
;
151 bool thread_alive (ptid_t ptid
) override
;
153 enum target_xfer_status
xfer_partial (enum target_object object
,
154 const char *annex
, gdb_byte
*readbuf
,
155 const gdb_byte
*writebuf
,
156 ULONGEST offset
, ULONGEST len
,
157 ULONGEST
*xfered_len
) override
;
160 stopped_by_watchpoint () override
162 return !ptid_is_gpu (inferior_ptid
)
163 && beneath ()->stopped_by_watchpoint ();
167 stopped_data_address (CORE_ADDR
*addr_p
) override
169 return !ptid_is_gpu (inferior_ptid
)
170 && beneath ()->stopped_data_address (addr_p
);
174 supports_stopped_by_sw_breakpoint () override
179 bool stopped_by_sw_breakpoint () override
;
182 stopped_by_hw_breakpoint () override
184 return !ptid_is_gpu (inferior_ptid
)
185 && beneath ()->stopped_by_hw_breakpoint ();
189 /* ROCm's target vector. */
190 static struct rocm_target_ops rocm_ops
;
192 /* ROCm breakpoint ops. */
193 static struct breakpoint_ops rocm_breakpoint_ops
;
195 /* Per-inferior data key. */
196 static const struct inferior_key
<rocm_inferior_info
> rocm_inferior_data
;
198 /* The read/write ends of the pipe registered as waitable file in the
200 static int rocm_event_pipe
[2] = { -1, -1 };
202 /* Flush the event pipe. */
205 async_file_flush (void)
212 ret
= read (rocm_event_pipe
[0], &buf
, 1);
214 while (ret
>= 0 || (ret
== -1 && errno
== EINTR
));
217 /* Put something (anything, doesn't matter what, or how much) in event
218 pipe, so that the select/poll in the event-loop realizes we have
219 something to process. */
222 async_file_mark (void)
226 /* It doesn't really matter what the pipe contains, as long we end
227 up with something in it. Might as well flush the previous
233 ret
= write (rocm_event_pipe
[1], "+", 1);
235 while (ret
== -1 && errno
== EINTR
);
237 /* Ignore EAGAIN. If the pipe is full, the event loop will already
238 be awakened anyway. */
241 /* Fetch the rocm_inferior_info data for the given inferior. */
243 static struct rocm_inferior_info
*
244 get_rocm_inferior_info (struct inferior
*inferior
)
247 inferior
= current_inferior ();
249 struct rocm_inferior_info
*info
= rocm_inferior_data
.get (inferior
);
252 info
= rocm_inferior_data
.emplace (inferior
);
257 /* Fetch the amd_dbgapi_process_id for the given inferior. */
259 amd_dbgapi_process_id_t
260 get_amd_dbgapi_process_id (struct inferior
*inferior
)
262 return get_rocm_inferior_info (inferior
)->process_id
;
266 rocm_breakpoint_check_status (struct bpstats
*bs
)
268 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
269 amd_dbgapi_process_id_t process_id
= info
->process_id
;
270 amd_dbgapi_status_t status
;
273 bs
->print_it
= print_it_noop
;
275 /* Find the address the breakpoint is set at. */
276 auto it
= std::find_if (
277 info
->breakpoint_map
.begin (), info
->breakpoint_map
.end (),
278 [=] (const decltype (info
->breakpoint_map
)::value_type
&value
) {
279 return value
.second
== bs
->breakpoint_at
;
282 if (it
== info
->breakpoint_map
.end ())
283 error (_ ("Could not find breakpoint_id for breakpoint at %#lx"),
284 bs
->bp_location_at
->address
);
286 amd_dbgapi_breakpoint_id_t breakpoint_id
{ it
->first
};
287 amd_dbgapi_breakpoint_action_t action
;
289 status
= amd_dbgapi_report_breakpoint_hit (process_id
, breakpoint_id
,
290 inferior_thread (), &action
);
292 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
293 error (_ ("amd_dbgapi_report_breakpoint_hit failed: breakpoint_%ld "
295 breakpoint_id
.handle
, bs
->bp_location_at
->address
, status
);
297 if (action
== AMD_DBGAPI_BREAKPOINT_ACTION_RESUME
)
300 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
301 a breakpoint resume event for this breakpoint_id is seen. */
303 amd_dbgapi_event_id_t resume_event_id
304 = rocm_process_event_queue (AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
);
306 /* We should always get a breakpoint_resume event after processing all
307 events generated by reporting the breakpoint was hit. */
308 gdb_assert (resume_event_id
.handle
!= AMD_DBGAPI_EVENT_NONE
.handle
);
310 amd_dbgapi_breakpoint_id_t resume_breakpoint_id
;
311 status
= amd_dbgapi_event_get_info (
312 process_id
, resume_event_id
, AMD_DBGAPI_EVENT_INFO_BREAKPOINT
,
313 sizeof (resume_breakpoint_id
), &resume_breakpoint_id
);
315 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
316 error (_ ("amd_dbgapi_event_get_info failed (rc=%d)"), status
);
318 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint]
319 sequences cannot interleave, so this breakpoint resume event must be
320 for our breakpoint_id. */
321 if (resume_breakpoint_id
.handle
!= breakpoint_id
.handle
)
322 error (_ ("breakpoint resume event is not for this breakpoint. "
323 "Expected breakpoint_%ld, got breakpoint_%ld"),
324 breakpoint_id
.handle
, resume_breakpoint_id
.handle
);
326 amd_dbgapi_event_processed (process_id
, resume_event_id
);
330 rocm_target_dbgapi_activated ()
332 /* FIXME: only push on the first activation. */
333 /* Engage the ROCm target_ops and so_ops. */
334 push_target (&rocm_ops
);
338 rocm_target_dbgapi_deactivated ()
340 /* FIXME: only unpush on the last activation. */
341 /* Disengage the ROCm target_ops. */
342 unpush_target (&rocm_ops
);
346 rocm_target_ops::thread_alive (ptid_t ptid
)
348 if (!ptid_is_gpu (ptid
))
349 return beneath ()->thread_alive (ptid
);
351 /* Check that the wave_id is valid. */
353 inferior
*inf
= find_inferior_ptid (ptid
);
357 amd_dbgapi_wave_state_t state
;
358 return amd_dbgapi_wave_get_info (
359 get_amd_dbgapi_process_id (inf
), get_amd_dbgapi_wave_id (ptid
),
360 AMD_DBGAPI_WAVE_INFO_STATE
, sizeof (state
), &state
)
361 == AMD_DBGAPI_STATUS_SUCCESS
;
365 rocm_target_ops::thread_name (thread_info
*tp
)
367 if (!ptid_is_gpu (tp
->ptid
))
368 return beneath ()->thread_name (tp
);
370 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (tp
->inf
);
371 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (tp
->ptid
);
372 amd_dbgapi_dispatch_id_t dispatch_id
;
373 amd_dbgapi_global_address_t kernel_addr
;
375 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
376 AMD_DBGAPI_WAVE_INFO_DISPATCH
,
377 sizeof (dispatch_id
), &dispatch_id
)
378 != AMD_DBGAPI_STATUS_SUCCESS
379 || amd_dbgapi_dispatch_get_info (
380 process_id
, dispatch_id
,
381 AMD_DBGAPI_DISPATCH_INFO_KERNEL_ENTRY_ADDRESS
,
382 sizeof (kernel_addr
), &kernel_addr
)
383 != AMD_DBGAPI_STATUS_SUCCESS
)
386 struct bound_minimal_symbol msymbol
387 = lookup_minimal_symbol_by_pc_section (kernel_addr
, nullptr);
389 if (msymbol
.minsym
!= NULL
)
391 static char buf
[256];
394 xsnprintf (buf
, sizeof (buf
), "%s", msymbol
.minsym
->print_name ());
396 /* Strip the arguments from the demangled function name. */
397 if ((endp
= strchr (buf
, '(')))
407 rocm_target_ops::pid_to_str (ptid_t ptid
)
409 if (!ptid_is_gpu (ptid
))
411 return beneath ()->pid_to_str (ptid
);
414 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
415 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
416 amd_dbgapi_dispatch_id_t dispatch_id
;
417 uint32_t group_ids
[3], wave_in_group
;
419 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
420 AMD_DBGAPI_WAVE_INFO_DISPATCH
,
421 sizeof (dispatch_id
), &dispatch_id
)
422 != AMD_DBGAPI_STATUS_SUCCESS
423 || amd_dbgapi_wave_get_info (process_id
, wave_id
,
424 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD
,
425 sizeof (group_ids
), &group_ids
)
426 != AMD_DBGAPI_STATUS_SUCCESS
427 || amd_dbgapi_wave_get_info (
429 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP
,
430 sizeof (wave_in_group
), &wave_in_group
)
431 != AMD_DBGAPI_STATUS_SUCCESS
)
432 return std::string ("ROCm Thread");
434 return string_printf ("ROCm Thread %ld.%ld (%d,%d,%d)/%d",
435 dispatch_id
.handle
, wave_id
.handle
, group_ids
[2],
436 group_ids
[1], group_ids
[0], wave_in_group
);
440 rocm_target_ops::extra_thread_info (thread_info
*tp
)
442 if (!ptid_is_gpu (tp
->ptid
))
443 beneath ()->extra_thread_info (tp
);
448 enum target_xfer_status
449 rocm_target_ops::xfer_partial (enum target_object object
, const char *annex
,
450 gdb_byte
*readbuf
, const gdb_byte
*writebuf
,
451 ULONGEST offset
, ULONGEST requested_len
,
452 ULONGEST
*xfered_len
)
454 gdb::optional
<scoped_restore_current_thread
> maybe_restore_thread
;
456 if (ptid_is_gpu (inferior_ptid
))
458 gdb_assert (requested_len
&& xfered_len
&& "checking invariants");
460 if (object
!= TARGET_OBJECT_MEMORY
)
461 return TARGET_XFER_E_IO
;
463 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
464 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
466 amd_dbgapi_architecture_id_t architecture_id
;
467 amd_dbgapi_address_space_id_t address_space_id
;
469 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
470 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
471 sizeof (architecture_id
), &architecture_id
)
472 != AMD_DBGAPI_STATUS_SUCCESS
473 || amd_dbgapi_architecture_get_info (
475 AMD_DBGAPI_ARCHITECTURE_INFO_DEFAULT_GLOBAL_ADDRESS_SPACE
,
476 sizeof (address_space_id
), &address_space_id
)
477 != AMD_DBGAPI_STATUS_SUCCESS
)
478 error (_ ("Couldn't get default global address space"));
480 size_t len
= requested_len
;
481 amd_dbgapi_status_t status
;
484 status
= amd_dbgapi_read_memory (
485 process_id
, wave_id
, 0, address_space_id
, offset
, &len
, readbuf
);
487 status
= amd_dbgapi_write_memory (
488 process_id
, wave_id
, 0, address_space_id
, offset
, &len
, writebuf
);
490 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
492 if (status
!= AMD_DBGAPI_STATUS_ERROR_MEMORY_ACCESS
)
493 error (_ ("amd_dbgapi_%s_memory failed (rc=%d"),
494 readbuf
? "read" : "write", status
);
495 return TARGET_XFER_EOF
;
499 return TARGET_XFER_OK
;
502 return beneath ()->xfer_partial (object
, annex
, readbuf
, writebuf
, offset
,
503 requested_len
, xfered_len
);
507 rocm_target_ops::resume (ptid_t ptid
, int step
, enum gdb_signal signo
)
509 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
514 "\e[1;34minfrun: rocm_target_ops::resume ([%d,%ld,%ld])\e[0m\n",
515 ptid
.pid (), ptid
.lwp (), ptid
.tid ());
517 /* Check if the thread focus is on the GPU device. */
518 if (ptid
== minus_one_ptid
|| !ptid_is_gpu (ptid
))
520 beneath ()->resume (ptid
, step
, signo
);
521 if (ptid
!= minus_one_ptid
)
525 /* A specific PTID means `step only this process id'. */
526 bool resume_one
= ptid
!= minus_one_ptid
&& !ptid
.is_pid ();
527 gdb_assert (resume_one
|| !step
);
530 error (_ ("internal error - unimplemented "));
532 amd_dbgapi_process_set_progress (info
->process_id
,
533 AMD_DBGAPI_PROGRESS_NO_FORWARD
);
535 amd_dbgapi_status_t status
= amd_dbgapi_wave_resume (
536 info
->process_id
, get_amd_dbgapi_wave_id (ptid
),
537 step
? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
538 : AMD_DBGAPI_RESUME_MODE_NORMAL
);
539 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
540 warning (_ ("Could not resume %s (rc=%d)"),
541 target_pid_to_str (ptid
).c_str (), status
);
543 info
->commit_resume_all_start
= true;
547 rocm_target_ops::commit_resume ()
549 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
554 "\e[1;34minfrun: rocm_target_ops::commit_resume ()\e[0m\n");
556 beneath ()->commit_resume ();
558 if (info
->commit_resume_all_start
)
560 amd_dbgapi_process_set_progress (info
->process_id
,
561 AMD_DBGAPI_PROGRESS_NORMAL
);
562 info
->commit_resume_all_start
= false;
565 if (target_can_async_p ())
570 rocm_target_stop_one_wave (ptid_t ptid
)
572 amd_dbgapi_status_t status
;
574 status
= amd_dbgapi_wave_stop (get_amd_dbgapi_process_id (),
575 get_amd_dbgapi_wave_id (ptid
));
577 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
579 /* the wave must have exited, set the thread status to reflect that. */
580 auto *tp
= find_thread_ptid (ptid
);
583 tp
->state
= THREAD_EXITED
;
585 else if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
586 warning (_ ("Could not stop %s (rc=%d)"),
587 target_pid_to_str (ptid
).c_str (), status
);
591 rocm_target_ops::stop (ptid_t ptid
)
596 "\e[1;34minfrun: rocm_target_ops::stop ([%d,%ld,%ld])\e[0m\n",
597 ptid
.pid (), ptid
.lwp (), ptid
.tid ());
599 if (ptid
== minus_one_ptid
|| !ptid_is_gpu (ptid
))
601 beneath ()->stop (ptid
);
602 if (ptid
!= minus_one_ptid
)
606 if (ptid
== minus_one_ptid
)
607 error (_ ("internal error - unimplemented "));
609 rocm_target_stop_one_wave (ptid
);
613 handle_target_event (int error
, gdb_client_data client_data
)
615 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
616 amd_dbgapi_process_id_t process_id
= info
->process_id
;
618 amd_dbgapi_process_set_progress (process_id
, AMD_DBGAPI_PROGRESS_NO_FORWARD
);
620 /* Flush the async file first. */
621 if (target_is_async_p ())
624 rocm_process_event_queue ();
626 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
627 we can keep the process in progress_no_forward mode. The infrun loop
628 will enable forward progress when a thread is resumed. */
629 if (non_stop
|| info
->wave_stop_events
.empty ())
630 amd_dbgapi_process_set_progress (process_id
, AMD_DBGAPI_PROGRESS_NORMAL
);
632 if (!info
->wave_stop_events
.empty ())
633 inferior_event_handler (INF_REG_EVENT
, nullptr);
637 rocm_target_ops::async (int enable
)
639 beneath ()->async (enable
);
643 if (rocm_event_pipe
[0] != -1)
646 if (gdb_pipe_cloexec (rocm_event_pipe
) == -1)
647 internal_error (__FILE__
, __LINE__
, "creating event pipe failed.");
649 ::fcntl (rocm_event_pipe
[0], F_SETFL
, O_NONBLOCK
);
650 ::fcntl (rocm_event_pipe
[1], F_SETFL
, O_NONBLOCK
);
652 add_file_handler (rocm_event_pipe
[0], handle_target_event
, nullptr);
654 /* There may be pending events to handle. Tell the event loop
660 delete_file_handler (rocm_event_pipe
[0]);
662 if (rocm_event_pipe
[0] == -1)
665 ::close (rocm_event_pipe
[0]);
666 ::close (rocm_event_pipe
[1]);
667 rocm_event_pipe
[0] = -1;
668 rocm_event_pipe
[1] = -1;
673 rocm_process_one_event (amd_dbgapi_event_id_t event_id
,
674 amd_dbgapi_event_kind_t event_kind
)
676 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
677 amd_dbgapi_process_id_t process_id
= info
->process_id
;
678 amd_dbgapi_status_t status
;
682 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP
:
684 amd_dbgapi_wave_id_t wave_id
;
685 if ((status
= amd_dbgapi_event_get_info (process_id
, event_id
,
686 AMD_DBGAPI_EVENT_INFO_WAVE
,
687 sizeof (wave_id
), &wave_id
))
688 != AMD_DBGAPI_STATUS_SUCCESS
)
689 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
690 event_id
.handle
, status
);
692 amd_dbgapi_wave_stop_reason_t stop_reason
;
693 status
= amd_dbgapi_wave_get_info (process_id
, wave_id
,
694 AMD_DBGAPI_WAVE_INFO_STOP_REASON
,
695 sizeof (stop_reason
), &stop_reason
);
697 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
698 && status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
699 error (_ ("wave_get_info for wave_%ld failed (rc=%d)"),
700 wave_id
.handle
, status
);
702 /* The wave may have exited, or the queue went into an error
703 state. In such cases, we will see another wave command
704 terminated event, and handle the wave termination then. */
706 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
707 info
->wave_stop_events
.emplace_back (
708 std::make_pair (wave_id
, stop_reason
));
712 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED
:
713 amd_dbgapi_code_object_list_updated
.notify ();
716 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
:
717 /* Breakpoint resume events should be handled by the breakpoint
718 action, and this code should not reach this. */
719 gdb_assert_not_reached (_ ("unhandled event kind"));
722 case AMD_DBGAPI_EVENT_KIND_RUNTIME
:
724 amd_dbgapi_runtime_state_t runtime_state
;
726 if ((status
= amd_dbgapi_event_get_info (
727 process_id
, event_id
, AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE
,
728 sizeof (runtime_state
), &runtime_state
))
729 != AMD_DBGAPI_STATUS_SUCCESS
)
730 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
731 event_id
.handle
, status
);
733 switch (runtime_state
)
735 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUPPORTED
:
736 amd_dbgapi_activated
.notify ();
738 case AMD_DBGAPI_RUNTIME_STATE_LOADED_UNSUPPORTED
:
739 warning (_ ("ROCm-GDB: low-level runtime version not supported"));
742 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED
:
743 amd_dbgapi_deactivated
.notify ();
750 error (_ ("event kind (%d) not supported"), event_kind
);
753 amd_dbgapi_event_processed (process_id
, event_id
);
756 /* Drain the amd_dbgapi event queue until an event of the given type is seen.
757 If no particular event kind is specified (AMD_DBGAPI_EVENT_KIND_NONE), the
758 event queue is completely drained. Wave stop events that are not returned
759 are re-queued into the current's process pending wave events. */
760 static amd_dbgapi_event_id_t
761 rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind
)
763 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
767 amd_dbgapi_event_id_t event_id
;
768 amd_dbgapi_event_kind_t event_kind
;
770 amd_dbgapi_status_t status
= amd_dbgapi_next_pending_event (
771 info
->process_id
, &event_id
, &event_kind
);
773 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
774 error (_ ("next_pending_event failed (rc=%d)"), status
);
776 if (event_id
.handle
== AMD_DBGAPI_EVENT_NONE
.handle
777 || event_kind
== until_event_kind
)
780 rocm_process_one_event (event_id
, event_kind
);
785 rocm_target_ops::wait (ptid_t ptid
, struct target_waitstatus
*ws
,
789 fprintf_unfiltered (gdb_stdlog
,
790 "\e[1;34minfrun: rocm_target_ops::wait\e[0m\n");
792 if (!ptid_is_gpu (ptid
))
794 ptid_t event_ptid
= beneath ()->wait (ptid
, ws
, target_options
);
795 if (event_ptid
!= minus_one_ptid
)
799 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
800 amd_dbgapi_process_id_t process_id
= info
->process_id
;
802 /* Drain all the events from the amd_dbgapi, and preserve the ordering. */
803 if (info
->wave_stop_events
.empty ())
805 amd_dbgapi_process_set_progress (process_id
,
806 AMD_DBGAPI_PROGRESS_NO_FORWARD
);
808 /* Flush the async file first. */
809 if (target_is_async_p ())
812 rocm_process_event_queue ();
814 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
815 we can keep the process in progress_no_forward mode. The infrun loop
816 will enable forward progress when a thread is resumed. */
817 if (non_stop
|| info
->wave_stop_events
.empty ())
818 amd_dbgapi_process_set_progress (process_id
,
819 AMD_DBGAPI_PROGRESS_NORMAL
);
822 if (info
->wave_stop_events
.empty ())
823 return minus_one_ptid
;
825 amd_dbgapi_wave_id_t event_wave_id
;
826 amd_dbgapi_wave_stop_reason_t stop_reason
;
828 std::tie (event_wave_id
, stop_reason
) = info
->wave_stop_events
.front ();
829 info
->wave_stop_events
.pop_front ();
831 ptid_t
event_ptid (current_inferior ()->pid
, 1, event_wave_id
.handle
);
833 if (!find_thread_ptid (event_ptid
))
835 add_thread_silent (event_ptid
);
836 set_running (event_ptid
, 1);
837 set_executing (event_ptid
, 1);
840 /* Since we are manipulating the register cache for the event thread,
841 make sure it is the current thread. */
842 switch_to_thread (event_ptid
);
844 /* By caching the PC now, we avoid having to suspend/resume the queue
845 later when we need to access it. */
846 amd_dbgapi_global_address_t stop_pc
;
847 if (amd_dbgapi_wave_get_info (process_id
, event_wave_id
,
848 AMD_DBGAPI_WAVE_INFO_PC
, sizeof (stop_pc
),
850 == AMD_DBGAPI_STATUS_SUCCESS
)
852 struct regcache
*regcache
= get_thread_regcache (event_ptid
);
853 regcache
->raw_supply (gdbarch_pc_regnum (regcache
->arch ()), &stop_pc
);
855 ws
->kind
= TARGET_WAITKIND_STOPPED
;
858 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
859 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
))
860 ws
->value
.sig
= GDB_SIGNAL_TRAP
;
861 else if (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION
)
862 ws
->value
.sig
= GDB_SIGNAL_SEGV
;
864 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
865 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
866 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
867 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
868 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
869 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
870 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0
))
871 ws
->value
.sig
= GDB_SIGNAL_FPE
;
873 ws
->value
.sig
= GDB_SIGNAL_0
;
875 /* If there are more events in the list, mark the async file so that
876 rocm_target_ops::wait gets called again. */
877 if (target_is_async_p () && !info
->wave_stop_events
.empty ())
884 rocm_target_ops::stopped_by_sw_breakpoint ()
886 if (!ptid_is_gpu (inferior_ptid
))
887 return beneath ()->supports_stopped_by_sw_breakpoint ()
888 && beneath ()->stopped_by_sw_breakpoint ();
890 /* FIXME: we should check that the wave is not single-stepping. */
892 struct regcache
*regcache
= get_thread_regcache (inferior_ptid
);
894 CORE_ADDR bkpt_pc
= regcache_read_pc (regcache
)
895 - gdbarch_decr_pc_after_break (regcache
->arch ());
897 return software_breakpoint_inserted_here_p (regcache
->aspace (), bkpt_pc
);
901 rocm_target_ops::mourn_inferior ()
903 /* FIXME: only unpush on the last activation. */
904 /* Disengage the ROCm target_ops. */
905 unpush_target (&rocm_ops
);
907 beneath ()->mourn_inferior ();
911 rocm_target_ops::fetch_registers (struct regcache
*regcache
, int regno
)
913 struct gdbarch
*gdbarch
= regcache
->arch ();
914 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
916 /* delegate to the host routines when not on the device */
918 if (!rocm_is_amdgcn_gdbarch (gdbarch
))
920 beneath ()->fetch_registers (regcache
, regno
);
924 inferior
*inf
= find_inferior_ptid (regcache
->ptid ());
925 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (inf
);
926 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
928 gdb_byte raw
[AMDGCN_MAX_REGISTER_SIZE
];
930 amd_dbgapi_status_t status
= amd_dbgapi_read_register (
931 process_id
, wave_id
, tdep
->register_ids
[regno
], 0,
932 TYPE_LENGTH (register_type (gdbarch
, regno
)), raw
);
934 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
936 regcache
->raw_supply (regno
, raw
);
938 else if (status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_REGISTER_ID
)
940 warning (_ ("Couldn't read register %s (#%d)."),
941 gdbarch_register_name (gdbarch
, regno
), regno
);
946 rocm_target_ops::store_registers (struct regcache
*regcache
, int regno
)
948 struct gdbarch
*gdbarch
= regcache
->arch ();
949 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
950 gdb_byte raw
[AMDGCN_MAX_REGISTER_SIZE
];
952 if (!rocm_is_amdgcn_gdbarch (gdbarch
))
954 beneath ()->store_registers (regcache
, regno
);
958 inferior
*inf
= find_inferior_ptid (regcache
->ptid ());
959 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (inf
);
960 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
962 regcache
->raw_collect (regno
, &raw
);
964 amd_dbgapi_status_t status
= amd_dbgapi_write_register (
965 process_id
, wave_id
, tdep
->register_ids
[regno
], 0,
966 TYPE_LENGTH (register_type (gdbarch
, regno
)), raw
);
968 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
970 warning (_ ("Couldn't write register %s (#%d)."),
971 gdbarch_register_name (gdbarch
, regno
), regno
);
975 /* Fix breakpoints created with an address location while the
976 architecture was set to the host (could be fixed in core GDB). */
979 rocm_target_breakpoint_fixup (struct breakpoint
*b
)
981 if (b
->location
.get ()
982 && event_location_type (b
->location
.get ()) == ADDRESS_LOCATION
983 && gdbarch_bfd_arch_info (b
->loc
->gdbarch
)->arch
== bfd_arch_amdgcn
984 && gdbarch_bfd_arch_info (b
->gdbarch
)->arch
!= bfd_arch_amdgcn
)
986 b
->gdbarch
= b
->loc
->gdbarch
;
991 rocm_target_ops::thread_architecture (ptid_t ptid
)
993 static std::result_of
<decltype (&ptid_t::tid
) (ptid_t
)>::type last_tid
= 0;
994 static struct gdbarch
*cached_arch
= nullptr;
996 if (!ptid_is_gpu (ptid
))
997 return beneath ()->thread_architecture (ptid
);
999 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
1000 wave IDs are unique, and aren't reused. */
1001 if (ptid
.tid () == last_tid
)
1004 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1005 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
1006 amd_dbgapi_architecture_id_t architecture_id
;
1008 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
1009 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
1010 sizeof (architecture_id
), &architecture_id
)
1011 != AMD_DBGAPI_STATUS_SUCCESS
)
1012 error (_ ("Couldn't get architecture for wave_%ld"), ptid
.tid ());
1014 uint32_t elf_amdgpu_machine
;
1015 if (amd_dbgapi_architecture_get_info (
1016 architecture_id
, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE
,
1017 sizeof (elf_amdgpu_machine
), &elf_amdgpu_machine
)
1018 != AMD_DBGAPI_STATUS_SUCCESS
)
1019 error (_ ("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1020 architecture_id
.handle
);
1022 struct gdbarch_info info
;
1023 gdbarch_info_init (&info
);
1025 info
.bfd_arch_info
= bfd_lookup_arch (bfd_arch_amdgcn
, elf_amdgpu_machine
);
1026 info
.byte_order
= BFD_ENDIAN_LITTLE
;
1027 info
.osabi
= GDB_OSABI_AMDGPU_HSA
;
1029 last_tid
= ptid
.tid ();
1030 if (!(cached_arch
= gdbarch_find_by_info (info
)))
1031 error (_ ("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine
);
1037 rocm_target_ops::update_thread_list ()
1039 for (inferior
*inf
: all_inferiors ())
1041 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (inf
);
1042 amd_dbgapi_wave_id_t
*wave_list
;
1045 amd_dbgapi_changed_t changed
;
1046 amd_dbgapi_status_t status
;
1048 = amd_dbgapi_wave_list (process_id
, &count
, &wave_list
, &changed
))
1049 != AMD_DBGAPI_STATUS_SUCCESS
)
1050 error (_ ("amd_dbgapi_wave_list failed (rc=%d"), status
);
1052 if (changed
== AMD_DBGAPI_CHANGED_NO
)
1055 /* Create a set and free the wave list. */
1056 std::set
<std::result_of
<decltype (&ptid_t::tid
) (ptid_t
)>::type
> threads
;
1057 for (size_t i
= 0; i
< count
; ++i
)
1058 threads
.emplace (wave_list
[i
].handle
);
1061 /* Then prune the wave_ids that already have a thread_info. */
1062 for (thread_info
*tp
: inf
->non_exited_threads ())
1063 if (ptid_is_gpu (tp
->ptid
))
1064 threads
.erase (tp
->ptid
.tid ());
1066 /* The wave_ids that are left require a new thread_info. */
1067 for (auto &&tid
: threads
)
1069 ptid_t
wave_ptid (inf
->pid
, 1, tid
);
1070 amd_dbgapi_wave_state_t state
;
1072 if (amd_dbgapi_wave_get_info (
1073 process_id
, get_amd_dbgapi_wave_id (wave_ptid
),
1074 AMD_DBGAPI_WAVE_INFO_STATE
, sizeof (state
), &state
)
1075 != AMD_DBGAPI_STATUS_SUCCESS
)
1078 add_thread_silent (wave_ptid
);
1079 set_running (wave_ptid
, 1);
1080 set_executing (wave_ptid
, 1);
1084 /* Give the beneath target a chance to do extra processing. */
1085 this->beneath ()->update_thread_list ();
1089 rocm_target_solib_loaded (struct so_list
*solib
)
1091 /* Notify the amd_dbgapi that a shared library has been loaded. */
1092 for (auto &&value
: get_rocm_inferior_info ()->notify_solib_map
)
1093 /* TODO: If we want to support file name wildcards, change this code. */
1094 if (::strstr (solib
->so_original_name
, value
.second
.compare
.c_str ())
1095 && !value
.second
.is_loaded
)
1097 value
.second
.solib
= solib
;
1098 value
.second
.is_loaded
= true;
1100 amd_dbgapi_report_shared_library (
1101 get_amd_dbgapi_process_id (),
1102 amd_dbgapi_shared_library_id_t
{ value
.first
},
1103 AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
);
1108 rocm_target_solib_unloaded (struct so_list
*solib
)
1110 /* Notify the amd_dbgapi that a shared library will unload. */
1111 for (auto &&value
: get_rocm_inferior_info ()->notify_solib_map
)
1112 /* TODO: If we want to support file name wildcards, change this code. */
1113 if (::strstr (solib
->so_original_name
, value
.second
.compare
.c_str ())
1114 && value
.second
.is_loaded
)
1116 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
1118 amd_dbgapi_report_shared_library (
1119 info
->process_id
, amd_dbgapi_shared_library_id_t
{ value
.first
},
1120 AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED
);
1122 /* Delete breakpoints that were left inserted in this shared library.
1124 for (auto it
= info
->breakpoint_map
.begin ();
1125 it
!= info
->breakpoint_map
.end ();)
1126 if (solib_contains_address_p (solib
, it
->second
->loc
->address
))
1128 warning (_ ("breakpoint_%ld is still inserted after "
1129 "shared_library_%ld was unloaded"),
1130 it
->first
, value
.first
);
1131 delete_breakpoint (it
->second
);
1132 it
= info
->breakpoint_map
.erase (it
);
1137 value
.second
.solib
= nullptr;
1138 value
.second
.is_loaded
= false;
1143 rocm_target_inferior_created (struct target_ops
*target
, int from_tty
)
1145 struct inferior
*inf
= current_inferior ();
1146 auto *info
= get_rocm_inferior_info (inf
);
1147 amd_dbgapi_status_t status
;
1149 if (!target_can_async_p ())
1152 _ ("ROCm-GDB requires target-async, GPU debugging is disabled"));
1156 gdb_assert (info
->wave_stop_events
.empty ());
1158 status
= amd_dbgapi_process_attach (inf
, &info
->process_id
);
1160 if (status
== AMD_DBGAPI_STATUS_ERROR_VERSION_MISMATCH
)
1161 warning (_ ("The version of the kernel driver does not match the version "
1162 "required by the ROCm debugger library"));
1164 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1166 warning (_ ("Could not attach to process %d"), inf
->pid
);
1170 if (amd_dbgapi_process_get_info (info
->process_id
,
1171 AMD_DBGAPI_PROCESS_INFO_NOTIFIER
,
1172 sizeof (info
->notifier
), &info
->notifier
)
1173 != AMD_DBGAPI_STATUS_SUCCESS
)
1175 warning (_ ("Could not retrieve process %d's notifier"), inf
->pid
);
1176 amd_dbgapi_process_detach (info
->process_id
);
1180 /* We add a file handler for events returned by the debugger api. We'll use
1181 this handler to signal our async handler that events are available. */
1184 [] (int error
, gdb_client_data client_data
) {
1185 auto info_
= static_cast<struct rocm_inferior_info
*> (client_data
);
1188 /* Drain the notifier pipe. */
1192 ret
= read (info_
->notifier
, &buf
, 1);
1194 while (ret
>= 0 || (ret
== -1 && errno
== EINTR
));
1196 /* Signal our async handler. */
1201 /* Attaching to the inferior may have generated runtime events, process
1203 rocm_process_event_queue ();
1207 rocm_target_inferior_exit (struct inferior
*inf
)
1209 auto *info
= get_rocm_inferior_info (inf
);
1211 amd_dbgapi_deactivated
.notify ();
1213 delete_file_handler (info
->notifier
);
1215 amd_dbgapi_process_detach (info
->process_id
);
1217 /* Delete the breakpoints that are still active. */
1218 for (auto &&value
: info
->breakpoint_map
)
1219 delete_breakpoint (value
.second
);
1221 rocm_inferior_data
.clear (inf
);
1224 static cli_style_option
warning_style ("rocm_warning", ui_file_style::RED
);
1225 static cli_style_option
info_style ("rocm_info", ui_file_style::GREEN
);
1226 static cli_style_option
verbose_style ("rocm_verbose", ui_file_style::BLUE
);
1228 static amd_dbgapi_callbacks_t dbgapi_callbacks
= {
1229 /* allocate_memory. */
1230 .allocate_memory
= xmalloc
,
1232 /* deallocate_memory. */
1233 .deallocate_memory
= xfree
,
1236 .get_os_pid
= [] (amd_dbgapi_client_process_id_t client_process_id
,
1237 pid_t
*pid
) -> amd_dbgapi_status_t
{
1238 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1241 return AMD_DBGAPI_STATUS_SUCCESS
;
1244 /* enable_notify_shared_library callback. */
1245 .enable_notify_shared_library
1246 = [] (amd_dbgapi_client_process_id_t client_process_id
,
1247 const char *library_name
, amd_dbgapi_shared_library_id_t library_id
,
1248 amd_dbgapi_shared_library_state_t
*library_state
)
1249 -> amd_dbgapi_status_t
{
1250 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1251 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1253 if (!library_name
|| !library_state
)
1254 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1256 if (info
->notify_solib_map
.find (library_id
.handle
)
1257 != info
->notify_solib_map
.end ())
1259 /* This library id is already registered. */
1260 return AMD_DBGAPI_STATUS_ERROR
;
1263 /* Check whether the library is already loaded. */
1264 bool is_loaded
= false;
1265 struct so_list
*solib
;
1266 for (solib
= inf
->pspace
->so_list
; solib
; solib
= solib
->next
)
1267 if (::strstr (solib
->so_original_name
, library_name
))
1273 /* Check that the library_name is valid. If must not be empty, and
1274 should not have wildcard characters. */
1275 if (*library_name
== '\0'
1276 || std::string (library_name
).find_first_of ("*?[]")
1277 != std::string::npos
)
1278 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1280 /* Add a new entry in the notify_solib_map. */
1281 if (!info
->notify_solib_map
1282 .emplace (std::piecewise_construct
,
1283 std::forward_as_tuple (library_id
.handle
),
1284 std::forward_as_tuple (rocm_notify_shared_library_info
{
1285 library_name
, solib
, is_loaded
}))
1287 return AMD_DBGAPI_STATUS_ERROR
;
1289 *library_state
= is_loaded
? AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
1290 : AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED
;
1292 return AMD_DBGAPI_STATUS_SUCCESS
;
1295 /* disable_notify_shared_library callback. */
1296 .disable_notify_shared_library
1297 = [] (amd_dbgapi_client_process_id_t client_process_id
,
1298 amd_dbgapi_shared_library_id_t library_id
) -> amd_dbgapi_status_t
{
1299 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1300 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1302 auto it
= info
->notify_solib_map
.find (library_id
.handle
);
1303 if (it
== info
->notify_solib_map
.end ())
1304 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID
;
1306 info
->notify_solib_map
.erase (it
);
1307 return AMD_DBGAPI_STATUS_SUCCESS
;
1310 /* get_symbol_address callback. */
1311 .get_symbol_address
=
1312 [] (amd_dbgapi_client_process_id_t client_process_id
,
1313 amd_dbgapi_shared_library_id_t library_id
, const char *symbol_name
,
1314 amd_dbgapi_global_address_t
*address
) {
1315 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1316 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1318 auto it
= info
->notify_solib_map
.find (library_id
.handle
);
1319 if (it
== info
->notify_solib_map
.end ())
1320 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID
;
1322 struct so_list
*solib
= it
->second
.solib
;
1324 return AMD_DBGAPI_STATUS_ERROR_LIBRARY_NOT_LOADED
;
1326 solib_read_symbols (solib
, 0);
1327 gdb_assert (solib
->objfile
);
1329 struct bound_minimal_symbol msymbol
1330 = lookup_minimal_symbol (symbol_name
, NULL
, solib
->objfile
);
1332 if (!msymbol
.minsym
|| BMSYMBOL_VALUE_ADDRESS (msymbol
) == 0)
1333 return AMD_DBGAPI_STATUS_ERROR_SYMBOL_NOT_FOUND
;
1335 *address
= BMSYMBOL_VALUE_ADDRESS (msymbol
);
1336 return AMD_DBGAPI_STATUS_SUCCESS
;
1339 /* set_breakpoint callback. */
1341 [] (amd_dbgapi_client_process_id_t client_process_id
,
1342 amd_dbgapi_shared_library_id_t shared_library_id
,
1343 amd_dbgapi_global_address_t address
,
1344 amd_dbgapi_breakpoint_id_t breakpoint_id
) {
1345 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1346 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1348 /* Initialize the breakpoint ops lazily since we depend on
1349 bkpt_breakpoint_ops and we can't control the order in which
1350 initializers are called. */
1351 if (rocm_breakpoint_ops
.check_status
== NULL
)
1353 rocm_breakpoint_ops
= bkpt_breakpoint_ops
;
1354 rocm_breakpoint_ops
.check_status
= rocm_breakpoint_check_status
;
1357 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1358 if (it
!= info
->breakpoint_map
.end ())
1359 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1361 /* Create a new breakpoint. */
1362 struct obj_section
*section
= find_pc_section (address
);
1363 if (!section
|| !section
->objfile
)
1364 return AMD_DBGAPI_STATUS_ERROR
;
1366 event_location_up location
1367 = new_address_location (address
, nullptr, 0);
1368 if (!create_breakpoint (
1369 get_objfile_arch (section
->objfile
), location
.get (),
1370 /*cond_string*/ NULL
, /*thread*/ -1, /*extra_sring*/ NULL
,
1371 /*parse_extra*/ 0, /*tempflag*/ 0, /*bptype*/ bp_breakpoint
,
1372 /*ignore_count*/ 0, /*pending_break*/ AUTO_BOOLEAN_FALSE
,
1373 /*ops*/ &rocm_breakpoint_ops
, /*from_tty*/ 0,
1374 /*enabled*/ 1, /*internal*/ 1, /*flags*/ 0))
1375 return AMD_DBGAPI_STATUS_ERROR
;
1377 /* Find our breakpoint in the breakpoint list. */
1378 auto bp_loc
= std::make_pair (inf
->aspace
, address
);
1379 auto bp
= breakpoint_find_if (
1380 [] (struct breakpoint
*b
, void *data
) {
1381 auto *arg
= static_cast<decltype (&bp_loc
)> (data
);
1382 if (b
->ops
== &rocm_breakpoint_ops
&& b
->loc
1383 && b
->loc
->pspace
->aspace
== arg
->first
1384 && b
->loc
->address
== arg
->second
)
1388 reinterpret_cast<void *> (&bp_loc
));
1391 error (_ ("Could not find breakpoint"));
1393 info
->breakpoint_map
.emplace (breakpoint_id
.handle
, bp
);
1394 return AMD_DBGAPI_STATUS_SUCCESS
;
1397 /* remove_breakpoint callback. */
1398 .remove_breakpoint
=
1399 [] (amd_dbgapi_client_process_id_t client_process_id
,
1400 amd_dbgapi_breakpoint_id_t breakpoint_id
) {
1401 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1402 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1404 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1405 if (it
== info
->breakpoint_map
.end ())
1406 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1408 delete_breakpoint (it
->second
);
1409 info
->breakpoint_map
.erase (it
);
1411 return AMD_DBGAPI_STATUS_SUCCESS
;
1414 /* set_breakpoint_state callback. */
1415 .set_breakpoint_state
=
1416 [] (amd_dbgapi_client_process_id_t client_process_id
,
1417 amd_dbgapi_breakpoint_id_t breakpoint_id
,
1418 amd_dbgapi_breakpoint_state_t breakpoint_state
) {
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 if (breakpoint_state
== AMD_DBGAPI_BREAKPOINT_STATE_ENABLE
)
1427 it
->second
->enable_state
= bp_enabled
;
1428 else if (breakpoint_state
== AMD_DBGAPI_BREAKPOINT_STATE_DISABLE
)
1429 it
->second
->enable_state
= bp_disabled
;
1431 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1433 return AMD_DBGAPI_STATUS_SUCCESS
;
1437 = [] (amd_dbgapi_log_level_t level
, const char *message
) -> void {
1438 gdb::optional
<target_terminal::scoped_restore_terminal_state
> tstate
;
1440 if (level
> get_debug_amd_dbgapi_log_level ())
1443 if (target_supports_terminal_ours ())
1446 target_terminal::ours_for_output ();
1449 if (filtered_printing_initialized ())
1452 struct ui_file
*out_file
1453 = (level
>= AMD_DBGAPI_LOG_LEVEL_INFO
) ? gdb_stdlog
: gdb_stderr
;
1457 case AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
:
1458 fputs_unfiltered ("[amd-dbgapi]: ", out_file
);
1460 case AMD_DBGAPI_LOG_LEVEL_WARNING
:
1461 fputs_styled ("[amd-dbgapi]: ", warning_style
.style (), out_file
);
1463 case AMD_DBGAPI_LOG_LEVEL_INFO
:
1464 fputs_styled ("[amd-dbgapi]: ", info_style
.style (), out_file
);
1466 case AMD_DBGAPI_LOG_LEVEL_VERBOSE
:
1467 fputs_styled ("[amd-dbgapi]: ", verbose_style
.style (), out_file
);
1471 fputs_unfiltered (message
, out_file
);
1472 fputs_unfiltered ("\n", out_file
);
1476 /* Implementation of `_wave_id' variable. */
1478 static struct value
*
1479 rocm_wave_id_make_value (struct gdbarch
*gdbarch
, struct internalvar
*var
,
1482 if (ptid_is_gpu (inferior_ptid
))
1484 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1485 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
1486 uint32_t group_ids
[3], wave_in_group
;
1488 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
1489 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD
,
1490 sizeof (group_ids
), &group_ids
)
1491 == AMD_DBGAPI_STATUS_SUCCESS
1492 && amd_dbgapi_wave_get_info (
1493 process_id
, wave_id
,
1494 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP
,
1495 sizeof (wave_in_group
), &wave_in_group
)
1496 == AMD_DBGAPI_STATUS_SUCCESS
)
1498 std::string wave_id_str
1499 = string_printf ("(%d,%d,%d)/%d", group_ids
[2], group_ids
[1],
1500 group_ids
[0], wave_in_group
);
1502 return value_cstring (wave_id_str
.data (), wave_id_str
.length () + 1,
1503 builtin_type (gdbarch
)->builtin_char
);
1507 return allocate_value (builtin_type (gdbarch
)->builtin_void
);
1510 static const struct internalvar_funcs rocm_wave_id_funcs
1511 = { rocm_wave_id_make_value
, NULL
, NULL
};
1513 /* List of set/show debug amd_dbgapi commands. */
1514 struct cmd_list_element
*set_debug_amd_dbgapi_list
;
1515 struct cmd_list_element
*show_debug_amd_dbgapi_list
;
1518 set_debug_amd_dbgapi (const char *arg
, int from_tty
)
1520 help_list (set_debug_amd_dbgapi_list
, "set debug amd-dbgapi ",
1521 (enum command_class
) - 1, gdb_stdout
);
1525 show_debug_amd_dbgapi (const char *args
, int from_tty
)
1527 cmd_show_list (show_debug_amd_dbgapi_list
, from_tty
, "");
1530 constexpr char amd_dbgapi_log_level_off
[] = "off";
1531 constexpr char amd_dbgapi_log_level_error
[] = "error";
1532 constexpr char amd_dbgapi_log_level_warning
[] = "warning";
1533 constexpr char amd_dbgapi_log_level_info
[] = "info";
1534 constexpr char amd_dbgapi_log_level_verbose
[] = "verbose";
1536 constexpr const char *debug_amd_dbgapi_log_level_enums
[]
1537 = { [AMD_DBGAPI_LOG_LEVEL_NONE
] = amd_dbgapi_log_level_off
,
1538 [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
] = amd_dbgapi_log_level_error
,
1539 [AMD_DBGAPI_LOG_LEVEL_WARNING
] = amd_dbgapi_log_level_warning
,
1540 [AMD_DBGAPI_LOG_LEVEL_INFO
] = amd_dbgapi_log_level_info
,
1541 [AMD_DBGAPI_LOG_LEVEL_VERBOSE
] = amd_dbgapi_log_level_verbose
,
1544 static const char *debug_amd_dbgapi_log_level
= amd_dbgapi_log_level_error
;
1546 static amd_dbgapi_log_level_t
1547 get_debug_amd_dbgapi_log_level ()
1550 for (pos
= 0; debug_amd_dbgapi_log_level_enums
[pos
]; ++pos
)
1551 if (debug_amd_dbgapi_log_level
== debug_amd_dbgapi_log_level_enums
[pos
])
1554 gdb_assert (debug_amd_dbgapi_log_level_enums
[pos
]);
1555 return static_cast<amd_dbgapi_log_level_t
> (pos
);
1559 set_debug_amd_dbgapi_log_level (const char *args
, int from_tty
,
1560 struct cmd_list_element
*c
)
1562 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1566 show_debug_amd_dbgapi_log_level (struct ui_file
*file
, int from_tty
,
1567 struct cmd_list_element
*c
,
1570 fprintf_filtered (file
, _ ("The amd-dbgapi log level is %s.\n"), value
);
1574 info_agents_command (const char *args
, int from_tty
)
1576 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1577 struct ui_out
*uiout
= current_uiout
;
1578 amd_dbgapi_status_t status
;
1580 amd_dbgapi_agent_id_t
*agent_list
;
1583 if (process_id
.handle
!= AMD_DBGAPI_PROCESS_NONE
.handle
1585 = amd_dbgapi_agent_list (process_id
, &count
, &agent_list
, nullptr))
1586 != AMD_DBGAPI_STATUS_SUCCESS
)
1587 error (_ ("amd_dbgapi_agent_list failed (rc=%d)"), status
);
1589 if (!count
&& !uiout
->is_mi_like_p ())
1591 uiout
->field_string (NULL
,
1592 _ ("No agents are currently active.\n"));
1596 /* Calculate the maximum size needed to print the agents names. */
1597 std::vector
<std::string
> agent_names (count
);
1599 size_t max_name_len
= 0;
1600 for (size_t i
= 0; i
< count
; ++i
)
1604 if ((status
= amd_dbgapi_agent_get_info (
1605 process_id
, agent_list
[i
], AMD_DBGAPI_AGENT_INFO_NAME
,
1606 sizeof (agent_name
), &agent_name
))
1607 != AMD_DBGAPI_STATUS_SUCCESS
)
1609 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID
)
1610 agent_names
[i
] = "N/A";
1612 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status
);
1616 agent_names
[i
] = agent_name
;
1620 max_name_len
= std::max (max_name_len
, agent_names
[i
].size ());
1624 ui_out_emit_table
table_emmitter (uiout
, 7, count
, "InfoRocmDevicesTable");
1626 uiout
->table_header (2, ui_left
, "agent_id", "Id");
1627 uiout
->table_header (8, ui_left
, "location_id", "PCI Slot");
1628 uiout
->table_header (std::max (11ul, max_name_len
), ui_left
, "name",
1630 uiout
->table_header (14, ui_left
, "num_se", "Shader Engines");
1631 uiout
->table_header (13, ui_left
, "num_cu", "Compute Units");
1632 uiout
->table_header (7, ui_left
, "simd", "SIMD/CU");
1633 uiout
->table_header (15, ui_left
, "waves", "Wavefronts/SIMD");
1634 uiout
->table_body ();
1637 for (size_t i
= 0; i
< count
; ++i
)
1639 ui_out_emit_tuple
tuple_emitter (uiout
, "InfoRocmDevicesRow");
1642 uiout
->field_signed ("agent_id", agent_list
[i
].handle
);
1645 uint32_t location_id
;
1646 if ((status
= amd_dbgapi_agent_get_info (
1647 process_id
, agent_list
[i
], AMD_DBGAPI_AGENT_INFO_PCIE_SLOT
,
1648 sizeof (location_id
), &location_id
))
1649 != AMD_DBGAPI_STATUS_SUCCESS
)
1651 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID
)
1652 uiout
->field_string ("location_id", "N/A");
1654 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status
);
1657 uiout
->field_string (
1659 string_printf ("%02x:%02x.%d", (location_id
>> 8) & 0xFF,
1660 (location_id
>> 3) & 0x1F, location_id
& 0x7));
1663 uiout
->field_string ("name", agent_names
[i
]);
1665 /* num_se, num_cu, simd, waves */
1667 #define UIOUT_FIELD_INT(name, query) \
1669 if ((status = amd_dbgapi_agent_get_info (process_id, agent_list[i], query, \
1670 sizeof (name), &name)) \
1671 != AMD_DBGAPI_STATUS_SUCCESS) \
1673 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID) \
1674 uiout->field_string (#name, "N/A"); \
1676 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status); \
1679 uiout->field_signed (#name, name);
1681 UIOUT_FIELD_INT (num_se
, AMD_DBGAPI_AGENT_INFO_SHADER_ENGINE_COUNT
);
1682 UIOUT_FIELD_INT (num_cu
, AMD_DBGAPI_AGENT_INFO_COMPUTE_UNIT_COUNT
);
1683 UIOUT_FIELD_INT (simd
, AMD_DBGAPI_AGENT_INFO_NUM_SIMD_PER_COMPUTE_UNIT
);
1684 UIOUT_FIELD_INT (waves
, AMD_DBGAPI_AGENT_INFO_MAX_WAVES_PER_SIMD
);
1686 #undef UIOUT_FIELD_INT
1692 gdb_flush (gdb_stdout
);
1695 /* -Wmissing-prototypes */
1696 extern initialize_file_ftype _initialize_rocm_tdep
;
1699 _initialize_rocm_tdep (void)
1701 /* Initialize the ROCm Debug API. */
1702 if (amd_dbgapi_initialize (&dbgapi_callbacks
) != AMD_DBGAPI_STATUS_SUCCESS
)
1705 /* Set the initial log level. */
1706 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1708 /* Install observers. */
1709 gdb::observers::breakpoint_created
.attach (rocm_target_breakpoint_fixup
);
1710 gdb::observers::solib_loaded
.attach (rocm_target_solib_loaded
);
1711 gdb::observers::solib_unloaded
.attach (rocm_target_solib_unloaded
);
1712 gdb::observers::inferior_created
.attach (rocm_target_inferior_created
);
1713 gdb::observers::inferior_exit
.attach (rocm_target_inferior_exit
);
1715 amd_dbgapi_activated
.attach (rocm_target_dbgapi_activated
);
1716 amd_dbgapi_deactivated
.attach (rocm_target_dbgapi_deactivated
);
1718 create_internalvar_type_lazy ("_wave_id", &rocm_wave_id_funcs
, NULL
);
1721 "amd-dbgapi", no_class
, set_debug_amd_dbgapi
,
1722 _ ("Generic command for setting amd-dbgapi debugging flags"),
1723 &set_debug_amd_dbgapi_list
, "set debug amd-dbgapi ", 0, &setdebuglist
);
1726 "amd-dbgapi", no_class
, show_debug_amd_dbgapi
,
1727 _ ("Generic command for showing amd-dbgapi debugging flags"),
1728 &show_debug_amd_dbgapi_list
, "show debug amd-dbgapi ", 0,
1731 add_setshow_enum_cmd (
1732 "log-level", class_maintenance
, debug_amd_dbgapi_log_level_enums
,
1733 &debug_amd_dbgapi_log_level
, _ ("Set the amd-dbgapi log level."),
1734 _ ("Show the amd-dbgapi log level."),
1735 _ ("off == no logging is enabled\n"
1736 "error == fatal errors are reported\n"
1737 "warning == fatal errors and warnings are reported\n"
1738 "info == fatal errors, warnings, and info messages are reported\n"
1739 "verbose == all messages are reported"),
1740 set_debug_amd_dbgapi_log_level
, show_debug_amd_dbgapi_log_level
,
1741 &set_debug_amd_dbgapi_list
, &show_debug_amd_dbgapi_list
);
1743 add_cmd ("agents", class_info
, info_agents_command
,
1744 _ ("Info about currently active agents."), &infolist
);