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_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 amd_dbgapi_wave_state_t state
;
354 return amd_dbgapi_wave_get_info (
355 get_amd_dbgapi_process_id (), get_amd_dbgapi_wave_id (ptid
),
356 AMD_DBGAPI_WAVE_INFO_STATE
, sizeof (state
), &state
)
357 == AMD_DBGAPI_STATUS_SUCCESS
;
361 rocm_target_ops::thread_name (thread_info
*tp
)
363 if (!ptid_is_gpu (tp
->ptid
))
364 return beneath ()->thread_name (tp
);
366 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
367 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (tp
->ptid
);
368 amd_dbgapi_dispatch_id_t dispatch_id
;
369 amd_dbgapi_global_address_t kernel_addr
;
371 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
372 AMD_DBGAPI_WAVE_INFO_DISPATCH
,
373 sizeof (dispatch_id
), &dispatch_id
)
374 != AMD_DBGAPI_STATUS_SUCCESS
375 || amd_dbgapi_dispatch_get_info (
376 process_id
, dispatch_id
,
377 AMD_DBGAPI_DISPATCH_INFO_KERNEL_ENTRY_ADDRESS
,
378 sizeof (kernel_addr
), &kernel_addr
)
379 != AMD_DBGAPI_STATUS_SUCCESS
)
382 struct bound_minimal_symbol msymbol
383 = lookup_minimal_symbol_by_pc_section (kernel_addr
, nullptr);
385 if (msymbol
.minsym
!= NULL
)
387 static char buf
[256];
390 xsnprintf (buf
, sizeof (buf
), "%s", msymbol
.minsym
->print_name ());
392 /* Strip the arguments from the demangled function name. */
393 if ((endp
= strchr (buf
, '(')))
403 rocm_target_ops::pid_to_str (ptid_t ptid
)
405 if (!ptid_is_gpu (ptid
))
407 return beneath ()->pid_to_str (ptid
);
410 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
411 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
412 amd_dbgapi_dispatch_id_t dispatch_id
;
413 uint32_t group_ids
[3], wave_in_group
;
415 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
416 AMD_DBGAPI_WAVE_INFO_DISPATCH
,
417 sizeof (dispatch_id
), &dispatch_id
)
418 != AMD_DBGAPI_STATUS_SUCCESS
419 || amd_dbgapi_wave_get_info (process_id
, wave_id
,
420 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD
,
421 sizeof (group_ids
), &group_ids
)
422 != AMD_DBGAPI_STATUS_SUCCESS
423 || amd_dbgapi_wave_get_info (
425 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP
,
426 sizeof (wave_in_group
), &wave_in_group
)
427 != AMD_DBGAPI_STATUS_SUCCESS
)
428 return std::string ("AMDGPU Thread");
430 return string_printf ("AMDGPU Thread %ld.%ld (%d,%d,%d)/%d",
431 dispatch_id
.handle
, wave_id
.handle
, group_ids
[2],
432 group_ids
[1], group_ids
[0], wave_in_group
);
436 rocm_target_ops::extra_thread_info (thread_info
*tp
)
438 if (!ptid_is_gpu (tp
->ptid
))
439 beneath ()->extra_thread_info (tp
);
444 enum target_xfer_status
445 rocm_target_ops::xfer_partial (enum target_object object
, const char *annex
,
446 gdb_byte
*readbuf
, const gdb_byte
*writebuf
,
447 ULONGEST offset
, ULONGEST requested_len
,
448 ULONGEST
*xfered_len
)
450 gdb::optional
<scoped_restore_current_thread
> maybe_restore_thread
;
452 if (ptid_is_gpu (inferior_ptid
))
454 gdb_assert (requested_len
&& xfered_len
&& "checking invariants");
456 if (object
!= TARGET_OBJECT_MEMORY
)
457 return TARGET_XFER_E_IO
;
459 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
460 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
462 amd_dbgapi_architecture_id_t architecture_id
;
463 amd_dbgapi_address_space_id_t address_space_id
;
465 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
466 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
467 sizeof (architecture_id
), &architecture_id
)
468 != AMD_DBGAPI_STATUS_SUCCESS
469 || amd_dbgapi_architecture_get_info (
471 AMD_DBGAPI_ARCHITECTURE_INFO_DEFAULT_GLOBAL_ADDRESS_SPACE
,
472 sizeof (address_space_id
), &address_space_id
)
473 != AMD_DBGAPI_STATUS_SUCCESS
)
474 error (_ ("Couldn't get default global address space"));
476 size_t len
= requested_len
;
477 amd_dbgapi_status_t status
;
480 status
= amd_dbgapi_read_memory (
481 process_id
, wave_id
, 0, address_space_id
, offset
, &len
, readbuf
);
483 status
= amd_dbgapi_write_memory (
484 process_id
, wave_id
, 0, address_space_id
, offset
, &len
, writebuf
);
486 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
488 if (status
!= AMD_DBGAPI_STATUS_ERROR_MEMORY_ACCESS
)
489 error (_ ("amd_dbgapi_%s_memory failed (rc=%d"),
490 readbuf
? "read" : "write", status
);
491 return TARGET_XFER_EOF
;
495 return TARGET_XFER_OK
;
498 return beneath ()->xfer_partial (object
, annex
, readbuf
, writebuf
, offset
,
499 requested_len
, xfered_len
);
503 rocm_target_ops::resume (ptid_t ptid
, int step
, enum gdb_signal signo
)
505 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
510 "\e[1;34minfrun: rocm_target_ops::resume ([%d,%ld,%ld])\e[0m\n",
511 ptid
.pid (), ptid
.lwp (), ptid
.tid ());
513 /* Check if the thread focus is on the GPU device. */
514 if (ptid
== minus_one_ptid
|| !ptid_is_gpu (ptid
))
516 beneath ()->resume (ptid
, step
, signo
);
517 if (ptid
!= minus_one_ptid
)
521 /* A specific PTID means `step only this process id'. */
522 bool resume_one
= ptid
!= minus_one_ptid
&& !ptid
.is_pid ();
523 gdb_assert (resume_one
|| !step
);
526 error (_ ("internal error - unimplemented "));
528 amd_dbgapi_process_set_progress (info
->process_id
,
529 AMD_DBGAPI_PROGRESS_NO_FORWARD
);
531 amd_dbgapi_status_t status
= amd_dbgapi_wave_resume (
532 info
->process_id
, get_amd_dbgapi_wave_id (ptid
),
533 step
? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
534 : AMD_DBGAPI_RESUME_MODE_NORMAL
);
535 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
536 warning (_ ("Could not resume %s (rc=%d)"),
537 target_pid_to_str (ptid
).c_str (), status
);
539 info
->commit_resume_all_start
= true;
543 rocm_target_ops::commit_resume ()
545 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
550 "\e[1;34minfrun: rocm_target_ops::commit_resume ()\e[0m\n");
552 beneath ()->commit_resume ();
554 if (info
->commit_resume_all_start
)
556 amd_dbgapi_process_set_progress (info
->process_id
,
557 AMD_DBGAPI_PROGRESS_NORMAL
);
558 info
->commit_resume_all_start
= false;
561 if (target_can_async_p ())
566 rocm_target_stop_one_wave (ptid_t ptid
)
568 amd_dbgapi_status_t status
;
570 status
= amd_dbgapi_wave_stop (get_amd_dbgapi_process_id (),
571 get_amd_dbgapi_wave_id (ptid
));
573 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
575 /* the wave must have exited, set the thread status to reflect that. */
576 auto *tp
= find_thread_ptid (current_inferior (), ptid
);
579 tp
->state
= THREAD_EXITED
;
581 else if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
582 warning (_ ("Could not stop %s (rc=%d)"),
583 target_pid_to_str (ptid
).c_str (), status
);
587 rocm_target_ops::stop (ptid_t ptid
)
592 "\e[1;34minfrun: rocm_target_ops::stop ([%d,%ld,%ld])\e[0m\n",
593 ptid
.pid (), ptid
.lwp (), ptid
.tid ());
595 if (ptid
== minus_one_ptid
|| !ptid_is_gpu (ptid
))
597 beneath ()->stop (ptid
);
598 if (ptid
!= minus_one_ptid
)
602 if (ptid
== minus_one_ptid
)
603 error (_ ("internal error - unimplemented "));
605 rocm_target_stop_one_wave (ptid
);
609 handle_target_event (int error
, gdb_client_data client_data
)
611 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
612 amd_dbgapi_process_id_t process_id
= info
->process_id
;
614 amd_dbgapi_process_set_progress (process_id
, AMD_DBGAPI_PROGRESS_NO_FORWARD
);
616 /* Flush the async file first. */
617 if (target_is_async_p ())
620 rocm_process_event_queue ();
622 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
623 we can keep the process in progress_no_forward mode. The infrun loop
624 will enable forward progress when a thread is resumed. */
625 if (non_stop
|| info
->wave_stop_events
.empty ())
626 amd_dbgapi_process_set_progress (process_id
, AMD_DBGAPI_PROGRESS_NORMAL
);
628 if (!info
->wave_stop_events
.empty ())
629 inferior_event_handler (INF_REG_EVENT
, nullptr);
633 rocm_target_ops::async (int enable
)
635 beneath ()->async (enable
);
639 if (rocm_event_pipe
[0] != -1)
642 if (gdb_pipe_cloexec (rocm_event_pipe
) == -1)
643 internal_error (__FILE__
, __LINE__
, "creating event pipe failed.");
645 ::fcntl (rocm_event_pipe
[0], F_SETFL
, O_NONBLOCK
);
646 ::fcntl (rocm_event_pipe
[1], F_SETFL
, O_NONBLOCK
);
648 add_file_handler (rocm_event_pipe
[0], handle_target_event
, nullptr);
650 /* There may be pending events to handle. Tell the event loop
656 delete_file_handler (rocm_event_pipe
[0]);
658 if (rocm_event_pipe
[0] == -1)
661 ::close (rocm_event_pipe
[0]);
662 ::close (rocm_event_pipe
[1]);
663 rocm_event_pipe
[0] = -1;
664 rocm_event_pipe
[1] = -1;
669 rocm_process_one_event (amd_dbgapi_event_id_t event_id
,
670 amd_dbgapi_event_kind_t event_kind
)
672 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
673 amd_dbgapi_process_id_t process_id
= info
->process_id
;
674 amd_dbgapi_status_t status
;
678 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP
:
680 amd_dbgapi_wave_id_t wave_id
;
681 if ((status
= amd_dbgapi_event_get_info (process_id
, event_id
,
682 AMD_DBGAPI_EVENT_INFO_WAVE
,
683 sizeof (wave_id
), &wave_id
))
684 != AMD_DBGAPI_STATUS_SUCCESS
)
685 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
686 event_id
.handle
, status
);
688 amd_dbgapi_wave_stop_reason_t stop_reason
;
689 status
= amd_dbgapi_wave_get_info (process_id
, wave_id
,
690 AMD_DBGAPI_WAVE_INFO_STOP_REASON
,
691 sizeof (stop_reason
), &stop_reason
);
693 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
694 && status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID
)
695 error (_ ("wave_get_info for wave_%ld failed (rc=%d)"),
696 wave_id
.handle
, status
);
698 /* The wave may have exited, or the queue went into an error
699 state. In such cases, we will see another wave command
700 terminated event, and handle the wave termination then. */
702 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
703 info
->wave_stop_events
.emplace_back (
704 std::make_pair (wave_id
, stop_reason
));
708 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED
:
709 amd_dbgapi_code_object_list_updated
.notify ();
712 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME
:
713 /* Breakpoint resume events should be handled by the breakpoint
714 action, and this code should not reach this. */
715 gdb_assert_not_reached (_ ("unhandled event kind"));
718 case AMD_DBGAPI_EVENT_KIND_RUNTIME
:
720 amd_dbgapi_runtime_state_t runtime_state
;
722 if ((status
= amd_dbgapi_event_get_info (
723 process_id
, event_id
, AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE
,
724 sizeof (runtime_state
), &runtime_state
))
725 != AMD_DBGAPI_STATUS_SUCCESS
)
726 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
727 event_id
.handle
, status
);
729 switch (runtime_state
)
731 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUPPORTED
:
732 amd_dbgapi_activated
.notify ();
734 case AMD_DBGAPI_RUNTIME_STATE_LOADED_UNSUPPORTED
:
735 warning (_ ("ROCm-GDB: low-level runtime version not supported"));
738 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED
:
739 amd_dbgapi_deactivated
.notify ();
746 error (_ ("event kind (%d) not supported"), event_kind
);
749 amd_dbgapi_event_processed (process_id
, event_id
);
752 /* Drain the amd_dbgapi event queue until an event of the given type is seen.
753 If no particular event kind is specified (AMD_DBGAPI_EVENT_KIND_NONE), the
754 event queue is completely drained. Wave stop events that are not returned
755 are re-queued into the current's process pending wave events. */
756 static amd_dbgapi_event_id_t
757 rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind
)
759 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
763 amd_dbgapi_event_id_t event_id
;
764 amd_dbgapi_event_kind_t event_kind
;
766 amd_dbgapi_status_t status
= amd_dbgapi_next_pending_event (
767 info
->process_id
, &event_id
, &event_kind
);
769 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
770 error (_ ("next_pending_event failed (rc=%d)"), status
);
772 if (event_id
.handle
== AMD_DBGAPI_EVENT_NONE
.handle
773 || event_kind
== until_event_kind
)
776 rocm_process_one_event (event_id
, event_kind
);
781 rocm_target_ops::wait (ptid_t ptid
, struct target_waitstatus
*ws
,
785 fprintf_unfiltered (gdb_stdlog
,
786 "\e[1;34minfrun: rocm_target_ops::wait\e[0m\n");
788 if (!ptid_is_gpu (ptid
))
790 ptid_t event_ptid
= beneath ()->wait (ptid
, ws
, target_options
);
791 if (event_ptid
!= minus_one_ptid
)
795 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
796 amd_dbgapi_process_id_t process_id
= info
->process_id
;
798 /* Drain all the events from the amd_dbgapi, and preserve the ordering. */
799 if (info
->wave_stop_events
.empty ())
801 amd_dbgapi_process_set_progress (process_id
,
802 AMD_DBGAPI_PROGRESS_NO_FORWARD
);
804 /* Flush the async file first. */
805 if (target_is_async_p ())
808 rocm_process_event_queue ();
810 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
811 we can keep the process in progress_no_forward mode. The infrun loop
812 will enable forward progress when a thread is resumed. */
813 if (non_stop
|| info
->wave_stop_events
.empty ())
814 amd_dbgapi_process_set_progress (process_id
,
815 AMD_DBGAPI_PROGRESS_NORMAL
);
818 if (info
->wave_stop_events
.empty ())
819 return minus_one_ptid
;
821 amd_dbgapi_wave_id_t event_wave_id
;
822 amd_dbgapi_wave_stop_reason_t stop_reason
;
824 std::tie (event_wave_id
, stop_reason
) = info
->wave_stop_events
.front ();
825 info
->wave_stop_events
.pop_front ();
827 struct inferior
*inf
= current_inferior ();
828 ptid_t
event_ptid (inf
->pid
, 1, event_wave_id
.handle
);
830 if (!find_thread_ptid (inf
->process_target (), event_ptid
))
832 add_thread_silent (inf
->process_target (), event_ptid
);
833 set_running (inf
->process_target (), event_ptid
, 1);
834 set_executing (inf
->process_target (), event_ptid
, 1);
837 /* Since we are manipulating the register cache for the event thread,
838 make sure it is the current thread. */
839 switch_to_thread (inf
->process_target (), event_ptid
);
841 /* By caching the PC now, we avoid having to suspend/resume the queue
842 later when we need to access it. */
843 amd_dbgapi_global_address_t stop_pc
;
844 if (amd_dbgapi_wave_get_info (process_id
, event_wave_id
,
845 AMD_DBGAPI_WAVE_INFO_PC
, sizeof (stop_pc
),
847 == AMD_DBGAPI_STATUS_SUCCESS
)
849 struct regcache
*regcache
= get_thread_regcache_for_ptid (event_ptid
);
850 regcache
->raw_supply (gdbarch_pc_regnum (regcache
->arch ()), &stop_pc
);
852 ws
->kind
= TARGET_WAITKIND_STOPPED
;
855 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
856 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
))
857 ws
->value
.sig
= GDB_SIGNAL_TRAP
;
858 else if (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION
)
859 ws
->value
.sig
= GDB_SIGNAL_SEGV
;
861 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
862 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
863 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
864 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
865 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
866 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
867 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0
))
868 ws
->value
.sig
= GDB_SIGNAL_FPE
;
870 ws
->value
.sig
= GDB_SIGNAL_0
;
872 /* If there are more events in the list, mark the async file so that
873 rocm_target_ops::wait gets called again. */
874 if (target_is_async_p () && !info
->wave_stop_events
.empty ())
881 rocm_target_ops::stopped_by_sw_breakpoint ()
883 if (!ptid_is_gpu (inferior_ptid
))
884 return beneath ()->supports_stopped_by_sw_breakpoint ()
885 && beneath ()->stopped_by_sw_breakpoint ();
887 /* FIXME: we should check that the wave is not single-stepping. */
889 struct regcache
*regcache
= get_thread_regcache_for_ptid (inferior_ptid
);
891 CORE_ADDR bkpt_pc
= regcache_read_pc (regcache
)
892 - gdbarch_decr_pc_after_break (regcache
->arch ());
894 return software_breakpoint_inserted_here_p (regcache
->aspace (), bkpt_pc
);
898 rocm_target_ops::mourn_inferior ()
900 /* FIXME: only unpush on the last activation. */
901 /* Disengage the ROCm target_ops. */
902 unpush_target (&rocm_ops
);
904 beneath ()->mourn_inferior ();
908 rocm_target_ops::fetch_registers (struct regcache
*regcache
, int regno
)
910 struct gdbarch
*gdbarch
= regcache
->arch ();
911 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
913 /* delegate to the host routines when not on the device */
915 if (!rocm_is_amdgcn_gdbarch (gdbarch
))
917 beneath ()->fetch_registers (regcache
, regno
);
921 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
922 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
924 gdb_byte raw
[AMDGCN_MAX_REGISTER_SIZE
];
926 amd_dbgapi_status_t status
= amd_dbgapi_read_register (
927 process_id
, wave_id
, tdep
->register_ids
[regno
], 0,
928 TYPE_LENGTH (register_type (gdbarch
, regno
)), raw
);
930 if (status
== AMD_DBGAPI_STATUS_SUCCESS
)
932 regcache
->raw_supply (regno
, raw
);
934 else if (status
!= AMD_DBGAPI_STATUS_ERROR_INVALID_REGISTER_ID
)
936 warning (_ ("Couldn't read register %s (#%d)."),
937 gdbarch_register_name (gdbarch
, regno
), regno
);
942 rocm_target_ops::store_registers (struct regcache
*regcache
, int regno
)
944 struct gdbarch
*gdbarch
= regcache
->arch ();
945 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
946 gdb_byte raw
[AMDGCN_MAX_REGISTER_SIZE
];
948 if (!rocm_is_amdgcn_gdbarch (gdbarch
))
950 beneath ()->store_registers (regcache
, regno
);
954 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
955 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (regcache
->ptid ());
957 regcache
->raw_collect (regno
, &raw
);
959 amd_dbgapi_status_t status
= amd_dbgapi_write_register (
960 process_id
, wave_id
, tdep
->register_ids
[regno
], 0,
961 TYPE_LENGTH (register_type (gdbarch
, regno
)), raw
);
963 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
965 warning (_ ("Couldn't write register %s (#%d)."),
966 gdbarch_register_name (gdbarch
, regno
), regno
);
970 /* Fix breakpoints created with an address location while the
971 architecture was set to the host (could be fixed in core GDB). */
974 rocm_target_breakpoint_fixup (struct breakpoint
*b
)
976 if (b
->location
.get ()
977 && event_location_type (b
->location
.get ()) == ADDRESS_LOCATION
978 && gdbarch_bfd_arch_info (b
->loc
->gdbarch
)->arch
== bfd_arch_amdgcn
979 && gdbarch_bfd_arch_info (b
->gdbarch
)->arch
!= bfd_arch_amdgcn
)
981 b
->gdbarch
= b
->loc
->gdbarch
;
986 rocm_target_ops::thread_architecture (ptid_t ptid
)
988 static std::result_of
<decltype (&ptid_t::tid
) (ptid_t
)>::type last_tid
= 0;
989 static struct gdbarch
*cached_arch
= nullptr;
991 if (!ptid_is_gpu (ptid
))
992 return beneath ()->thread_architecture (ptid
);
994 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
995 wave IDs are unique, and aren't reused. */
996 if (ptid
.tid () == last_tid
)
999 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1000 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (ptid
);
1001 amd_dbgapi_architecture_id_t architecture_id
;
1003 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
1004 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE
,
1005 sizeof (architecture_id
), &architecture_id
)
1006 != AMD_DBGAPI_STATUS_SUCCESS
)
1007 error (_ ("Couldn't get architecture for wave_%ld"), ptid
.tid ());
1009 uint32_t elf_amdgpu_machine
;
1010 if (amd_dbgapi_architecture_get_info (
1011 architecture_id
, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE
,
1012 sizeof (elf_amdgpu_machine
), &elf_amdgpu_machine
)
1013 != AMD_DBGAPI_STATUS_SUCCESS
)
1014 error (_ ("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1015 architecture_id
.handle
);
1017 struct gdbarch_info info
;
1018 gdbarch_info_init (&info
);
1020 info
.bfd_arch_info
= bfd_lookup_arch (bfd_arch_amdgcn
, elf_amdgpu_machine
);
1021 info
.byte_order
= BFD_ENDIAN_LITTLE
;
1022 info
.osabi
= GDB_OSABI_AMDGPU_HSA
;
1024 last_tid
= ptid
.tid ();
1025 if (!(cached_arch
= gdbarch_find_by_info (info
)))
1026 error (_ ("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine
);
1032 rocm_target_ops::update_thread_list ()
1034 for (inferior
*inf
: all_inferiors ())
1036 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id (inf
);
1037 amd_dbgapi_wave_id_t
*wave_list
;
1040 amd_dbgapi_changed_t changed
;
1041 amd_dbgapi_status_t status
;
1043 = amd_dbgapi_wave_list (process_id
, &count
, &wave_list
, &changed
))
1044 != AMD_DBGAPI_STATUS_SUCCESS
)
1045 error (_ ("amd_dbgapi_wave_list failed (rc=%d"), status
);
1047 if (changed
== AMD_DBGAPI_CHANGED_NO
)
1050 /* Create a set and free the wave list. */
1051 std::set
<std::result_of
<decltype (&ptid_t::tid
) (ptid_t
)>::type
> threads
;
1052 for (size_t i
= 0; i
< count
; ++i
)
1053 threads
.emplace (wave_list
[i
].handle
);
1056 /* Then prune the wave_ids that already have a thread_info. */
1057 for (thread_info
*tp
: inf
->non_exited_threads ())
1058 if (ptid_is_gpu (tp
->ptid
))
1059 threads
.erase (tp
->ptid
.tid ());
1061 /* The wave_ids that are left require a new thread_info. */
1062 for (auto &&tid
: threads
)
1064 ptid_t
wave_ptid (inf
->pid
, 1, tid
);
1065 amd_dbgapi_wave_state_t state
;
1067 if (amd_dbgapi_wave_get_info (
1068 process_id
, get_amd_dbgapi_wave_id (wave_ptid
),
1069 AMD_DBGAPI_WAVE_INFO_STATE
, sizeof (state
), &state
)
1070 != AMD_DBGAPI_STATUS_SUCCESS
)
1073 add_thread_silent (inf
->process_target (), wave_ptid
);
1074 set_running (inf
->process_target (), wave_ptid
, 1);
1075 set_executing (inf
->process_target (), wave_ptid
, 1);
1079 /* Give the beneath target a chance to do extra processing. */
1080 this->beneath ()->update_thread_list ();
1084 rocm_target_solib_loaded (struct so_list
*solib
)
1086 /* Notify the amd_dbgapi that a shared library has been loaded. */
1087 for (auto &&value
: get_rocm_inferior_info ()->notify_solib_map
)
1088 /* TODO: If we want to support file name wildcards, change this code. */
1089 if (::strstr (solib
->so_original_name
, value
.second
.compare
.c_str ())
1090 && !value
.second
.is_loaded
)
1092 value
.second
.solib
= solib
;
1093 value
.second
.is_loaded
= true;
1095 amd_dbgapi_report_shared_library (
1096 get_amd_dbgapi_process_id (),
1097 amd_dbgapi_shared_library_id_t
{ value
.first
},
1098 AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
);
1103 rocm_target_solib_unloaded (struct so_list
*solib
)
1105 /* Notify the amd_dbgapi that a shared library will unload. */
1106 for (auto &&value
: get_rocm_inferior_info ()->notify_solib_map
)
1107 /* TODO: If we want to support file name wildcards, change this code. */
1108 if (::strstr (solib
->so_original_name
, value
.second
.compare
.c_str ())
1109 && value
.second
.is_loaded
)
1111 struct rocm_inferior_info
*info
= get_rocm_inferior_info ();
1113 amd_dbgapi_report_shared_library (
1114 info
->process_id
, amd_dbgapi_shared_library_id_t
{ value
.first
},
1115 AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED
);
1117 /* Delete breakpoints that were left inserted in this shared library.
1119 for (auto it
= info
->breakpoint_map
.begin ();
1120 it
!= info
->breakpoint_map
.end ();)
1121 if (solib_contains_address_p (solib
, it
->second
->loc
->address
))
1123 warning (_ ("breakpoint_%ld is still inserted after "
1124 "shared_library_%ld was unloaded"),
1125 it
->first
, value
.first
);
1126 delete_breakpoint (it
->second
);
1127 it
= info
->breakpoint_map
.erase (it
);
1132 value
.second
.solib
= nullptr;
1133 value
.second
.is_loaded
= false;
1138 rocm_target_inferior_created (struct target_ops
*target
, int from_tty
)
1140 struct inferior
*inf
= current_inferior ();
1141 auto *info
= get_rocm_inferior_info (inf
);
1142 amd_dbgapi_status_t status
;
1144 if (!target_can_async_p ())
1147 _ ("ROCm-GDB requires target-async, GPU debugging is disabled"));
1151 gdb_assert (info
->wave_stop_events
.empty ());
1153 status
= amd_dbgapi_process_attach (inf
, &info
->process_id
);
1155 if (status
== AMD_DBGAPI_STATUS_ERROR_VERSION_MISMATCH
)
1156 warning (_ ("The version of the kernel driver does not match the version "
1157 "required by the ROCm debugger library"));
1159 if (status
!= AMD_DBGAPI_STATUS_SUCCESS
)
1161 warning (_ ("Could not attach to process %d"), inf
->pid
);
1165 if (amd_dbgapi_process_get_info (info
->process_id
,
1166 AMD_DBGAPI_PROCESS_INFO_NOTIFIER
,
1167 sizeof (info
->notifier
), &info
->notifier
)
1168 != AMD_DBGAPI_STATUS_SUCCESS
)
1170 warning (_ ("Could not retrieve process %d's notifier"), inf
->pid
);
1171 amd_dbgapi_process_detach (info
->process_id
);
1175 /* We add a file handler for events returned by the debugger api. We'll use
1176 this handler to signal our async handler that events are available. */
1179 [] (int error
, gdb_client_data client_data
) {
1180 auto info_
= static_cast<struct rocm_inferior_info
*> (client_data
);
1183 /* Drain the notifier pipe. */
1187 ret
= read (info_
->notifier
, &buf
, 1);
1189 while (ret
>= 0 || (ret
== -1 && errno
== EINTR
));
1191 /* Signal our async handler. */
1196 /* Attaching to the inferior may have generated runtime events, process
1198 rocm_process_event_queue ();
1202 rocm_target_inferior_exit (struct inferior
*inf
)
1204 auto *info
= get_rocm_inferior_info (inf
);
1206 amd_dbgapi_deactivated
.notify ();
1208 if (info
->notifier
!= -1)
1209 delete_file_handler (info
->notifier
);
1211 amd_dbgapi_process_detach (info
->process_id
);
1213 /* Delete the breakpoints that are still active. */
1214 for (auto &&value
: info
->breakpoint_map
)
1215 delete_breakpoint (value
.second
);
1217 rocm_inferior_data
.clear (inf
);
1220 static cli_style_option
warning_style ("rocm_warning", ui_file_style::RED
);
1221 static cli_style_option
info_style ("rocm_info", ui_file_style::GREEN
);
1222 static cli_style_option
verbose_style ("rocm_verbose", ui_file_style::BLUE
);
1224 static amd_dbgapi_callbacks_t dbgapi_callbacks
= {
1225 /* allocate_memory. */
1226 .allocate_memory
= xmalloc
,
1228 /* deallocate_memory. */
1229 .deallocate_memory
= xfree
,
1232 .get_os_pid
= [] (amd_dbgapi_client_process_id_t client_process_id
,
1233 pid_t
*pid
) -> amd_dbgapi_status_t
{
1234 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1237 return AMD_DBGAPI_STATUS_SUCCESS
;
1240 /* enable_notify_shared_library callback. */
1241 .enable_notify_shared_library
1242 = [] (amd_dbgapi_client_process_id_t client_process_id
,
1243 const char *library_name
, amd_dbgapi_shared_library_id_t library_id
,
1244 amd_dbgapi_shared_library_state_t
*library_state
)
1245 -> amd_dbgapi_status_t
{
1246 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1247 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1249 if (!library_name
|| !library_state
)
1250 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1252 if (info
->notify_solib_map
.find (library_id
.handle
)
1253 != info
->notify_solib_map
.end ())
1255 /* This library id is already registered. */
1256 return AMD_DBGAPI_STATUS_ERROR
;
1259 /* Check whether the library is already loaded. */
1260 bool is_loaded
= false;
1261 struct so_list
*solib
;
1262 for (solib
= inf
->pspace
->so_list
; solib
; solib
= solib
->next
)
1263 if (::strstr (solib
->so_original_name
, library_name
))
1269 /* Check that the library_name is valid. If must not be empty, and
1270 should not have wildcard characters. */
1271 if (*library_name
== '\0'
1272 || std::string (library_name
).find_first_of ("*?[]")
1273 != std::string::npos
)
1274 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1276 /* Add a new entry in the notify_solib_map. */
1277 if (!info
->notify_solib_map
1278 .emplace (std::piecewise_construct
,
1279 std::forward_as_tuple (library_id
.handle
),
1280 std::forward_as_tuple (rocm_notify_shared_library_info
{
1281 library_name
, solib
, is_loaded
}))
1283 return AMD_DBGAPI_STATUS_ERROR
;
1285 *library_state
= is_loaded
? AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
1286 : AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED
;
1288 return AMD_DBGAPI_STATUS_SUCCESS
;
1291 /* disable_notify_shared_library callback. */
1292 .disable_notify_shared_library
1293 = [] (amd_dbgapi_client_process_id_t client_process_id
,
1294 amd_dbgapi_shared_library_id_t library_id
) -> amd_dbgapi_status_t
{
1295 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1296 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1298 auto it
= info
->notify_solib_map
.find (library_id
.handle
);
1299 if (it
== info
->notify_solib_map
.end ())
1300 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID
;
1302 info
->notify_solib_map
.erase (it
);
1303 return AMD_DBGAPI_STATUS_SUCCESS
;
1306 /* get_symbol_address callback. */
1307 .get_symbol_address
=
1308 [] (amd_dbgapi_client_process_id_t client_process_id
,
1309 amd_dbgapi_shared_library_id_t library_id
, const char *symbol_name
,
1310 amd_dbgapi_global_address_t
*address
) {
1311 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1312 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1314 auto it
= info
->notify_solib_map
.find (library_id
.handle
);
1315 if (it
== info
->notify_solib_map
.end ())
1316 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID
;
1318 struct so_list
*solib
= it
->second
.solib
;
1320 return AMD_DBGAPI_STATUS_ERROR_LIBRARY_NOT_LOADED
;
1322 solib_read_symbols (solib
, 0);
1323 gdb_assert (solib
->objfile
);
1325 struct bound_minimal_symbol msymbol
1326 = lookup_minimal_symbol (symbol_name
, NULL
, solib
->objfile
);
1328 if (!msymbol
.minsym
|| BMSYMBOL_VALUE_ADDRESS (msymbol
) == 0)
1329 return AMD_DBGAPI_STATUS_ERROR_SYMBOL_NOT_FOUND
;
1331 *address
= BMSYMBOL_VALUE_ADDRESS (msymbol
);
1332 return AMD_DBGAPI_STATUS_SUCCESS
;
1335 /* set_breakpoint callback. */
1337 [] (amd_dbgapi_client_process_id_t client_process_id
,
1338 amd_dbgapi_shared_library_id_t shared_library_id
,
1339 amd_dbgapi_global_address_t address
,
1340 amd_dbgapi_breakpoint_id_t breakpoint_id
) {
1341 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1342 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1344 /* Initialize the breakpoint ops lazily since we depend on
1345 bkpt_breakpoint_ops and we can't control the order in which
1346 initializers are called. */
1347 if (rocm_breakpoint_ops
.check_status
== NULL
)
1349 rocm_breakpoint_ops
= bkpt_breakpoint_ops
;
1350 rocm_breakpoint_ops
.check_status
= rocm_breakpoint_check_status
;
1353 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1354 if (it
!= info
->breakpoint_map
.end ())
1355 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1357 /* Create a new breakpoint. */
1358 struct obj_section
*section
= find_pc_section (address
);
1359 if (!section
|| !section
->objfile
)
1360 return AMD_DBGAPI_STATUS_ERROR
;
1362 event_location_up location
1363 = new_address_location (address
, nullptr, 0);
1364 if (!create_breakpoint (
1365 get_objfile_arch (section
->objfile
), location
.get (),
1366 /*cond_string*/ NULL
, /*thread*/ -1, /*extra_sring*/ NULL
,
1367 /*parse_extra*/ 0, /*tempflag*/ 0, /*bptype*/ bp_breakpoint
,
1368 /*ignore_count*/ 0, /*pending_break*/ AUTO_BOOLEAN_FALSE
,
1369 /*ops*/ &rocm_breakpoint_ops
, /*from_tty*/ 0,
1370 /*enabled*/ 1, /*internal*/ 1, /*flags*/ 0))
1371 return AMD_DBGAPI_STATUS_ERROR
;
1373 /* Find our breakpoint in the breakpoint list. */
1374 auto bp_loc
= std::make_pair (inf
->aspace
, address
);
1375 auto bp
= breakpoint_find_if (
1376 [] (struct breakpoint
*b
, void *data
) {
1377 auto *arg
= static_cast<decltype (&bp_loc
)> (data
);
1378 if (b
->ops
== &rocm_breakpoint_ops
&& b
->loc
1379 && b
->loc
->pspace
->aspace
== arg
->first
1380 && b
->loc
->address
== arg
->second
)
1384 reinterpret_cast<void *> (&bp_loc
));
1387 error (_ ("Could not find breakpoint"));
1389 info
->breakpoint_map
.emplace (breakpoint_id
.handle
, bp
);
1390 return AMD_DBGAPI_STATUS_SUCCESS
;
1393 /* remove_breakpoint callback. */
1394 .remove_breakpoint
=
1395 [] (amd_dbgapi_client_process_id_t client_process_id
,
1396 amd_dbgapi_breakpoint_id_t breakpoint_id
) {
1397 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1398 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1400 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1401 if (it
== info
->breakpoint_map
.end ())
1402 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1404 delete_breakpoint (it
->second
);
1405 info
->breakpoint_map
.erase (it
);
1407 return AMD_DBGAPI_STATUS_SUCCESS
;
1410 /* set_breakpoint_state callback. */
1411 .set_breakpoint_state
=
1412 [] (amd_dbgapi_client_process_id_t client_process_id
,
1413 amd_dbgapi_breakpoint_id_t breakpoint_id
,
1414 amd_dbgapi_breakpoint_state_t breakpoint_state
) {
1415 inferior
*inf
= static_cast<inferior
*> (client_process_id
);
1416 struct rocm_inferior_info
*info
= get_rocm_inferior_info (inf
);
1418 auto it
= info
->breakpoint_map
.find (breakpoint_id
.handle
);
1419 if (it
== info
->breakpoint_map
.end ())
1420 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID
;
1422 if (breakpoint_state
== AMD_DBGAPI_BREAKPOINT_STATE_ENABLE
)
1423 it
->second
->enable_state
= bp_enabled
;
1424 else if (breakpoint_state
== AMD_DBGAPI_BREAKPOINT_STATE_DISABLE
)
1425 it
->second
->enable_state
= bp_disabled
;
1427 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT
;
1429 return AMD_DBGAPI_STATUS_SUCCESS
;
1433 = [] (amd_dbgapi_log_level_t level
, const char *message
) -> void {
1434 gdb::optional
<target_terminal::scoped_restore_terminal_state
> tstate
;
1436 if (level
> get_debug_amd_dbgapi_log_level ())
1439 if (target_supports_terminal_ours ())
1442 target_terminal::ours_for_output ();
1445 if (filtered_printing_initialized ())
1448 struct ui_file
*out_file
1449 = (level
>= AMD_DBGAPI_LOG_LEVEL_INFO
) ? gdb_stdlog
: gdb_stderr
;
1453 case AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
:
1454 fputs_unfiltered ("[amd-dbgapi]: ", out_file
);
1456 case AMD_DBGAPI_LOG_LEVEL_WARNING
:
1457 fputs_styled ("[amd-dbgapi]: ", warning_style
.style (), out_file
);
1459 case AMD_DBGAPI_LOG_LEVEL_INFO
:
1460 fputs_styled ("[amd-dbgapi]: ", info_style
.style (), out_file
);
1462 case AMD_DBGAPI_LOG_LEVEL_VERBOSE
:
1463 fputs_styled ("[amd-dbgapi]: ", verbose_style
.style (), out_file
);
1467 fputs_unfiltered (message
, out_file
);
1468 fputs_unfiltered ("\n", out_file
);
1472 /* Implementation of `_wave_id' variable. */
1474 static struct value
*
1475 rocm_wave_id_make_value (struct gdbarch
*gdbarch
, struct internalvar
*var
,
1478 if (ptid_is_gpu (inferior_ptid
))
1480 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1481 amd_dbgapi_wave_id_t wave_id
= get_amd_dbgapi_wave_id (inferior_ptid
);
1482 uint32_t group_ids
[3], wave_in_group
;
1484 if (amd_dbgapi_wave_get_info (process_id
, wave_id
,
1485 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD
,
1486 sizeof (group_ids
), &group_ids
)
1487 == AMD_DBGAPI_STATUS_SUCCESS
1488 && amd_dbgapi_wave_get_info (
1489 process_id
, wave_id
,
1490 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP
,
1491 sizeof (wave_in_group
), &wave_in_group
)
1492 == AMD_DBGAPI_STATUS_SUCCESS
)
1494 std::string wave_id_str
1495 = string_printf ("(%d,%d,%d)/%d", group_ids
[2], group_ids
[1],
1496 group_ids
[0], wave_in_group
);
1498 return value_cstring (wave_id_str
.data (), wave_id_str
.length () + 1,
1499 builtin_type (gdbarch
)->builtin_char
);
1503 return allocate_value (builtin_type (gdbarch
)->builtin_void
);
1506 static const struct internalvar_funcs rocm_wave_id_funcs
1507 = { rocm_wave_id_make_value
, NULL
, NULL
};
1509 /* List of set/show debug amd_dbgapi commands. */
1510 struct cmd_list_element
*set_debug_amd_dbgapi_list
;
1511 struct cmd_list_element
*show_debug_amd_dbgapi_list
;
1514 set_debug_amd_dbgapi (const char *arg
, int from_tty
)
1516 help_list (set_debug_amd_dbgapi_list
, "set debug amd-dbgapi ",
1517 (enum command_class
) - 1, gdb_stdout
);
1521 show_debug_amd_dbgapi (const char *args
, int from_tty
)
1523 cmd_show_list (show_debug_amd_dbgapi_list
, from_tty
, "");
1526 constexpr char amd_dbgapi_log_level_off
[] = "off";
1527 constexpr char amd_dbgapi_log_level_error
[] = "error";
1528 constexpr char amd_dbgapi_log_level_warning
[] = "warning";
1529 constexpr char amd_dbgapi_log_level_info
[] = "info";
1530 constexpr char amd_dbgapi_log_level_verbose
[] = "verbose";
1532 constexpr const char *debug_amd_dbgapi_log_level_enums
[]
1533 = { [AMD_DBGAPI_LOG_LEVEL_NONE
] = amd_dbgapi_log_level_off
,
1534 [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR
] = amd_dbgapi_log_level_error
,
1535 [AMD_DBGAPI_LOG_LEVEL_WARNING
] = amd_dbgapi_log_level_warning
,
1536 [AMD_DBGAPI_LOG_LEVEL_INFO
] = amd_dbgapi_log_level_info
,
1537 [AMD_DBGAPI_LOG_LEVEL_VERBOSE
] = amd_dbgapi_log_level_verbose
,
1540 static const char *debug_amd_dbgapi_log_level
= amd_dbgapi_log_level_error
;
1542 static amd_dbgapi_log_level_t
1543 get_debug_amd_dbgapi_log_level ()
1546 for (pos
= 0; debug_amd_dbgapi_log_level_enums
[pos
]; ++pos
)
1547 if (debug_amd_dbgapi_log_level
== debug_amd_dbgapi_log_level_enums
[pos
])
1550 gdb_assert (debug_amd_dbgapi_log_level_enums
[pos
]);
1551 return static_cast<amd_dbgapi_log_level_t
> (pos
);
1555 set_debug_amd_dbgapi_log_level (const char *args
, int from_tty
,
1556 struct cmd_list_element
*c
)
1558 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1562 show_debug_amd_dbgapi_log_level (struct ui_file
*file
, int from_tty
,
1563 struct cmd_list_element
*c
, const char *value
)
1565 fprintf_filtered (file
, _ ("The amd-dbgapi log level is %s.\n"), value
);
1569 info_agents_command (const char *args
, int from_tty
)
1571 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
1572 struct ui_out
*uiout
= current_uiout
;
1573 amd_dbgapi_status_t status
;
1575 amd_dbgapi_agent_id_t
*agent_list
;
1578 if (process_id
.handle
!= AMD_DBGAPI_PROCESS_NONE
.handle
1580 = amd_dbgapi_agent_list (process_id
, &count
, &agent_list
, nullptr))
1581 != AMD_DBGAPI_STATUS_SUCCESS
)
1582 error (_ ("amd_dbgapi_agent_list failed (rc=%d)"), status
);
1584 if (!count
&& !uiout
->is_mi_like_p ())
1586 uiout
->field_string (NULL
, _ ("No agents are currently active.\n"));
1590 /* Calculate the maximum size needed to print the agents names. */
1591 std::vector
<std::string
> agent_names (count
);
1593 size_t max_name_len
= 0;
1594 for (size_t i
= 0; i
< count
; ++i
)
1598 if ((status
= amd_dbgapi_agent_get_info (
1599 process_id
, agent_list
[i
], AMD_DBGAPI_AGENT_INFO_NAME
,
1600 sizeof (agent_name
), &agent_name
))
1601 != AMD_DBGAPI_STATUS_SUCCESS
)
1603 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID
)
1604 agent_names
[i
] = "N/A";
1606 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status
);
1610 agent_names
[i
] = agent_name
;
1614 max_name_len
= std::max (max_name_len
, agent_names
[i
].size ());
1618 ui_out_emit_table
table_emmitter (uiout
, 7, count
, "InfoRocmDevicesTable");
1620 uiout
->table_header (2, ui_left
, "agent_id", "Id");
1621 uiout
->table_header (8, ui_left
, "location_id", "PCI Slot");
1622 uiout
->table_header (std::max (11ul, max_name_len
), ui_left
, "name",
1624 uiout
->table_header (14, ui_left
, "num_se", "Shader Engines");
1625 uiout
->table_header (13, ui_left
, "num_cu", "Compute Units");
1626 uiout
->table_header (7, ui_left
, "simd", "SIMD/CU");
1627 uiout
->table_header (15, ui_left
, "waves", "Wavefronts/SIMD");
1628 uiout
->table_body ();
1631 for (size_t i
= 0; i
< count
; ++i
)
1633 ui_out_emit_tuple
tuple_emitter (uiout
, "InfoRocmDevicesRow");
1636 uiout
->field_signed ("agent_id", agent_list
[i
].handle
);
1639 uint32_t location_id
;
1640 if ((status
= amd_dbgapi_agent_get_info (
1641 process_id
, agent_list
[i
], AMD_DBGAPI_AGENT_INFO_PCIE_SLOT
,
1642 sizeof (location_id
), &location_id
))
1643 != AMD_DBGAPI_STATUS_SUCCESS
)
1645 if (status
== AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID
)
1646 uiout
->field_string ("location_id", "N/A");
1648 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status
);
1651 uiout
->field_string (
1653 string_printf ("%02x:%02x.%d", (location_id
>> 8) & 0xFF,
1654 (location_id
>> 3) & 0x1F, location_id
& 0x7));
1657 uiout
->field_string ("name", agent_names
[i
]);
1659 /* num_se, num_cu, simd, waves */
1661 #define UIOUT_FIELD_INT(name, query) \
1663 if ((status = amd_dbgapi_agent_get_info (process_id, agent_list[i], query, \
1664 sizeof (name), &name)) \
1665 != AMD_DBGAPI_STATUS_SUCCESS) \
1667 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID) \
1668 uiout->field_string (#name, "N/A"); \
1670 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status); \
1673 uiout->field_signed (#name, name);
1675 UIOUT_FIELD_INT (num_se
, AMD_DBGAPI_AGENT_INFO_SHADER_ENGINE_COUNT
);
1676 UIOUT_FIELD_INT (num_cu
, AMD_DBGAPI_AGENT_INFO_COMPUTE_UNIT_COUNT
);
1677 UIOUT_FIELD_INT (simd
, AMD_DBGAPI_AGENT_INFO_NUM_SIMD_PER_COMPUTE_UNIT
);
1678 UIOUT_FIELD_INT (waves
, AMD_DBGAPI_AGENT_INFO_MAX_WAVES_PER_SIMD
);
1680 #undef UIOUT_FIELD_INT
1686 gdb_flush (gdb_stdout
);
1689 /* -Wmissing-prototypes */
1690 extern initialize_file_ftype _initialize_rocm_tdep
;
1693 _initialize_rocm_tdep (void)
1695 /* Initialize the ROCm Debug API. */
1696 if (amd_dbgapi_initialize (&dbgapi_callbacks
) != AMD_DBGAPI_STATUS_SUCCESS
)
1699 /* Set the initial log level. */
1700 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1702 /* Install observers. */
1703 gdb::observers::breakpoint_created
.attach (rocm_target_breakpoint_fixup
);
1704 gdb::observers::solib_loaded
.attach (rocm_target_solib_loaded
);
1705 gdb::observers::solib_unloaded
.attach (rocm_target_solib_unloaded
);
1706 gdb::observers::inferior_created
.attach (rocm_target_inferior_created
);
1707 gdb::observers::inferior_exit
.attach (rocm_target_inferior_exit
);
1709 amd_dbgapi_activated
.attach (rocm_target_dbgapi_activated
);
1710 amd_dbgapi_deactivated
.attach (rocm_target_dbgapi_deactivated
);
1712 create_internalvar_type_lazy ("_wave_id", &rocm_wave_id_funcs
, NULL
);
1714 add_prefix_cmd ("amd-dbgapi", no_class
, set_debug_amd_dbgapi
,
1715 _ ("Generic command for setting amd-dbgapi debugging flags"),
1716 &set_debug_amd_dbgapi_list
, "set debug amd-dbgapi ", 0,
1719 add_prefix_cmd ("amd-dbgapi", no_class
, show_debug_amd_dbgapi
,
1720 _ ("Generic command for showing amd-dbgapi debugging flags"),
1721 &show_debug_amd_dbgapi_list
, "show debug amd-dbgapi ", 0,
1724 add_setshow_enum_cmd (
1725 "log-level", class_maintenance
, debug_amd_dbgapi_log_level_enums
,
1726 &debug_amd_dbgapi_log_level
, _ ("Set the amd-dbgapi log level."),
1727 _ ("Show the amd-dbgapi log level."),
1728 _ ("off == no logging is enabled\n"
1729 "error == fatal errors are reported\n"
1730 "warning == fatal errors and warnings are reported\n"
1731 "info == fatal errors, warnings, and info messages are reported\n"
1732 "verbose == all messages are reported"),
1733 set_debug_amd_dbgapi_log_level
, show_debug_amd_dbgapi_log_level
,
1734 &set_debug_amd_dbgapi_list
, &show_debug_amd_dbgapi_list
);
1736 add_cmd ("agents", class_info
, info_agents_command
,
1737 _ ("Info about currently active agents."), &infolist
);