Update ROCm for multi-target support
[deliverable/binutils-gdb.git] / gdb / rocm-tdep.c
CommitLineData
5922befa
LM
1/* Target-dependent code for ROCm.
2
4e5106e6
LM
3 Copyright (C) 2019-2020 Free Software Foundation, Inc.
4 Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
5922befa
LM
5
6 This file is part of GDB.
7
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.
12
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.
17
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/>. */
20
21#include "defs.h"
22
23#include "amdgcn-rocm-tdep.h"
24#include "arch-utils.h"
25#include "cli/cli-style.h"
26#include "environ.h"
27#include "event-loop.h"
28#include "filenames.h"
29#include "gdbcmd.h"
30#include "gdbcore.h"
31#include "gdbsupport/filestuff.h"
32#include "gdbsupport/scoped_fd.h"
33#include "gdbthread.h"
34#include "hashtab.h"
35#include "inf-loop.h"
36#include "inferior.h"
37#include "location.h"
38#include "objfiles.h"
39#include "observable.h"
40#include "progspace-and-thread.h"
41#include "regcache.h"
42#include "rocm-tdep.h"
43#include "solib.h"
44#include "solist.h"
45#include "symfile.h"
46
47#include <dlfcn.h>
48#include <list>
49#include <set>
50#include <signal.h>
51#include <stdarg.h>
52#include <unordered_map>
53
54#include <amd-dbgapi.h>
55
56/* Big enough to hold the size of the largest register in bytes. */
57#define AMDGCN_MAX_REGISTER_SIZE 256
58
59#define DEFINE_OBSERVABLE(name) decltype (name) name (#name)
60
61DEFINE_OBSERVABLE (amd_dbgapi_activated);
62DEFINE_OBSERVABLE (amd_dbgapi_deactivated);
63DEFINE_OBSERVABLE (amd_dbgapi_code_object_list_updated);
64
65#undef DEFINE_OBSERVABLE
66
67struct rocm_notify_shared_library_info
68{
69 std::string compare; /* Compare loaded library names with this string. */
70 struct so_list *solib;
71 bool is_loaded;
72};
73
74/* ROCm-specific inferior data. */
75
76struct rocm_inferior_info
77{
78 /* The amd_dbgapi_process_id for this inferior. */
86e751f5 79 amd_dbgapi_process_id_t process_id{ AMD_DBGAPI_PROCESS_NONE };
5922befa
LM
80
81 /* The amd_dbgapi_notifier_t for this inferior. */
86e751f5 82 amd_dbgapi_notifier_t notifier{ -1 };
5922befa
LM
83
84 /* True if commit_resume should all-start the GPU queues. */
85 bool commit_resume_all_start;
86
87 std::unordered_map<decltype (amd_dbgapi_breakpoint_id_t::handle),
88 struct breakpoint *>
89 breakpoint_map;
90
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>>
93 wave_stop_events;
94
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>
99 notify_solib_map;
100};
101
102static amd_dbgapi_event_id_t
103rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind
104 = AMD_DBGAPI_EVENT_KIND_NONE);
105
106/* Return the inferior's rocm_inferior_info struct. */
107static struct rocm_inferior_info *
108get_rocm_inferior_info (struct inferior *inferior = nullptr);
109
110static const target_info rocm_ops_info
111 = { "rocm", N_ ("ROCm GPU debugging support"),
112 N_ ("ROCm GPU debugging support") };
113
114static amd_dbgapi_log_level_t get_debug_amd_dbgapi_log_level ();
115
116struct rocm_target_ops final : public target_ops
117{
118 const target_info &
119 info () const override
120 {
121 return rocm_ops_info;
122 }
123 strata
124 stratum () const override
125 {
126 return arch_stratum;
127 }
128
129 void mourn_inferior () override;
130
131 void async (int enable) override;
132
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;
137
138 void fetch_registers (struct regcache *, int) override;
139 void store_registers (struct regcache *, int) override;
140
141 void update_thread_list () override;
142
143 struct gdbarch *thread_architecture (ptid_t) override;
144
145 std::string pid_to_str (ptid_t ptid) override;
146
147 const char *thread_name (thread_info *tp) override;
148
149 const char *extra_thread_info (thread_info *tp) override;
150
151 bool thread_alive (ptid_t ptid) override;
152
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;
158
159 bool
160 stopped_by_watchpoint () override
161 {
162 return !ptid_is_gpu (inferior_ptid)
163 && beneath ()->stopped_by_watchpoint ();
164 }
165
166 bool
167 stopped_data_address (CORE_ADDR *addr_p) override
168 {
169 return !ptid_is_gpu (inferior_ptid)
170 && beneath ()->stopped_data_address (addr_p);
171 }
172
173 bool
174 supports_stopped_by_sw_breakpoint () override
175 {
176 return true;
177 }
178
179 bool stopped_by_sw_breakpoint () override;
180
181 bool
182 stopped_by_hw_breakpoint () override
183 {
184 return !ptid_is_gpu (inferior_ptid)
185 && beneath ()->stopped_by_hw_breakpoint ();
186 }
187};
188
189/* ROCm's target vector. */
190static struct rocm_target_ops rocm_ops;
191
192/* ROCm breakpoint ops. */
193static struct breakpoint_ops rocm_breakpoint_ops;
194
195/* Per-inferior data key. */
196static const struct inferior_key<rocm_inferior_info> rocm_inferior_data;
197
198/* The read/write ends of the pipe registered as waitable file in the
199 event loop. */
200static int rocm_event_pipe[2] = { -1, -1 };
201
202/* Flush the event pipe. */
203
204void
205async_file_flush (void)
206{
207 int ret;
208 char buf;
209
210 do
211 {
212 ret = read (rocm_event_pipe[0], &buf, 1);
213 }
214 while (ret >= 0 || (ret == -1 && errno == EINTR));
215}
216
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. */
220
221static void
222async_file_mark (void)
223{
224 int ret;
225
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
228 left-overs. */
229 async_file_flush ();
230
231 do
232 {
233 ret = write (rocm_event_pipe[1], "+", 1);
234 }
235 while (ret == -1 && errno == EINTR);
236
237 /* Ignore EAGAIN. If the pipe is full, the event loop will already
238 be awakened anyway. */
239}
240
241/* Fetch the rocm_inferior_info data for the given inferior. */
242
243static struct rocm_inferior_info *
244get_rocm_inferior_info (struct inferior *inferior)
245{
246 if (!inferior)
247 inferior = current_inferior ();
248
249 struct rocm_inferior_info *info = rocm_inferior_data.get (inferior);
250
251 if (!info)
252 info = rocm_inferior_data.emplace (inferior);
253
254 return info;
255}
256
257/* Fetch the amd_dbgapi_process_id for the given inferior. */
258
259amd_dbgapi_process_id_t
260get_amd_dbgapi_process_id (struct inferior *inferior)
261{
262 return get_rocm_inferior_info (inferior)->process_id;
263}
264
265static void
266rocm_breakpoint_check_status (struct bpstats *bs)
267{
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;
271
272 bs->stop = 0;
273 bs->print_it = print_it_noop;
274
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;
280 });
281
282 if (it == info->breakpoint_map.end ())
283 error (_ ("Could not find breakpoint_id for breakpoint at %#lx"),
284 bs->bp_location_at->address);
285
286 amd_dbgapi_breakpoint_id_t breakpoint_id{ it->first };
287 amd_dbgapi_breakpoint_action_t action;
288
289 status = amd_dbgapi_report_breakpoint_hit (process_id, breakpoint_id,
290 inferior_thread (), &action);
291
292 if (status != AMD_DBGAPI_STATUS_SUCCESS)
293 error (_ ("amd_dbgapi_report_breakpoint_hit failed: breakpoint_%ld "
294 "at %#lx (rc=%d)"),
295 breakpoint_id.handle, bs->bp_location_at->address, status);
296
297 if (action == AMD_DBGAPI_BREAKPOINT_ACTION_RESUME)
298 return;
299
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. */
302
303 amd_dbgapi_event_id_t resume_event_id
304 = rocm_process_event_queue (AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
305
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);
309
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);
314
315 if (status != AMD_DBGAPI_STATUS_SUCCESS)
316 error (_ ("amd_dbgapi_event_get_info failed (rc=%d)"), status);
317
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);
325
326 amd_dbgapi_event_processed (process_id, resume_event_id);
327}
328
329static void
330rocm_target_dbgapi_activated ()
331{
332 /* FIXME: only push on the first activation. */
333 /* Engage the ROCm target_ops and so_ops. */
334 push_target (&rocm_ops);
335}
336
337static void
338rocm_target_dbgapi_deactivated ()
339{
340 /* FIXME: only unpush on the last activation. */
341 /* Disengage the ROCm target_ops. */
342 unpush_target (&rocm_ops);
343}
344
345bool
346rocm_target_ops::thread_alive (ptid_t ptid)
347{
348 if (!ptid_is_gpu (ptid))
349 return beneath ()->thread_alive (ptid);
350
351 /* Check that the wave_id is valid. */
352
5922befa
LM
353 amd_dbgapi_wave_state_t state;
354 return amd_dbgapi_wave_get_info (
389fe864 355 get_amd_dbgapi_process_id (), get_amd_dbgapi_wave_id (ptid),
5922befa
LM
356 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state), &state)
357 == AMD_DBGAPI_STATUS_SUCCESS;
358}
359
360const char *
361rocm_target_ops::thread_name (thread_info *tp)
362{
363 if (!ptid_is_gpu (tp->ptid))
364 return beneath ()->thread_name (tp);
365
389fe864 366 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
5922befa
LM
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;
370
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)
380 return NULL;
381
382 struct bound_minimal_symbol msymbol
383 = lookup_minimal_symbol_by_pc_section (kernel_addr, nullptr);
384
385 if (msymbol.minsym != NULL)
386 {
387 static char buf[256];
388 char *endp;
389
390 xsnprintf (buf, sizeof (buf), "%s", msymbol.minsym->print_name ());
391
392 /* Strip the arguments from the demangled function name. */
393 if ((endp = strchr (buf, '(')))
394 *endp = '\0';
395
396 return buf;
397 }
398
399 return NULL;
400}
401
402std::string
403rocm_target_ops::pid_to_str (ptid_t ptid)
404{
405 if (!ptid_is_gpu (ptid))
406 {
407 return beneath ()->pid_to_str (ptid);
408 }
409
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;
414
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 (
424 process_id, wave_id,
425 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP,
426 sizeof (wave_in_group), &wave_in_group)
427 != AMD_DBGAPI_STATUS_SUCCESS)
66388092 428 return std::string ("AMDGPU Thread");
5922befa 429 else
66388092 430 return string_printf ("AMDGPU Thread %ld.%ld (%d,%d,%d)/%d",
5922befa
LM
431 dispatch_id.handle, wave_id.handle, group_ids[2],
432 group_ids[1], group_ids[0], wave_in_group);
433}
434
435const char *
436rocm_target_ops::extra_thread_info (thread_info *tp)
437{
438 if (!ptid_is_gpu (tp->ptid))
439 beneath ()->extra_thread_info (tp);
440
441 return NULL;
442}
443
444enum target_xfer_status
445rocm_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)
449{
450 gdb::optional<scoped_restore_current_thread> maybe_restore_thread;
451
452 if (ptid_is_gpu (inferior_ptid))
453 {
454 gdb_assert (requested_len && xfered_len && "checking invariants");
455
456 if (object != TARGET_OBJECT_MEMORY)
457 return TARGET_XFER_E_IO;
458
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);
461
462 amd_dbgapi_architecture_id_t architecture_id;
463 amd_dbgapi_address_space_id_t address_space_id;
464
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 (
470 architecture_id,
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"));
475
476 size_t len = requested_len;
477 amd_dbgapi_status_t status;
478
479 if (readbuf)
480 status = amd_dbgapi_read_memory (
481 process_id, wave_id, 0, address_space_id, offset, &len, readbuf);
482 else
483 status = amd_dbgapi_write_memory (
484 process_id, wave_id, 0, address_space_id, offset, &len, writebuf);
485
486 if (status != AMD_DBGAPI_STATUS_SUCCESS)
487 {
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;
492 }
493
494 *xfered_len = len;
495 return TARGET_XFER_OK;
496 }
497 else
498 return beneath ()->xfer_partial (object, annex, readbuf, writebuf, offset,
499 requested_len, xfered_len);
500}
501
502void
503rocm_target_ops::resume (ptid_t ptid, int step, enum gdb_signal signo)
504{
505 struct rocm_inferior_info *info = get_rocm_inferior_info ();
506
507 if (debug_infrun)
508 fprintf_unfiltered (
509 gdb_stdlog,
510 "\e[1;34minfrun: rocm_target_ops::resume ([%d,%ld,%ld])\e[0m\n",
511 ptid.pid (), ptid.lwp (), ptid.tid ());
512
513 /* Check if the thread focus is on the GPU device. */
514 if (ptid == minus_one_ptid || !ptid_is_gpu (ptid))
515 {
516 beneath ()->resume (ptid, step, signo);
517 if (ptid != minus_one_ptid)
518 return;
519 }
520
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);
524
525 if (!resume_one)
526 error (_ ("internal error - unimplemented "));
527
528 amd_dbgapi_process_set_progress (info->process_id,
529 AMD_DBGAPI_PROGRESS_NO_FORWARD);
530
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);
538
539 info->commit_resume_all_start = true;
540}
541
542void
543rocm_target_ops::commit_resume ()
544{
545 struct rocm_inferior_info *info = get_rocm_inferior_info ();
546
547 if (debug_infrun)
548 fprintf_unfiltered (
549 gdb_stdlog,
550 "\e[1;34minfrun: rocm_target_ops::commit_resume ()\e[0m\n");
551
552 beneath ()->commit_resume ();
553
554 if (info->commit_resume_all_start)
555 {
556 amd_dbgapi_process_set_progress (info->process_id,
557 AMD_DBGAPI_PROGRESS_NORMAL);
558 info->commit_resume_all_start = false;
559 }
560
561 if (target_can_async_p ())
562 target_async (1);
563}
564
565static void
566rocm_target_stop_one_wave (ptid_t ptid)
567{
568 amd_dbgapi_status_t status;
569
570 status = amd_dbgapi_wave_stop (get_amd_dbgapi_process_id (),
571 get_amd_dbgapi_wave_id (ptid));
572
573 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
574 {
575 /* the wave must have exited, set the thread status to reflect that. */
389fe864 576 auto *tp = find_thread_ptid (current_inferior (), ptid);
5922befa
LM
577 gdb_assert (tp);
578
579 tp->state = THREAD_EXITED;
580 }
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);
584}
585
586void
587rocm_target_ops::stop (ptid_t ptid)
588{
589 if (debug_infrun)
590 fprintf_unfiltered (
591 gdb_stdlog,
592 "\e[1;34minfrun: rocm_target_ops::stop ([%d,%ld,%ld])\e[0m\n",
593 ptid.pid (), ptid.lwp (), ptid.tid ());
594
595 if (ptid == minus_one_ptid || !ptid_is_gpu (ptid))
596 {
597 beneath ()->stop (ptid);
598 if (ptid != minus_one_ptid)
599 return;
600 }
601
602 if (ptid == minus_one_ptid)
603 error (_ ("internal error - unimplemented "));
604
605 rocm_target_stop_one_wave (ptid);
606}
607
608static void
609handle_target_event (int error, gdb_client_data client_data)
610{
611 struct rocm_inferior_info *info = get_rocm_inferior_info ();
612 amd_dbgapi_process_id_t process_id = info->process_id;
613
614 amd_dbgapi_process_set_progress (process_id, AMD_DBGAPI_PROGRESS_NO_FORWARD);
615
616 /* Flush the async file first. */
617 if (target_is_async_p ())
618 async_file_flush ();
619
620 rocm_process_event_queue ();
621
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);
627
628 if (!info->wave_stop_events.empty ())
629 inferior_event_handler (INF_REG_EVENT, nullptr);
630}
631
632void
633rocm_target_ops::async (int enable)
634{
635 beneath ()->async (enable);
636
637 if (enable)
638 {
639 if (rocm_event_pipe[0] != -1)
640 return;
641
642 if (gdb_pipe_cloexec (rocm_event_pipe) == -1)
643 internal_error (__FILE__, __LINE__, "creating event pipe failed.");
644
645 ::fcntl (rocm_event_pipe[0], F_SETFL, O_NONBLOCK);
646 ::fcntl (rocm_event_pipe[1], F_SETFL, O_NONBLOCK);
647
648 add_file_handler (rocm_event_pipe[0], handle_target_event, nullptr);
649
650 /* There may be pending events to handle. Tell the event loop
651 to poll them. */
652 async_file_mark ();
653 }
654 else
655 {
656 delete_file_handler (rocm_event_pipe[0]);
657
658 if (rocm_event_pipe[0] == -1)
659 return;
660
661 ::close (rocm_event_pipe[0]);
662 ::close (rocm_event_pipe[1]);
663 rocm_event_pipe[0] = -1;
664 rocm_event_pipe[1] = -1;
665 }
666}
667
668static void
669rocm_process_one_event (amd_dbgapi_event_id_t event_id,
670 amd_dbgapi_event_kind_t event_kind)
671{
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;
675
676 switch (event_kind)
677 {
678 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
679 {
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);
687
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);
692
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);
697
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. */
701
702 if (status == AMD_DBGAPI_STATUS_SUCCESS)
703 info->wave_stop_events.emplace_back (
704 std::make_pair (wave_id, stop_reason));
705 }
706 break;
707
708 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED:
709 amd_dbgapi_code_object_list_updated.notify ();
710 break;
711
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"));
716 break;
717
718 case AMD_DBGAPI_EVENT_KIND_RUNTIME:
719 {
720 amd_dbgapi_runtime_state_t runtime_state;
721
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);
728
729 switch (runtime_state)
730 {
731 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUPPORTED:
732 amd_dbgapi_activated.notify ();
733 break;
734 case AMD_DBGAPI_RUNTIME_STATE_LOADED_UNSUPPORTED:
735 warning (_ ("ROCm-GDB: low-level runtime version not supported"));
736 break;
737
738 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED:
739 amd_dbgapi_deactivated.notify ();
740 break;
741 }
742 }
743 break;
744
745 default:
746 error (_ ("event kind (%d) not supported"), event_kind);
747 }
748
749 amd_dbgapi_event_processed (process_id, event_id);
750}
751
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. */
756static amd_dbgapi_event_id_t
757rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind)
758{
759 struct rocm_inferior_info *info = get_rocm_inferior_info ();
760
761 while (true)
762 {
763 amd_dbgapi_event_id_t event_id;
764 amd_dbgapi_event_kind_t event_kind;
765
766 amd_dbgapi_status_t status = amd_dbgapi_next_pending_event (
767 info->process_id, &event_id, &event_kind);
768
769 if (status != AMD_DBGAPI_STATUS_SUCCESS)
770 error (_ ("next_pending_event failed (rc=%d)"), status);
771
772 if (event_id.handle == AMD_DBGAPI_EVENT_NONE.handle
773 || event_kind == until_event_kind)
774 return event_id;
775
776 rocm_process_one_event (event_id, event_kind);
777 }
778}
779
780ptid_t
781rocm_target_ops::wait (ptid_t ptid, struct target_waitstatus *ws,
782 int target_options)
783{
784 if (debug_infrun)
785 fprintf_unfiltered (gdb_stdlog,
786 "\e[1;34minfrun: rocm_target_ops::wait\e[0m\n");
787
788 if (!ptid_is_gpu (ptid))
789 {
790 ptid_t event_ptid = beneath ()->wait (ptid, ws, target_options);
791 if (event_ptid != minus_one_ptid)
792 return event_ptid;
793 }
794
795 struct rocm_inferior_info *info = get_rocm_inferior_info ();
796 amd_dbgapi_process_id_t process_id = info->process_id;
797
798 /* Drain all the events from the amd_dbgapi, and preserve the ordering. */
799 if (info->wave_stop_events.empty ())
800 {
801 amd_dbgapi_process_set_progress (process_id,
802 AMD_DBGAPI_PROGRESS_NO_FORWARD);
803
804 /* Flush the async file first. */
805 if (target_is_async_p ())
806 async_file_flush ();
807
808 rocm_process_event_queue ();
809
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);
816 }
817
818 if (info->wave_stop_events.empty ())
819 return minus_one_ptid;
820
821 amd_dbgapi_wave_id_t event_wave_id;
822 amd_dbgapi_wave_stop_reason_t stop_reason;
823
824 std::tie (event_wave_id, stop_reason) = info->wave_stop_events.front ();
825 info->wave_stop_events.pop_front ();
826
389fe864
LM
827 struct inferior *inf = current_inferior ();
828 ptid_t event_ptid (inf->pid, 1, event_wave_id.handle);
5922befa 829
389fe864 830 if (!find_thread_ptid (inf->process_target (), event_ptid))
5922befa 831 {
389fe864
LM
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);
5922befa
LM
835 }
836
837 /* Since we are manipulating the register cache for the event thread,
838 make sure it is the current thread. */
389fe864 839 switch_to_thread (inf->process_target (), event_ptid);
5922befa
LM
840
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),
846 &stop_pc)
847 == AMD_DBGAPI_STATUS_SUCCESS)
848 {
389fe864 849 struct regcache *regcache = get_thread_regcache_for_ptid (event_ptid);
5922befa
LM
850 regcache->raw_supply (gdbarch_pc_regnum (regcache->arch ()), &stop_pc);
851 }
852 ws->kind = TARGET_WAITKIND_STOPPED;
853
854 if (stop_reason
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;
860 else if (stop_reason
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;
869 else
870 ws->value.sig = GDB_SIGNAL_0;
871
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 ())
875 async_file_mark ();
876
877 return event_ptid;
878}
879
880bool
881rocm_target_ops::stopped_by_sw_breakpoint ()
882{
883 if (!ptid_is_gpu (inferior_ptid))
884 return beneath ()->supports_stopped_by_sw_breakpoint ()
885 && beneath ()->stopped_by_sw_breakpoint ();
886
887 /* FIXME: we should check that the wave is not single-stepping. */
888
389fe864 889 struct regcache *regcache = get_thread_regcache_for_ptid (inferior_ptid);
5922befa
LM
890
891 CORE_ADDR bkpt_pc = regcache_read_pc (regcache)
892 - gdbarch_decr_pc_after_break (regcache->arch ());
893
894 return software_breakpoint_inserted_here_p (regcache->aspace (), bkpt_pc);
895}
896
897void
898rocm_target_ops::mourn_inferior ()
899{
900 /* FIXME: only unpush on the last activation. */
901 /* Disengage the ROCm target_ops. */
902 unpush_target (&rocm_ops);
903
904 beneath ()->mourn_inferior ();
905}
906
907void
908rocm_target_ops::fetch_registers (struct regcache *regcache, int regno)
909{
910 struct gdbarch *gdbarch = regcache->arch ();
911 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
912
913 /* delegate to the host routines when not on the device */
914
915 if (!rocm_is_amdgcn_gdbarch (gdbarch))
916 {
917 beneath ()->fetch_registers (regcache, regno);
918 return;
919 }
920
389fe864 921 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
5922befa
LM
922 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
923
924 gdb_byte raw[AMDGCN_MAX_REGISTER_SIZE];
925
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);
929
930 if (status == AMD_DBGAPI_STATUS_SUCCESS)
931 {
932 regcache->raw_supply (regno, raw);
933 }
934 else if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_REGISTER_ID)
935 {
936 warning (_ ("Couldn't read register %s (#%d)."),
937 gdbarch_register_name (gdbarch, regno), regno);
938 }
939}
940
941void
942rocm_target_ops::store_registers (struct regcache *regcache, int regno)
943{
944 struct gdbarch *gdbarch = regcache->arch ();
945 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
946 gdb_byte raw[AMDGCN_MAX_REGISTER_SIZE];
947
948 if (!rocm_is_amdgcn_gdbarch (gdbarch))
949 {
950 beneath ()->store_registers (regcache, regno);
951 return;
952 }
953
389fe864 954 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
5922befa
LM
955 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
956
957 regcache->raw_collect (regno, &raw);
958
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);
962
963 if (status != AMD_DBGAPI_STATUS_SUCCESS)
964 {
965 warning (_ ("Couldn't write register %s (#%d)."),
966 gdbarch_register_name (gdbarch, regno), regno);
967 }
968}
969
970/* Fix breakpoints created with an address location while the
971 architecture was set to the host (could be fixed in core GDB). */
972
973static void
974rocm_target_breakpoint_fixup (struct breakpoint *b)
975{
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)
980 {
981 b->gdbarch = b->loc->gdbarch;
982 }
983}
984
985struct gdbarch *
986rocm_target_ops::thread_architecture (ptid_t ptid)
987{
988 static std::result_of<decltype (&ptid_t::tid) (ptid_t)>::type last_tid = 0;
989 static struct gdbarch *cached_arch = nullptr;
990
991 if (!ptid_is_gpu (ptid))
992 return beneath ()->thread_architecture (ptid);
993
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)
997 return cached_arch;
998
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;
1002
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 ());
1008
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);
1016
1017 struct gdbarch_info info;
1018 gdbarch_info_init (&info);
1019
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;
1023
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);
1027
1028 return cached_arch;
1029}
1030
1031void
1032rocm_target_ops::update_thread_list ()
1033{
1034 for (inferior *inf : all_inferiors ())
1035 {
1036 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id (inf);
1037 amd_dbgapi_wave_id_t *wave_list;
1038 size_t count;
1039
1040 amd_dbgapi_changed_t changed;
1041 amd_dbgapi_status_t status;
1042 if ((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);
1046
1047 if (changed == AMD_DBGAPI_CHANGED_NO)
1048 continue;
1049
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);
1054 xfree (wave_list);
1055
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 ());
1060
1061 /* The wave_ids that are left require a new thread_info. */
1062 for (auto &&tid : threads)
1063 {
1064 ptid_t wave_ptid (inf->pid, 1, tid);
1065 amd_dbgapi_wave_state_t state;
1066
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)
1071 continue;
1072
389fe864
LM
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);
5922befa
LM
1076 }
1077 }
1078
1079 /* Give the beneath target a chance to do extra processing. */
1080 this->beneath ()->update_thread_list ();
1081}
1082
1083static void
1084rocm_target_solib_loaded (struct so_list *solib)
1085{
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)
1091 {
1092 value.second.solib = solib;
1093 value.second.is_loaded = true;
1094
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);
1099 }
1100}
1101
1102static void
1103rocm_target_solib_unloaded (struct so_list *solib)
1104{
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)
1110 {
1111 struct rocm_inferior_info *info = get_rocm_inferior_info ();
1112
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);
1116
1117 /* Delete breakpoints that were left inserted in this shared library.
1118 */
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))
1122 {
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);
1128 }
1129 else
1130 ++it;
1131
1132 value.second.solib = nullptr;
1133 value.second.is_loaded = false;
1134 }
1135}
1136
1137static void
1138rocm_target_inferior_created (struct target_ops *target, int from_tty)
1139{
1140 struct inferior *inf = current_inferior ();
1141 auto *info = get_rocm_inferior_info (inf);
1142 amd_dbgapi_status_t status;
1143
1144 if (!target_can_async_p ())
1145 {
1146 warning (
1147 _ ("ROCm-GDB requires target-async, GPU debugging is disabled"));
1148 return;
1149 }
1150
1151 gdb_assert (info->wave_stop_events.empty ());
1152
1153 status = amd_dbgapi_process_attach (inf, &info->process_id);
1154
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"));
1158
1159 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1160 {
1161 warning (_ ("Could not attach to process %d"), inf->pid);
1162 return;
1163 }
1164
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)
1169 {
1170 warning (_ ("Could not retrieve process %d's notifier"), inf->pid);
1171 amd_dbgapi_process_detach (info->process_id);
1172 return;
1173 }
1174
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. */
1177 add_file_handler (
1178 info->notifier,
1179 [] (int error, gdb_client_data client_data) {
1180 auto info_ = static_cast<struct rocm_inferior_info *> (client_data);
1181 int ret;
1182
1183 /* Drain the notifier pipe. */
1184 do
1185 {
1186 char buf;
1187 ret = read (info_->notifier, &buf, 1);
1188 }
1189 while (ret >= 0 || (ret == -1 && errno == EINTR));
1190
1191 /* Signal our async handler. */
1192 async_file_mark ();
1193 },
1194 info);
1195
1196 /* Attaching to the inferior may have generated runtime events, process
1197 them now. */
1198 rocm_process_event_queue ();
1199}
1200
1201static void
1202rocm_target_inferior_exit (struct inferior *inf)
1203{
1204 auto *info = get_rocm_inferior_info (inf);
1205
1206 amd_dbgapi_deactivated.notify ();
1207
86e751f5
LM
1208 if (info->notifier != -1)
1209 delete_file_handler (info->notifier);
5922befa
LM
1210
1211 amd_dbgapi_process_detach (info->process_id);
1212
1213 /* Delete the breakpoints that are still active. */
1214 for (auto &&value : info->breakpoint_map)
1215 delete_breakpoint (value.second);
1216
1217 rocm_inferior_data.clear (inf);
1218}
1219
1220static cli_style_option warning_style ("rocm_warning", ui_file_style::RED);
1221static cli_style_option info_style ("rocm_info", ui_file_style::GREEN);
1222static cli_style_option verbose_style ("rocm_verbose", ui_file_style::BLUE);
1223
1224static amd_dbgapi_callbacks_t dbgapi_callbacks = {
1225 /* allocate_memory. */
1226 .allocate_memory = xmalloc,
1227
1228 /* deallocate_memory. */
1229 .deallocate_memory = xfree,
1230
1231 /* get_os_pid. */
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);
1235
1236 *pid = inf->pid;
1237 return AMD_DBGAPI_STATUS_SUCCESS;
1238 },
1239
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);
1248
1249 if (!library_name || !library_state)
1250 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
1251
1252 if (info->notify_solib_map.find (library_id.handle)
1253 != info->notify_solib_map.end ())
1254 {
1255 /* This library id is already registered. */
1256 return AMD_DBGAPI_STATUS_ERROR;
1257 }
1258
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))
1264 {
1265 is_loaded = true;
1266 break;
1267 }
1268
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;
1275
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 }))
1282 .second)
1283 return AMD_DBGAPI_STATUS_ERROR;
1284
1285 *library_state = is_loaded ? AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
1286 : AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED;
1287
1288 return AMD_DBGAPI_STATUS_SUCCESS;
1289 },
1290
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);
1297
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;
1301
1302 info->notify_solib_map.erase (it);
1303 return AMD_DBGAPI_STATUS_SUCCESS;
1304 },
1305
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);
1313
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;
1317
1318 struct so_list *solib = it->second.solib;
1319 if (!solib)
1320 return AMD_DBGAPI_STATUS_ERROR_LIBRARY_NOT_LOADED;
1321
1322 solib_read_symbols (solib, 0);
1323 gdb_assert (solib->objfile);
1324
1325 struct bound_minimal_symbol msymbol
1326 = lookup_minimal_symbol (symbol_name, NULL, solib->objfile);
1327
1328 if (!msymbol.minsym || BMSYMBOL_VALUE_ADDRESS (msymbol) == 0)
1329 return AMD_DBGAPI_STATUS_ERROR_SYMBOL_NOT_FOUND;
1330
1331 *address = BMSYMBOL_VALUE_ADDRESS (msymbol);
1332 return AMD_DBGAPI_STATUS_SUCCESS;
1333 },
1334
1335 /* set_breakpoint callback. */
1336 .add_breakpoint =
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);
1343
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)
1348 {
1349 rocm_breakpoint_ops = bkpt_breakpoint_ops;
1350 rocm_breakpoint_ops.check_status = rocm_breakpoint_check_status;
1351 }
1352
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;
1356
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;
1361
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;
1372
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)
1381 return 1;
1382 return 0;
1383 },
1384 reinterpret_cast<void *> (&bp_loc));
1385
1386 if (!bp)
1387 error (_ ("Could not find breakpoint"));
1388
1389 info->breakpoint_map.emplace (breakpoint_id.handle, bp);
1390 return AMD_DBGAPI_STATUS_SUCCESS;
1391 },
1392
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);
1399
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;
1403
1404 delete_breakpoint (it->second);
1405 info->breakpoint_map.erase (it);
1406
1407 return AMD_DBGAPI_STATUS_SUCCESS;
1408 },
1409
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);
1417
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;
1421
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;
1426 else
1427 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
1428
1429 return AMD_DBGAPI_STATUS_SUCCESS;
1430 },
1431
1432 .log_message
1433 = [] (amd_dbgapi_log_level_t level, const char *message) -> void {
1434 gdb::optional<target_terminal::scoped_restore_terminal_state> tstate;
1435
1436 if (level > get_debug_amd_dbgapi_log_level ())
1437 return;
1438
1439 if (target_supports_terminal_ours ())
1440 {
1441 tstate.emplace ();
1442 target_terminal::ours_for_output ();
1443 }
1444
1445 if (filtered_printing_initialized ())
1446 wrap_here ("");
1447
1448 struct ui_file *out_file
1449 = (level >= AMD_DBGAPI_LOG_LEVEL_INFO) ? gdb_stdlog : gdb_stderr;
1450
1451 switch (level)
1452 {
1453 case AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR:
1454 fputs_unfiltered ("[amd-dbgapi]: ", out_file);
1455 break;
1456 case AMD_DBGAPI_LOG_LEVEL_WARNING:
1457 fputs_styled ("[amd-dbgapi]: ", warning_style.style (), out_file);
1458 break;
1459 case AMD_DBGAPI_LOG_LEVEL_INFO:
1460 fputs_styled ("[amd-dbgapi]: ", info_style.style (), out_file);
1461 break;
1462 case AMD_DBGAPI_LOG_LEVEL_VERBOSE:
1463 fputs_styled ("[amd-dbgapi]: ", verbose_style.style (), out_file);
1464 break;
1465 }
1466
1467 fputs_unfiltered (message, out_file);
1468 fputs_unfiltered ("\n", out_file);
1469 }
1470};
1471
1472/* Implementation of `_wave_id' variable. */
1473
1474static struct value *
1475rocm_wave_id_make_value (struct gdbarch *gdbarch, struct internalvar *var,
1476 void *ignore)
1477{
1478 if (ptid_is_gpu (inferior_ptid))
1479 {
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;
1483
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)
1493 {
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);
1497
1498 return value_cstring (wave_id_str.data (), wave_id_str.length () + 1,
1499 builtin_type (gdbarch)->builtin_char);
1500 }
1501 }
1502
1503 return allocate_value (builtin_type (gdbarch)->builtin_void);
1504}
1505
1506static const struct internalvar_funcs rocm_wave_id_funcs
1507 = { rocm_wave_id_make_value, NULL, NULL };
1508
1509/* List of set/show debug amd_dbgapi commands. */
1510struct cmd_list_element *set_debug_amd_dbgapi_list;
1511struct cmd_list_element *show_debug_amd_dbgapi_list;
1512
1513static void
1514set_debug_amd_dbgapi (const char *arg, int from_tty)
1515{
1516 help_list (set_debug_amd_dbgapi_list, "set debug amd-dbgapi ",
1517 (enum command_class) - 1, gdb_stdout);
1518}
1519
1520static void
1521show_debug_amd_dbgapi (const char *args, int from_tty)
1522{
1523 cmd_show_list (show_debug_amd_dbgapi_list, from_tty, "");
1524}
1525
1526constexpr char amd_dbgapi_log_level_off[] = "off";
1527constexpr char amd_dbgapi_log_level_error[] = "error";
1528constexpr char amd_dbgapi_log_level_warning[] = "warning";
1529constexpr char amd_dbgapi_log_level_info[] = "info";
1530constexpr char amd_dbgapi_log_level_verbose[] = "verbose";
1531
1532constexpr 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,
1538 nullptr };
1539
1540static const char *debug_amd_dbgapi_log_level = amd_dbgapi_log_level_error;
1541
1542static amd_dbgapi_log_level_t
1543get_debug_amd_dbgapi_log_level ()
1544{
1545 size_t pos;
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])
1548 break;
1549
1550 gdb_assert (debug_amd_dbgapi_log_level_enums[pos]);
1551 return static_cast<amd_dbgapi_log_level_t> (pos);
1552}
1553
1554static void
1555set_debug_amd_dbgapi_log_level (const char *args, int from_tty,
389fe864 1556 struct cmd_list_element *c)
5922befa
LM
1557{
1558 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1559}
1560
1561static void
1562show_debug_amd_dbgapi_log_level (struct ui_file *file, int from_tty,
389fe864 1563 struct cmd_list_element *c, const char *value)
5922befa
LM
1564{
1565 fprintf_filtered (file, _ ("The amd-dbgapi log level is %s.\n"), value);
1566}
1567
1568static void
1569info_agents_command (const char *args, int from_tty)
1570{
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;
1574
1575 amd_dbgapi_agent_id_t *agent_list;
1576 size_t count = 0;
1577
1578 if (process_id.handle != AMD_DBGAPI_PROCESS_NONE.handle
1579 && (status
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);
1583
1584 if (!count && !uiout->is_mi_like_p ())
1585 {
389fe864 1586 uiout->field_string (NULL, _ ("No agents are currently active.\n"));
5922befa
LM
1587 return;
1588 }
1589
1590 /* Calculate the maximum size needed to print the agents names. */
1591 std::vector<std::string> agent_names (count);
1592
1593 size_t max_name_len = 0;
1594 for (size_t i = 0; i < count; ++i)
1595 {
1596 char *agent_name;
1597
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)
1602 {
1603 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID)
1604 agent_names[i] = "N/A";
1605 else
1606 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status);
1607 }
1608 else
1609 {
1610 agent_names[i] = agent_name;
1611 xfree (agent_name);
1612 }
1613
1614 max_name_len = std::max (max_name_len, agent_names[i].size ());
1615 }
1616
1617 /* Header: */
1618 ui_out_emit_table table_emmitter (uiout, 7, count, "InfoRocmDevicesTable");
1619
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",
1623 "Device 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 ();
1629
1630 /* Rows: */
1631 for (size_t i = 0; i < count; ++i)
1632 {
1633 ui_out_emit_tuple tuple_emitter (uiout, "InfoRocmDevicesRow");
1634
1635 /* agent */
1636 uiout->field_signed ("agent_id", agent_list[i].handle);
1637
1638 /* location */
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)
1644 {
1645 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID)
1646 uiout->field_string ("location_id", "N/A");
1647 else
1648 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status);
1649 }
1650 else
1651 uiout->field_string (
1652 "location_id",
1653 string_printf ("%02x:%02x.%d", (location_id >> 8) & 0xFF,
1654 (location_id >> 3) & 0x1F, location_id & 0x7));
1655
1656 /* name */
1657 uiout->field_string ("name", agent_names[i]);
1658
1659 /* num_se, num_cu, simd, waves */
1660
1661#define UIOUT_FIELD_INT(name, query) \
1662 uint32_t name; \
1663 if ((status = amd_dbgapi_agent_get_info (process_id, agent_list[i], query, \
1664 sizeof (name), &name)) \
1665 != AMD_DBGAPI_STATUS_SUCCESS) \
1666 { \
1667 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID) \
1668 uiout->field_string (#name, "N/A"); \
1669 else \
1670 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status); \
1671 } \
1672 else \
1673 uiout->field_signed (#name, name);
1674
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);
1679
1680#undef UIOUT_FIELD_INT
1681
1682 uiout->text ("\n");
1683 }
1684
1685 xfree (agent_list);
1686 gdb_flush (gdb_stdout);
1687}
1688
1689/* -Wmissing-prototypes */
1690extern initialize_file_ftype _initialize_rocm_tdep;
1691
1692void
1693_initialize_rocm_tdep (void)
1694{
1695 /* Initialize the ROCm Debug API. */
1696 if (amd_dbgapi_initialize (&dbgapi_callbacks) != AMD_DBGAPI_STATUS_SUCCESS)
1697 return;
1698
1699 /* Set the initial log level. */
1700 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1701
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);
1708
1709 amd_dbgapi_activated.attach (rocm_target_dbgapi_activated);
1710 amd_dbgapi_deactivated.attach (rocm_target_dbgapi_deactivated);
1711
1712 create_internalvar_type_lazy ("_wave_id", &rocm_wave_id_funcs, NULL);
1713
389fe864
LM
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,
1717 &setdebuglist);
5922befa 1718
389fe864
LM
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,
1722 &showdebuglist);
5922befa
LM
1723
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);
1735
1736 add_cmd ("agents", class_info, info_agents_command,
1737 _ ("Info about currently active agents."), &infolist);
1738}
This page took 0.11712 seconds and 4 git commands to generate.