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 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_re_set (struct breakpoint
*b
)
271 rocm_breakpoint_check_status (struct bpstats
*bs
)
273 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
274 amd_dbgapi_process_id_t process_id
= info
->process_id
;
275 amd_dbgapi_status_t status
;
278 bs
->print_it
= print_it_noop
;
280 /* Find the address the breakpoint is set at. */
281 auto it
= std::find_if (
282 info
->breakpoint_map
.begin (), info
->breakpoint_map
.end (),
283 [=] (const decltype (info
->breakpoint_map
)::value_type
&value
) {
284 return value
.second
== bs
->breakpoint_at
;
287 if (it
== info
->breakpoint_map
.end ())
288 error (_ ("Could not find breakpoint_id for breakpoint at %#lx"),
289 bs
->bp_location_at
->address
);
291 amd_dbgapi_breakpoint_id_t breakpoint_id
{ it
->first
};
292 amd_dbgapi_breakpoint_action_t action
;
294 status
= amd_dbgapi_report_breakpoint_hit (process_id
, breakpoint_id
,
295 inferior_thread (), &action
);
297 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
298 error (_ ("amd_dbgapi_report_breakpoint_hit failed: breakpoint_%ld "
300 breakpoint_id
.handle
, bs
->bp_location_at
->address
, status
);
302 if (action
== AMD_DBGAPI_BREAKPOINT_ACTION_RESUME
)
305 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
306 a breakpoint resume event for this breakpoint_id is seen. */
308 amd_dbgapi_event_id_t resume_event_id
309 = rocm_process_event_queue (AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
);
311 /* We should always get a breakpoint_resume event after processing all
312 events generated by reporting the breakpoint was hit. */
313 gdb_assert (resume_event_id
.handle
!= AMD_DBGAPI_EVENT_NONE
.handle
);
315 amd_dbgapi_breakpoint_id_t resume_breakpoint_id
;
316 status
= amd_dbgapi_event_get_info (
317 process_id
, resume_event_id
, AMD_DBGAPI_EVENT_INFO_BREAKPOINT
,
318 sizeof (resume_breakpoint_id
), &resume_breakpoint_id
);
320 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
321 error (_ ("amd_dbgapi_event_get_info failed (rc=%d)"), status
);
323 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint]
324 sequences cannot interleave, so this breakpoint resume event must be
325 for our breakpoint_id. */
326 if (resume_breakpoint_id
.handle
!= breakpoint_id
.handle
)
327 error (_ ("breakpoint resume event is not for this breakpoint. "
328 "Expected breakpoint_%ld, got breakpoint_%ld"),
329 breakpoint_id
.handle
, resume_breakpoint_id
.handle
);
331 amd_dbgapi_event_processed (process_id
, resume_event_id
);
335 rocm_target_dbgapi_activated ()
337 /* FIXME: only push on the first activation. */
338 /* Engage the ROCm target_ops and so_ops. */
339 push_target (&rocm_ops
);
343 rocm_target_dbgapi_deactivated ()
345 /* FIXME: only unpush on the last activation. */
346 /* Disengage the ROCm target_ops. */
347 unpush_target (&rocm_ops
);
351 rocm_target_ops::thread_alive (ptid_t ptid
)
353 if (!ptid_is_gpu (ptid
))
354 return beneath ()->thread_alive (ptid
);
356 /* Check that the wave_id is valid. */
358 inferior
*inf
= find_inferior_ptid (ptid
);
362 amd_dbgapi_wave_state_t state
;
363 return amd_dbgapi_wave_get_info (
364 get_amd_dbgapi_process_id (inf
), get_amd_dbgapi_wave_id (ptid
),
365 AMD_DBGAPI_WAVE_INFO_STATE
, sizeof (state
), &state
)
366 == AMD_DBGAPI_STATUS_SUCCESS
;
370 rocm_target_ops::thread_name (thread_info
*tp
)
372 if (!ptid_is_gpu (tp
->ptid
))
373 return beneath ()->thread_name (tp
);
375 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (tp
->inf
);
376 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (tp
->ptid
);
377 amd_dbgapi_dispatch_id_t dispatch_id
;
378 amd_dbgapi_global_address_t kernel_addr
;
380 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
381 AMD_DBGAPI_WAVE_INFO_DISPATCH
,
382 sizeof (dispatch_id
), &dispatch_id
)
383 != AMD_DBGAPI_STATUS_SUCCESS
384 || amd_dbgapi_dispatch_get_info (
385 process_id
, dispatch_id
,
386 AMD_DBGAPI_DISPATCH_INFO_KERNEL_ENTRY_ADDRESS
,
387 sizeof (kernel_addr
), &kernel_addr
)
388 != AMD_DBGAPI_STATUS_SUCCESS
)
391 struct bound_minimal_symbol msymbol
392 = lookup_minimal_symbol_by_pc_section (kernel_addr
, nullptr);
394 if (msymbol
.minsym
!= NULL
)
396 static char buf
[256];
399 xsnprintf (buf
, sizeof (buf
), "%s", msymbol
.minsym
->print_name ());
401 /* Strip the arguments from the demangled function name. */
402 if ((endp
= strchr (buf
, '(')))
412 rocm_target_ops::pid_to_str (ptid_t ptid
)
414 if (!ptid_is_gpu (ptid
))
416 return beneath ()->pid_to_str (ptid
);
419 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
420 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
421 amd_dbgapi_dispatch_id_t dispatch_id
;
422 uint32_t group_ids
[3], wave_in_group
;
424 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
425 AMD_DBGAPI_WAVE_INFO_DISPATCH
,
426 sizeof (dispatch_id
), &dispatch_id
)
427 != AMD_DBGAPI_STATUS_SUCCESS
428 || amd_dbgapi_wave_get_info (process_id
, wave_id
,
429 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD
,
430 sizeof (group_ids
), &group_ids
)
431 != AMD_DBGAPI_STATUS_SUCCESS
432 || amd_dbgapi_wave_get_info (
434 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP
,
435 sizeof (wave_in_group
), &wave_in_group
)
436 != AMD_DBGAPI_STATUS_SUCCESS
)
437 return std::string ("AMDGPU Thread");
439 return string_printf ("AMDGPU Thread %ld.%ld (%d,%d,%d)/%d",
440 dispatch_id
.handle
, wave_id
.handle
, group_ids
[2],
441 group_ids
[1], group_ids
[0], wave_in_group
);
445 rocm_target_ops::extra_thread_info (thread_info
*tp
)
447 if (!ptid_is_gpu (tp
->ptid
))
448 beneath ()->extra_thread_info (tp
);
453 enum target_xfer_status
454 rocm_target_ops::xfer_partial (enum target_object object
, const char *annex
,
455 gdb_byte
*readbuf
, const gdb_byte
*writebuf
,
456 ULONGEST offset
, ULONGEST requested_len
,
457 ULONGEST
*xfered_len
)
459 gdb::optional
<scoped_restore_current_thread
> maybe_restore_thread
;
461 if (ptid_is_gpu (inferior_ptid
))
463 gdb_assert (requested_len
&& xfered_len
&& "checking invariants");
465 if (object
!= TARGET_OBJECT_MEMORY
)
466 return TARGET_XFER_E_IO
;
468 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
469 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
471 amd_dbgapi_architecture_id_t architecture_id
;
472 amd_dbgapi_address_space_id_t address_space_id
;
474 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
475 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
476 sizeof (architecture_id
), &architecture_id
)
477 != AMD_DBGAPI_STATUS_SUCCESS
478 || amd_dbgapi_architecture_get_info (
480 AMD_DBGAPI_ARCHITECTURE_INFO_DEFAULT_GLOBAL_ADDRESS_SPACE
,
481 sizeof (address_space_id
), &address_space_id
)
482 != AMD_DBGAPI_STATUS_SUCCESS
)
483 error (_ ("Couldn't get default global address space"));
485 size_t len
= requested_len
;
486 amd_dbgapi_status_t status
;
489 status
= amd_dbgapi_read_memory (
490 process_id
, wave_id
, 0, address_space_id
, offset
, &len
, readbuf
);
492 status
= amd_dbgapi_write_memory (
493 process_id
, wave_id
, 0, address_space_id
, offset
, &len
, writebuf
);
495 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
497 if (status
!= AMD_DBGAPI_STATUS_ERROR_MEMORY_ACCESS
)
498 error (_ ("amd_dbgapi_%s_memory failed (rc=%d"),
499 readbuf
? "read" : "write", status
);
500 return TARGET_XFER_EOF
;
504 return TARGET_XFER_OK
;
507 return beneath ()->xfer_partial (object
, annex
, readbuf
, writebuf
, offset
,
508 requested_len
, xfered_len
);
512 rocm_target_ops::resume (ptid_t ptid
, int step
, enum gdb_signal signo
)
514 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
519 "\e[1;34minfrun: rocm_target_ops::resume ([%d,%ld,%ld])\e[0m\n",
520 ptid
.pid (), ptid
.lwp (), ptid
.tid ());
522 /* Check if the thread focus is on the GPU device. */
523 if (ptid
== minus_one_ptid
|| !ptid_is_gpu (ptid
))
525 beneath ()->resume (ptid
, step
, signo
);
526 if (ptid
!= minus_one_ptid
)
530 /* A specific PTID means `step only this process id'. */
531 bool resume_one
= ptid
!= minus_one_ptid
&& !ptid
.is_pid ();
532 gdb_assert (resume_one
|| !step
);
535 error (_ ("internal error - unimplemented "));
537 amd_dbgapi_process_set_progress (info
->process_id
,
538 AMD_DBGAPI_PROGRESS_NO_FORWARD
);
540 amd_dbgapi_status_t status
= amd_dbgapi_wave_resume (
541 info
->process_id
, get_amd_dbgapi_wave_id (ptid
),
542 step
? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
543 : AMD_DBGAPI_RESUME_MODE_NORMAL
);
544 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
545 warning (_ ("Could not resume %s (rc=%d)"),
546 target_pid_to_str (ptid
).c_str (), status
);
548 info
->commit_resume_all_start
= true;
552 rocm_target_ops::commit_resume ()
554 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
559 "\e[1;34minfrun: rocm_target_ops::commit_resume ()\e[0m\n");
561 beneath ()->commit_resume ();
563 if (info
->commit_resume_all_start
)
565 amd_dbgapi_process_set_progress (info
->process_id
,
566 AMD_DBGAPI_PROGRESS_NORMAL
);
567 info
->commit_resume_all_start
= false;
570 if (target_can_async_p ())
575 rocm_target_stop_one_wave (ptid_t ptid
)
577 amd_dbgapi_status_t status
;
579 status
= amd_dbgapi_wave_stop (get_amd_dbgapi_process_id (),
580 get_amd_dbgapi_wave_id (ptid
));
582 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
584 /* the wave must have exited, set the thread status to reflect that. */
585 auto *tp
= find_thread_ptid (ptid
);
588 tp
->state
= THREAD_EXITED
;
590 else if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
591 warning (_ ("Could not stop %s (rc=%d)"),
592 target_pid_to_str (ptid
).c_str (), status
);
596 rocm_target_ops::stop (ptid_t ptid
)
601 "\e[1;34minfrun: rocm_target_ops::stop ([%d,%ld,%ld])\e[0m\n",
602 ptid
.pid (), ptid
.lwp (), ptid
.tid ());
604 if (ptid
== minus_one_ptid
|| !ptid_is_gpu (ptid
))
606 beneath ()->stop (ptid
);
607 if (ptid
!= minus_one_ptid
)
611 if (ptid
== minus_one_ptid
)
612 error (_ ("internal error - unimplemented "));
614 rocm_target_stop_one_wave (ptid
);
618 handle_target_event (int error
, gdb_client_data client_data
)
620 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
621 amd_dbgapi_process_id_t process_id
= info
->process_id
;
623 amd_dbgapi_process_set_progress (process_id
, AMD_DBGAPI_PROGRESS_NO_FORWARD
);
625 /* Flush the async file first. */
626 if (target_is_async_p ())
629 rocm_process_event_queue ();
631 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
632 we can keep the process in progress_no_forward mode. The infrun loop
633 will enable forward progress when a thread is resumed. */
634 if (non_stop
|| info
->wave_stop_events
.empty ())
635 amd_dbgapi_process_set_progress (process_id
, AMD_DBGAPI_PROGRESS_NORMAL
);
637 if (!info
->wave_stop_events
.empty ())
638 inferior_event_handler (INF_REG_EVENT
, nullptr);
642 rocm_target_ops::async (int enable
)
644 beneath ()->async (enable
);
648 if (rocm_event_pipe
[0] != -1)
651 if (gdb_pipe_cloexec (rocm_event_pipe
) == -1)
652 internal_error (__FILE__
, __LINE__
, "creating event pipe failed.");
654 ::fcntl (rocm_event_pipe
[0], F_SETFL
, O_NONBLOCK
);
655 ::fcntl (rocm_event_pipe
[1], F_SETFL
, O_NONBLOCK
);
657 add_file_handler (rocm_event_pipe
[0], handle_target_event
, nullptr);
659 /* There may be pending events to handle. Tell the event loop
665 delete_file_handler (rocm_event_pipe
[0]);
667 if (rocm_event_pipe
[0] == -1)
670 ::close (rocm_event_pipe
[0]);
671 ::close (rocm_event_pipe
[1]);
672 rocm_event_pipe
[0] = -1;
673 rocm_event_pipe
[1] = -1;
678 rocm_process_one_event (amd_dbgapi_event_id_t event_id
,
679 amd_dbgapi_event_kind_t event_kind
)
681 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
682 amd_dbgapi_process_id_t process_id
= info
->process_id
;
683 amd_dbgapi_status_t status
;
687 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP
:
689 amd_dbgapi_wave_id_t wave_id
;
690 if ((status
= amd_dbgapi_event_get_info (process_id
, event_id
,
691 AMD_DBGAPI_EVENT_INFO_WAVE
,
692 sizeof (wave_id
), &wave_id
))
693 != AMD_DBGAPI_STATUS_SUCCESS
)
694 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
695 event_id
.handle
, status
);
697 amd_dbgapi_wave_stop_reason_t stop_reason
;
698 status
= amd_dbgapi_wave_get_info (process_id
, wave_id
,
699 AMD_DBGAPI_WAVE_INFO_STOP_REASON
,
700 sizeof (stop_reason
), &stop_reason
);
702 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
703 && status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
704 error (_ ("wave_get_info for wave_%ld failed (rc=%d)"),
705 wave_id
.handle
, status
);
707 /* The wave may have exited, or the queue went into an error
708 state. In such cases, we will see another wave command
709 terminated event, and handle the wave termination then. */
711 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
712 info
->wave_stop_events
.emplace_back (
713 std::make_pair (wave_id
, stop_reason
));
717 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED
:
718 amd_dbgapi_code_object_list_updated
.notify ();
721 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
:
722 /* Breakpoint resume events should be handled by the breakpoint
723 action, and this code should not reach this. */
724 gdb_assert_not_reached (_ ("unhandled event kind"));
727 case AMD_DBGAPI_EVENT_KIND_RUNTIME
:
729 amd_dbgapi_runtime_state_t runtime_state
;
731 if ((status
= amd_dbgapi_event_get_info (
732 process_id
, event_id
, AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE
,
733 sizeof (runtime_state
), &runtime_state
))
734 != AMD_DBGAPI_STATUS_SUCCESS
)
735 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
736 event_id
.handle
, status
);
738 switch (runtime_state
)
740 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUPPORTED
:
741 amd_dbgapi_activated
.notify ();
743 case AMD_DBGAPI_RUNTIME_STATE_LOADED_UNSUPPORTED
:
744 warning (_ ("ROCm-GDB: low-level runtime version not supported"));
747 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED
:
748 amd_dbgapi_deactivated
.notify ();
755 error (_ ("event kind (%d) not supported"), event_kind
);
758 amd_dbgapi_event_processed (process_id
, event_id
);
761 /* Drain the amd_dbgapi event queue until an event of the given type is seen.
762 If no particular event kind is specified (AMD_DBGAPI_EVENT_KIND_NONE), the
763 event queue is completely drained. Wave stop events that are not returned
764 are re-queued into the current's process pending wave events. */
765 static amd_dbgapi_event_id_t
766 rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind
)
768 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
772 amd_dbgapi_event_id_t event_id
;
773 amd_dbgapi_event_kind_t event_kind
;
775 amd_dbgapi_status_t status
= amd_dbgapi_next_pending_event (
776 info
->process_id
, &event_id
, &event_kind
);
778 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
779 error (_ ("next_pending_event failed (rc=%d)"), status
);
781 if (event_id
.handle
== AMD_DBGAPI_EVENT_NONE
.handle
782 || event_kind
== until_event_kind
)
785 rocm_process_one_event (event_id
, event_kind
);
790 rocm_target_ops::wait (ptid_t ptid
, struct target_waitstatus
*ws
,
794 fprintf_unfiltered (gdb_stdlog
,
795 "\e[1;34minfrun: rocm_target_ops::wait\e[0m\n");
797 if (!ptid_is_gpu (ptid
))
799 ptid_t event_ptid
= beneath ()->wait (ptid
, ws
, target_options
);
800 if (event_ptid
!= minus_one_ptid
)
804 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
805 amd_dbgapi_process_id_t process_id
= info
->process_id
;
807 /* Drain all the events from the amd_dbgapi, and preserve the ordering. */
808 if (info
->wave_stop_events
.empty ())
810 amd_dbgapi_process_set_progress (process_id
,
811 AMD_DBGAPI_PROGRESS_NO_FORWARD
);
813 /* Flush the async file first. */
814 if (target_is_async_p ())
817 rocm_process_event_queue ();
819 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
820 we can keep the process in progress_no_forward mode. The infrun loop
821 will enable forward progress when a thread is resumed. */
822 if (non_stop
|| info
->wave_stop_events
.empty ())
823 amd_dbgapi_process_set_progress (process_id
,
824 AMD_DBGAPI_PROGRESS_NORMAL
);
827 if (info
->wave_stop_events
.empty ())
828 return minus_one_ptid
;
830 amd_dbgapi_wave_id_t event_wave_id
;
831 amd_dbgapi_wave_stop_reason_t stop_reason
;
833 std::tie (event_wave_id
, stop_reason
) = info
->wave_stop_events
.front ();
834 info
->wave_stop_events
.pop_front ();
836 ptid_t
event_ptid (current_inferior ()->pid
, 1, event_wave_id
.handle
);
838 if (!find_thread_ptid (event_ptid
))
840 add_thread_silent (event_ptid
);
841 set_running (event_ptid
, 1);
842 set_executing (event_ptid
, 1);
845 /* Since we are manipulating the register cache for the event thread,
846 make sure it is the current thread. */
847 switch_to_thread (event_ptid
);
849 /* By caching the PC now, we avoid having to suspend/resume the queue
850 later when we need to access it. */
851 amd_dbgapi_global_address_t stop_pc
;
852 if (amd_dbgapi_wave_get_info (process_id
, event_wave_id
,
853 AMD_DBGAPI_WAVE_INFO_PC
, sizeof (stop_pc
),
855 == AMD_DBGAPI_STATUS_SUCCESS
)
857 struct regcache
*regcache
= get_thread_regcache (event_ptid
);
858 regcache
->raw_supply (gdbarch_pc_regnum (regcache
->arch ()), &stop_pc
);
860 ws
->kind
= TARGET_WAITKIND_STOPPED
;
863 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
864 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
))
865 ws
->value
.sig
= GDB_SIGNAL_TRAP
;
866 else if (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION
)
867 ws
->value
.sig
= GDB_SIGNAL_SEGV
;
869 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
870 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
871 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
872 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
873 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
874 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
875 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0
))
876 ws
->value
.sig
= GDB_SIGNAL_FPE
;
878 ws
->value
.sig
= GDB_SIGNAL_0
;
880 /* If there are more events in the list, mark the async file so that
881 rocm_target_ops::wait gets called again. */
882 if (target_is_async_p () && !info
->wave_stop_events
.empty ())
889 rocm_target_ops::stopped_by_sw_breakpoint ()
891 if (!ptid_is_gpu (inferior_ptid
))
892 return beneath ()->supports_stopped_by_sw_breakpoint ()
893 && beneath ()->stopped_by_sw_breakpoint ();
895 /* FIXME: we should check that the wave is not single-stepping. */
897 struct regcache
*regcache
= get_thread_regcache (inferior_ptid
);
899 CORE_ADDR bkpt_pc
= regcache_read_pc (regcache
)
900 - gdbarch_decr_pc_after_break (regcache
->arch ());
902 return software_breakpoint_inserted_here_p (regcache
->aspace (), bkpt_pc
);
906 rocm_target_ops::mourn_inferior ()
908 /* FIXME: only unpush on the last activation. */
909 /* Disengage the ROCm target_ops. */
910 unpush_target (&rocm_ops
);
912 beneath ()->mourn_inferior ();
916 rocm_target_ops::fetch_registers (struct regcache
*regcache
, int regno
)
918 struct gdbarch
*gdbarch
= regcache
->arch ();
919 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
921 /* delegate to the host routines when not on the device */
923 if (!rocm_is_amdgcn_gdbarch (gdbarch
))
925 beneath ()->fetch_registers (regcache
, regno
);
929 inferior
*inf
= find_inferior_ptid (regcache
->ptid ());
930 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (inf
);
931 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
933 gdb_byte raw
[AMDGCN_MAX_REGISTER_SIZE
];
935 amd_dbgapi_status_t status
= amd_dbgapi_read_register (
936 process_id
, wave_id
, tdep
->register_ids
[regno
], 0,
937 TYPE_LENGTH (register_type (gdbarch
, regno
)), raw
);
939 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
941 regcache
->raw_supply (regno
, raw
);
943 else if (status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_REGISTER_ID
)
945 warning (_ ("Couldn't read register %s (#%d)."),
946 gdbarch_register_name (gdbarch
, regno
), regno
);
951 rocm_target_ops::store_registers (struct regcache
*regcache
, int regno
)
953 struct gdbarch
*gdbarch
= regcache
->arch ();
954 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
955 gdb_byte raw
[AMDGCN_MAX_REGISTER_SIZE
];
957 if (!rocm_is_amdgcn_gdbarch (gdbarch
))
959 beneath ()->store_registers (regcache
, regno
);
963 inferior
*inf
= find_inferior_ptid (regcache
->ptid ());
964 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (inf
);
965 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
967 regcache
->raw_collect (regno
, &raw
);
969 amd_dbgapi_status_t status
= amd_dbgapi_write_register (
970 process_id
, wave_id
, tdep
->register_ids
[regno
], 0,
971 TYPE_LENGTH (register_type (gdbarch
, regno
)), raw
);
973 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
975 warning (_ ("Couldn't write register %s (#%d)."),
976 gdbarch_register_name (gdbarch
, regno
), regno
);
980 /* Fix breakpoints created with an address location while the
981 architecture was set to the host (could be fixed in core GDB). */
984 rocm_target_breakpoint_fixup (struct breakpoint
*b
)
986 if (b
->location
.get ()
987 && event_location_type (b
->location
.get ()) == ADDRESS_LOCATION
988 && gdbarch_bfd_arch_info (b
->loc
->gdbarch
)->arch
== bfd_arch_amdgcn
989 && gdbarch_bfd_arch_info (b
->gdbarch
)->arch
!= bfd_arch_amdgcn
)
991 b
->gdbarch
= b
->loc
->gdbarch
;
996 rocm_target_ops::thread_architecture (ptid_t ptid
)
998 static std::result_of
<decltype (&ptid_t::tid
) (ptid_t
)>::type last_tid
= 0;
999 static struct gdbarch
*cached_arch
= nullptr;
1001 if (!ptid_is_gpu (ptid
))
1002 return beneath ()->thread_architecture (ptid
);
1004 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
1005 wave IDs are unique, and aren't reused. */
1006 if (ptid
.tid () == last_tid
)
1009 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1010 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
1011 amd_dbgapi_architecture_id_t architecture_id
;
1013 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
1014 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
1015 sizeof (architecture_id
), &architecture_id
)
1016 != AMD_DBGAPI_STATUS_SUCCESS
)
1017 error (_ ("Couldn't get architecture for wave_%ld"), ptid
.tid ());
1019 uint32_t elf_amdgpu_machine
;
1020 if (amd_dbgapi_architecture_get_info (
1021 architecture_id
, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE
,
1022 sizeof (elf_amdgpu_machine
), &elf_amdgpu_machine
)
1023 != AMD_DBGAPI_STATUS_SUCCESS
)
1024 error (_ ("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1025 architecture_id
.handle
);
1027 struct gdbarch_info info
;
1028 gdbarch_info_init (&info
);
1030 info
.bfd_arch_info
= bfd_lookup_arch (bfd_arch_amdgcn
, elf_amdgpu_machine
);
1031 info
.byte_order
= BFD_ENDIAN_LITTLE
;
1032 info
.osabi
= GDB_OSABI_AMDGPU_HSA
;
1034 last_tid
= ptid
.tid ();
1035 if (!(cached_arch
= gdbarch_find_by_info (info
)))
1036 error (_ ("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine
);
1042 rocm_target_ops::update_thread_list ()
1044 for (inferior
*inf
: all_inferiors ())
1046 amd_dbgapi_process_id_t process_id
;
1047 amd_dbgapi_wave_id_t
*wave_list
;
1050 process_id
= get_amd_dbgapi_process_id (inf
);
1051 if (process_id
.handle
== AMD_DBGAPI_PROCESS_NONE
.handle
)
1053 /* The inferior may not be attached yet. */
1057 amd_dbgapi_changed_t changed
;
1058 amd_dbgapi_status_t status
;
1060 = amd_dbgapi_wave_list (process_id
, &count
, &wave_list
, &changed
))
1061 != AMD_DBGAPI_STATUS_SUCCESS
)
1062 error (_ ("amd_dbgapi_wave_list failed (rc=%d)"), status
);
1064 if (changed
== AMD_DBGAPI_CHANGED_NO
)
1067 /* Create a set and free the wave list. */
1068 std::set
<std::result_of
<decltype (&ptid_t::tid
) (ptid_t
)>::type
> threads
;
1069 for (size_t i
= 0; i
< count
; ++i
)
1070 threads
.emplace (wave_list
[i
].handle
);
1073 /* Then prune the wave_ids that already have a thread_info. */
1074 for (thread_info
*tp
: inf
->non_exited_threads ())
1075 if (ptid_is_gpu (tp
->ptid
))
1076 threads
.erase (tp
->ptid
.tid ());
1078 /* The wave_ids that are left require a new thread_info. */
1079 for (auto &&tid
: threads
)
1081 ptid_t
wave_ptid (inf
->pid
, 1, tid
);
1082 /* FIXME: is this really needed?
1083 amd_dbgapi_wave_state_t state;
1085 if (amd_dbgapi_wave_get_info (
1086 process_id, get_amd_dbgapi_wave_id (wave_ptid),
1087 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state), &state)
1088 != AMD_DBGAPI_STATUS_SUCCESS)
1091 add_thread_silent (wave_ptid
);
1092 set_running (wave_ptid
, 1);
1093 set_executing (wave_ptid
, 1);
1097 /* Give the beneath target a chance to do extra processing. */
1098 this->beneath ()->update_thread_list ();
1102 rocm_target_solib_loaded (struct so_list
*solib
)
1104 /* Notify the amd_dbgapi that a shared library has been loaded. */
1105 for (auto &&value
: get_rocm_inferior_info ()->notify_solib_map
)
1106 /* TODO: If we want to support file name wildcards, change this code. */
1107 if (::strstr (solib
->so_original_name
, value
.second
.compare
.c_str ())
1108 && !value
.second
.is_loaded
)
1110 value
.second
.solib
= solib
;
1111 value
.second
.is_loaded
= true;
1113 amd_dbgapi_report_shared_library (
1114 get_amd_dbgapi_process_id (),
1115 amd_dbgapi_shared_library_id_t
{ value
.first
},
1116 AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
);
1121 rocm_target_solib_unloaded (struct so_list
*solib
)
1123 /* Notify the amd_dbgapi that a shared library will unload. */
1124 for (auto &&value
: get_rocm_inferior_info ()->notify_solib_map
)
1125 /* TODO: If we want to support file name wildcards, change this code. */
1126 if (::strstr (solib
->so_original_name
, value
.second
.compare
.c_str ())
1127 && value
.second
.is_loaded
)
1129 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
1131 amd_dbgapi_report_shared_library (
1132 info
->process_id
, amd_dbgapi_shared_library_id_t
{ value
.first
},
1133 AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED
);
1135 /* Delete breakpoints that were left inserted in this shared library.
1137 for (auto it
= info
->breakpoint_map
.begin ();
1138 it
!= info
->breakpoint_map
.end ();)
1139 if (solib_contains_address_p (solib
, it
->second
->loc
->address
))
1141 warning (_ ("breakpoint_%ld is still inserted after "
1142 "shared_library_%ld was unloaded"),
1143 it
->first
, value
.first
);
1144 delete_breakpoint (it
->second
);
1145 it
= info
->breakpoint_map
.erase (it
);
1150 value
.second
.solib
= nullptr;
1151 value
.second
.is_loaded
= false;
1156 rocm_target_inferior_created (struct target_ops
*target
, int from_tty
)
1158 struct inferior
*inf
= current_inferior ();
1159 auto *info
= get_rocm_inferior_info (inf
);
1160 amd_dbgapi_status_t status
;
1162 if (!target_can_async_p ())
1165 _ ("ROCm-GDB requires target-async, GPU debugging is disabled"));
1169 gdb_assert (info
->wave_stop_events
.empty ());
1171 status
= amd_dbgapi_process_attach (inf
, &info
->process_id
);
1173 if (status
== AMD_DBGAPI_STATUS_ERROR_VERSION_MISMATCH
)
1174 warning (_ ("The version of the kernel driver does not match the version "
1175 "required by the ROCm debugger library"));
1177 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1179 warning (_ ("Could not attach to process %d"), inf
->pid
);
1183 if (amd_dbgapi_process_get_info (info
->process_id
,
1184 AMD_DBGAPI_PROCESS_INFO_NOTIFIER
,
1185 sizeof (info
->notifier
), &info
->notifier
)
1186 != AMD_DBGAPI_STATUS_SUCCESS
)
1188 warning (_ ("Could not retrieve process %d's notifier"), inf
->pid
);
1189 amd_dbgapi_process_detach (info
->process_id
);
1193 /* We add a file handler for events returned by the debugger api. We'll use
1194 this handler to signal our async handler that events are available. */
1197 [] (int error
, gdb_client_data client_data
) {
1198 auto info_
= static_cast<struct rocm_inferior_info
*> (client_data
);
1201 /* Drain the notifier pipe. */
1205 ret
= read (info_
->notifier
, &buf
, 1);
1207 while (ret
>= 0 || (ret
== -1 && errno
== EINTR
));
1209 /* Signal our async handler. */
1214 /* Attaching to the inferior may have generated runtime events, process
1216 rocm_process_event_queue ();
1220 rocm_target_inferior_exit (struct inferior
*inf
)
1222 auto *info
= get_rocm_inferior_info (inf
);
1224 amd_dbgapi_deactivated
.notify ();
1226 if (info
->notifier
!= -1)
1227 delete_file_handler (info
->notifier
);
1229 amd_dbgapi_process_detach (info
->process_id
);
1231 /* Delete the breakpoints that are still active. */
1232 for (auto &&value
: info
->breakpoint_map
)
1233 delete_breakpoint (value
.second
);
1235 rocm_inferior_data
.clear (inf
);
1238 static cli_style_option
warning_style ("rocm_warning", ui_file_style::RED
);
1239 static cli_style_option
info_style ("rocm_info", ui_file_style::GREEN
);
1240 static cli_style_option
verbose_style ("rocm_verbose", ui_file_style::BLUE
);
1242 static amd_dbgapi_callbacks_t dbgapi_callbacks
= {
1243 /* allocate_memory. */
1244 .allocate_memory
= xmalloc
,
1246 /* deallocate_memory. */
1247 .deallocate_memory
= xfree
,
1250 .get_os_pid
= [] (amd_dbgapi_client_process_id_t client_process_id
,
1251 pid_t
*pid
) -> amd_dbgapi_status_t
{
1252 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1255 return AMD_DBGAPI_STATUS_SUCCESS
;
1258 /* enable_notify_shared_library callback. */
1259 .enable_notify_shared_library
1260 = [] (amd_dbgapi_client_process_id_t client_process_id
,
1261 const char *library_name
, amd_dbgapi_shared_library_id_t library_id
,
1262 amd_dbgapi_shared_library_state_t
*library_state
)
1263 -> amd_dbgapi_status_t
{
1264 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1265 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1267 if (!library_name
|| !library_state
)
1268 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1270 if (info
->notify_solib_map
.find (library_id
.handle
)
1271 != info
->notify_solib_map
.end ())
1273 /* This library id is already registered. */
1274 return AMD_DBGAPI_STATUS_ERROR
;
1277 /* Check whether the library is already loaded. */
1278 bool is_loaded
= false;
1279 struct so_list
*solib
;
1280 for (solib
= inf
->pspace
->so_list
; solib
; solib
= solib
->next
)
1281 if (::strstr (solib
->so_original_name
, library_name
))
1287 /* Check that the library_name is valid. If must not be empty, and
1288 should not have wildcard characters. */
1289 if (*library_name
== '\0'
1290 || std::string (library_name
).find_first_of ("*?[]")
1291 != std::string::npos
)
1292 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1294 /* Add a new entry in the notify_solib_map. */
1295 if (!info
->notify_solib_map
1296 .emplace (std::piecewise_construct
,
1297 std::forward_as_tuple (library_id
.handle
),
1298 std::forward_as_tuple (rocm_notify_shared_library_info
{
1299 library_name
, solib
, is_loaded
}))
1301 return AMD_DBGAPI_STATUS_ERROR
;
1303 *library_state
= is_loaded
? AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
1304 : AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED
;
1306 return AMD_DBGAPI_STATUS_SUCCESS
;
1309 /* disable_notify_shared_library callback. */
1310 .disable_notify_shared_library
1311 = [] (amd_dbgapi_client_process_id_t client_process_id
,
1312 amd_dbgapi_shared_library_id_t library_id
) -> amd_dbgapi_status_t
{
1313 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1314 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1316 auto it
= info
->notify_solib_map
.find (library_id
.handle
);
1317 if (it
== info
->notify_solib_map
.end ())
1318 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID
;
1320 info
->notify_solib_map
.erase (it
);
1321 return AMD_DBGAPI_STATUS_SUCCESS
;
1324 /* get_symbol_address callback. */
1325 .get_symbol_address
=
1326 [] (amd_dbgapi_client_process_id_t client_process_id
,
1327 amd_dbgapi_shared_library_id_t library_id
, const char *symbol_name
,
1328 amd_dbgapi_global_address_t
*address
) {
1329 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1330 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1332 auto it
= info
->notify_solib_map
.find (library_id
.handle
);
1333 if (it
== info
->notify_solib_map
.end ())
1334 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID
;
1336 struct so_list
*solib
= it
->second
.solib
;
1338 return AMD_DBGAPI_STATUS_ERROR_LIBRARY_NOT_LOADED
;
1340 solib_read_symbols (solib
, 0);
1341 gdb_assert (solib
->objfile
);
1343 struct bound_minimal_symbol msymbol
1344 = lookup_minimal_symbol (symbol_name
, NULL
, solib
->objfile
);
1346 if (!msymbol
.minsym
|| BMSYMBOL_VALUE_ADDRESS (msymbol
) == 0)
1347 return AMD_DBGAPI_STATUS_ERROR_SYMBOL_NOT_FOUND
;
1349 *address
= BMSYMBOL_VALUE_ADDRESS (msymbol
);
1350 return AMD_DBGAPI_STATUS_SUCCESS
;
1353 /* set_breakpoint callback. */
1355 [] (amd_dbgapi_client_process_id_t client_process_id
,
1356 amd_dbgapi_shared_library_id_t shared_library_id
,
1357 amd_dbgapi_global_address_t address
,
1358 amd_dbgapi_breakpoint_id_t breakpoint_id
) {
1359 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1360 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1362 /* Initialize the breakpoint ops lazily since we depend on
1363 bkpt_breakpoint_ops and we can't control the order in which
1364 initializers are called. */
1365 if (rocm_breakpoint_ops
.check_status
== NULL
)
1367 rocm_breakpoint_ops
= bkpt_breakpoint_ops
;
1368 rocm_breakpoint_ops
.check_status
= rocm_breakpoint_check_status
;
1369 rocm_breakpoint_ops
.re_set
= rocm_breakpoint_re_set
;
1372 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1373 if (it
!= info
->breakpoint_map
.end ())
1374 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1376 /* Create a new breakpoint. */
1377 struct obj_section
*section
= find_pc_section (address
);
1378 if (!section
|| !section
->objfile
)
1379 return AMD_DBGAPI_STATUS_ERROR
;
1381 event_location_up location
1382 = new_address_location (address
, nullptr, 0);
1383 if (!create_breakpoint (
1384 get_objfile_arch (section
->objfile
), location
.get (),
1385 /*cond_string*/ NULL
, /*thread*/ -1, /*extra_sring*/ NULL
,
1386 /*parse_extra*/ 0, /*tempflag*/ 0, /*bptype*/ bp_breakpoint
,
1387 /*ignore_count*/ 0, /*pending_break*/ AUTO_BOOLEAN_FALSE
,
1388 /*ops*/ &rocm_breakpoint_ops
, /*from_tty*/ 0,
1389 /*enabled*/ 1, /*internal*/ 1, /*flags*/ 0))
1390 return AMD_DBGAPI_STATUS_ERROR
;
1392 /* Find our breakpoint in the breakpoint list. */
1393 auto bp_loc
= std::make_pair (inf
->aspace
, address
);
1394 auto bp
= breakpoint_find_if (
1395 [] (struct breakpoint
*b
, void *data
) {
1396 auto *arg
= static_cast<decltype (&bp_loc
)> (data
);
1397 if (b
->ops
== &rocm_breakpoint_ops
&& b
->loc
1398 && b
->loc
->pspace
->aspace
== arg
->first
1399 && b
->loc
->address
== arg
->second
)
1403 reinterpret_cast<void *> (&bp_loc
));
1406 error (_ ("Could not find breakpoint"));
1408 info
->breakpoint_map
.emplace (breakpoint_id
.handle
, bp
);
1409 return AMD_DBGAPI_STATUS_SUCCESS
;
1412 /* remove_breakpoint callback. */
1413 .remove_breakpoint
=
1414 [] (amd_dbgapi_client_process_id_t client_process_id
,
1415 amd_dbgapi_breakpoint_id_t breakpoint_id
) {
1416 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1417 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1419 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1420 if (it
== info
->breakpoint_map
.end ())
1421 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1423 delete_breakpoint (it
->second
);
1424 info
->breakpoint_map
.erase (it
);
1426 return AMD_DBGAPI_STATUS_SUCCESS
;
1429 /* set_breakpoint_state callback. */
1430 .set_breakpoint_state
=
1431 [] (amd_dbgapi_client_process_id_t client_process_id
,
1432 amd_dbgapi_breakpoint_id_t breakpoint_id
,
1433 amd_dbgapi_breakpoint_state_t breakpoint_state
) {
1434 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1435 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1437 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1438 if (it
== info
->breakpoint_map
.end ())
1439 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1441 if (breakpoint_state
== AMD_DBGAPI_BREAKPOINT_STATE_ENABLE
)
1442 it
->second
->enable_state
= bp_enabled
;
1443 else if (breakpoint_state
== AMD_DBGAPI_BREAKPOINT_STATE_DISABLE
)
1444 it
->second
->enable_state
= bp_disabled
;
1446 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1448 return AMD_DBGAPI_STATUS_SUCCESS
;
1452 = [] (amd_dbgapi_log_level_t level
, const char *message
) -> void {
1453 gdb::optional
<target_terminal::scoped_restore_terminal_state
> tstate
;
1455 if (level
> get_debug_amd_dbgapi_log_level ())
1458 if (target_supports_terminal_ours ())
1461 target_terminal::ours_for_output ();
1464 if (filtered_printing_initialized ())
1467 struct ui_file
*out_file
1468 = (level
>= AMD_DBGAPI_LOG_LEVEL_INFO
) ? gdb_stdlog
: gdb_stderr
;
1472 case AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
:
1473 fputs_unfiltered ("[amd-dbgapi]: ", out_file
);
1475 case AMD_DBGAPI_LOG_LEVEL_WARNING
:
1476 fputs_styled ("[amd-dbgapi]: ", warning_style
.style (), out_file
);
1478 case AMD_DBGAPI_LOG_LEVEL_INFO
:
1479 fputs_styled ("[amd-dbgapi]: ", info_style
.style (), out_file
);
1481 case AMD_DBGAPI_LOG_LEVEL_VERBOSE
:
1482 fputs_styled ("[amd-dbgapi]: ", verbose_style
.style (), out_file
);
1486 fputs_unfiltered (message
, out_file
);
1487 fputs_unfiltered ("\n", out_file
);
1491 /* Implementation of `_wave_id' variable. */
1493 static struct value
*
1494 rocm_wave_id_make_value (struct gdbarch
*gdbarch
, struct internalvar
*var
,
1497 if (ptid_is_gpu (inferior_ptid
))
1499 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1500 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
1501 uint32_t group_ids
[3], wave_in_group
;
1503 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
1504 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD
,
1505 sizeof (group_ids
), &group_ids
)
1506 == AMD_DBGAPI_STATUS_SUCCESS
1507 && amd_dbgapi_wave_get_info (
1508 process_id
, wave_id
,
1509 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP
,
1510 sizeof (wave_in_group
), &wave_in_group
)
1511 == AMD_DBGAPI_STATUS_SUCCESS
)
1513 std::string wave_id_str
1514 = string_printf ("(%d,%d,%d)/%d", group_ids
[2], group_ids
[1],
1515 group_ids
[0], wave_in_group
);
1517 return value_cstring (wave_id_str
.data (), wave_id_str
.length () + 1,
1518 builtin_type (gdbarch
)->builtin_char
);
1522 return allocate_value (builtin_type (gdbarch
)->builtin_void
);
1525 static const struct internalvar_funcs rocm_wave_id_funcs
1526 = { rocm_wave_id_make_value
, NULL
, NULL
};
1528 /* List of set/show debug amd_dbgapi commands. */
1529 struct cmd_list_element
*set_debug_amd_dbgapi_list
;
1530 struct cmd_list_element
*show_debug_amd_dbgapi_list
;
1533 set_debug_amd_dbgapi (const char *arg
, int from_tty
)
1535 help_list (set_debug_amd_dbgapi_list
, "set debug amd-dbgapi ",
1536 (enum command_class
) - 1, gdb_stdout
);
1540 show_debug_amd_dbgapi (const char *args
, int from_tty
)
1542 cmd_show_list (show_debug_amd_dbgapi_list
, from_tty
, "");
1545 constexpr char amd_dbgapi_log_level_off
[] = "off";
1546 constexpr char amd_dbgapi_log_level_error
[] = "error";
1547 constexpr char amd_dbgapi_log_level_warning
[] = "warning";
1548 constexpr char amd_dbgapi_log_level_info
[] = "info";
1549 constexpr char amd_dbgapi_log_level_verbose
[] = "verbose";
1551 constexpr const char *debug_amd_dbgapi_log_level_enums
[]
1552 = { [AMD_DBGAPI_LOG_LEVEL_NONE
] = amd_dbgapi_log_level_off
,
1553 [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
] = amd_dbgapi_log_level_error
,
1554 [AMD_DBGAPI_LOG_LEVEL_WARNING
] = amd_dbgapi_log_level_warning
,
1555 [AMD_DBGAPI_LOG_LEVEL_INFO
] = amd_dbgapi_log_level_info
,
1556 [AMD_DBGAPI_LOG_LEVEL_VERBOSE
] = amd_dbgapi_log_level_verbose
,
1559 static const char *debug_amd_dbgapi_log_level
= amd_dbgapi_log_level_error
;
1561 static amd_dbgapi_log_level_t
1562 get_debug_amd_dbgapi_log_level ()
1565 for (pos
= 0; debug_amd_dbgapi_log_level_enums
[pos
]; ++pos
)
1566 if (debug_amd_dbgapi_log_level
== debug_amd_dbgapi_log_level_enums
[pos
])
1569 gdb_assert (debug_amd_dbgapi_log_level_enums
[pos
]);
1570 return static_cast<amd_dbgapi_log_level_t
> (pos
);
1574 set_debug_amd_dbgapi_log_level (const char *args
, int from_tty
,
1575 struct cmd_list_element
*c
)
1577 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1581 show_debug_amd_dbgapi_log_level (struct ui_file
*file
, int from_tty
,
1582 struct cmd_list_element
*c
,
1585 fprintf_filtered (file
, _ ("The amd-dbgapi log level is %s.\n"), value
);
1589 info_agents_command (const char *args
, int from_tty
)
1591 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1592 struct ui_out
*uiout
= current_uiout
;
1593 amd_dbgapi_status_t status
;
1595 amd_dbgapi_agent_id_t
*agent_list
;
1598 if (process_id
.handle
!= AMD_DBGAPI_PROCESS_NONE
.handle
1600 = amd_dbgapi_agent_list (process_id
, &count
, &agent_list
, nullptr))
1601 != AMD_DBGAPI_STATUS_SUCCESS
)
1602 error (_ ("amd_dbgapi_agent_list failed (rc=%d)"), status
);
1604 if (!count
&& !uiout
->is_mi_like_p ())
1606 uiout
->field_string (NULL
,
1607 _ ("No agents are currently active.\n"));
1611 /* Calculate the maximum size needed to print the agents names. */
1612 std::vector
<std::string
> agent_names (count
);
1614 size_t max_name_len
= 0;
1615 for (size_t i
= 0; i
< count
; ++i
)
1619 if ((status
= amd_dbgapi_agent_get_info (
1620 process_id
, agent_list
[i
], AMD_DBGAPI_AGENT_INFO_NAME
,
1621 sizeof (agent_name
), &agent_name
))
1622 != AMD_DBGAPI_STATUS_SUCCESS
)
1624 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID
)
1625 agent_names
[i
] = "N/A";
1627 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status
);
1631 agent_names
[i
] = agent_name
;
1635 max_name_len
= std::max (max_name_len
, agent_names
[i
].size ());
1639 ui_out_emit_table
table_emmitter (uiout
, 7, count
, "InfoRocmDevicesTable");
1641 uiout
->table_header (2, ui_left
, "agent_id", "Id");
1642 uiout
->table_header (8, ui_left
, "location_id", "PCI Slot");
1643 uiout
->table_header (std::max (11ul, max_name_len
), ui_left
, "name",
1645 uiout
->table_header (14, ui_left
, "num_se", "Shader Engines");
1646 uiout
->table_header (13, ui_left
, "num_cu", "Compute Units");
1647 uiout
->table_header (7, ui_left
, "simd", "SIMD/CU");
1648 uiout
->table_header (15, ui_left
, "waves", "Wavefronts/SIMD");
1649 uiout
->table_body ();
1652 for (size_t i
= 0; i
< count
; ++i
)
1654 ui_out_emit_tuple
tuple_emitter (uiout
, "InfoRocmDevicesRow");
1657 uiout
->field_signed ("agent_id", agent_list
[i
].handle
);
1660 uint32_t location_id
;
1661 if ((status
= amd_dbgapi_agent_get_info (
1662 process_id
, agent_list
[i
], AMD_DBGAPI_AGENT_INFO_PCIE_SLOT
,
1663 sizeof (location_id
), &location_id
))
1664 != AMD_DBGAPI_STATUS_SUCCESS
)
1666 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID
)
1667 uiout
->field_string ("location_id", "N/A");
1669 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status
);
1672 uiout
->field_string (
1674 string_printf ("%02x:%02x.%d", (location_id
>> 8) & 0xFF,
1675 (location_id
>> 3) & 0x1F, location_id
& 0x7));
1678 uiout
->field_string ("name", agent_names
[i
]);
1680 /* num_se, num_cu, simd, waves */
1682 #define UIOUT_FIELD_INT(name, query) \
1684 if ((status = amd_dbgapi_agent_get_info (process_id, agent_list[i], query, \
1685 sizeof (name), &name)) \
1686 != AMD_DBGAPI_STATUS_SUCCESS) \
1688 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID) \
1689 uiout->field_string (#name, "N/A"); \
1691 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status); \
1694 uiout->field_signed (#name, name);
1696 UIOUT_FIELD_INT (num_se
, AMD_DBGAPI_AGENT_INFO_SHADER_ENGINE_COUNT
);
1697 UIOUT_FIELD_INT (num_cu
, AMD_DBGAPI_AGENT_INFO_COMPUTE_UNIT_COUNT
);
1698 UIOUT_FIELD_INT (simd
, AMD_DBGAPI_AGENT_INFO_NUM_SIMD_PER_COMPUTE_UNIT
);
1699 UIOUT_FIELD_INT (waves
, AMD_DBGAPI_AGENT_INFO_MAX_WAVES_PER_SIMD
);
1701 #undef UIOUT_FIELD_INT
1707 gdb_flush (gdb_stdout
);
1710 /* -Wmissing-prototypes */
1711 extern initialize_file_ftype _initialize_rocm_tdep
;
1714 _initialize_rocm_tdep (void)
1716 /* Initialize the ROCm Debug API. */
1717 if (amd_dbgapi_initialize (&dbgapi_callbacks
) != AMD_DBGAPI_STATUS_SUCCESS
)
1720 /* Set the initial log level. */
1721 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1723 /* Install observers. */
1724 gdb::observers::breakpoint_created
.attach (rocm_target_breakpoint_fixup
);
1725 gdb::observers::solib_loaded
.attach (rocm_target_solib_loaded
);
1726 gdb::observers::solib_unloaded
.attach (rocm_target_solib_unloaded
);
1727 gdb::observers::inferior_created
.attach (rocm_target_inferior_created
);
1728 gdb::observers::inferior_exit
.attach (rocm_target_inferior_exit
);
1730 amd_dbgapi_activated
.attach (rocm_target_dbgapi_activated
);
1731 amd_dbgapi_deactivated
.attach (rocm_target_dbgapi_deactivated
);
1733 create_internalvar_type_lazy ("_wave_id", &rocm_wave_id_funcs
, NULL
);
1736 "amd-dbgapi", no_class
, set_debug_amd_dbgapi
,
1737 _ ("Generic command for setting amd-dbgapi debugging flags"),
1738 &set_debug_amd_dbgapi_list
, "set debug amd-dbgapi ", 0, &setdebuglist
);
1741 "amd-dbgapi", no_class
, show_debug_amd_dbgapi
,
1742 _ ("Generic command for showing amd-dbgapi debugging flags"),
1743 &show_debug_amd_dbgapi_list
, "show debug amd-dbgapi ", 0,
1746 add_setshow_enum_cmd (
1747 "log-level", class_maintenance
, debug_amd_dbgapi_log_level_enums
,
1748 &debug_amd_dbgapi_log_level
, _ ("Set the amd-dbgapi log level."),
1749 _ ("Show the amd-dbgapi log level."),
1750 _ ("off == no logging is enabled\n"
1751 "error == fatal errors are reported\n"
1752 "warning == fatal errors and warnings are reported\n"
1753 "info == fatal errors, warnings, and info messages are reported\n"
1754 "verbose == all messages are reported"),
1755 set_debug_amd_dbgapi_log_level
, show_debug_amd_dbgapi_log_level
,
1756 &set_debug_amd_dbgapi_list
, &show_debug_amd_dbgapi_list
);
1758 add_cmd ("agents", class_info
, info_agents_command
,
1759 _ ("Info about currently active agents."), &infolist
);