Handle multiple target events before commit resume
[deliverable/binutils-gdb.git] / gdb / rocm-tdep.c
CommitLineData
abeeff98
LM
1/* Target-dependent code for ROCm.
2
ca9af5a1
LM
3 Copyright (C) 2019-2020 Free Software Foundation, Inc.
4 Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
abeeff98
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{
96dd14e9
LM
78 /* True if the target is activated. */
79 bool activated{ false };
80
abeeff98 81 /* The amd_dbgapi_process_id for this inferior. */
b8ff49b7 82 amd_dbgapi_process_id_t process_id{ AMD_DBGAPI_PROCESS_NONE };
abeeff98
LM
83
84 /* The amd_dbgapi_notifier_t for this inferior. */
b8ff49b7 85 amd_dbgapi_notifier_t notifier{ -1 };
abeeff98
LM
86
87 /* True if commit_resume should all-start the GPU queues. */
88 bool commit_resume_all_start;
89
96dd14e9 90 /* True if the inferior has exited. */
243f18ba
LM
91 bool has_exited{ false };
92
abeeff98
LM
93 std::unordered_map<decltype (amd_dbgapi_breakpoint_id_t::handle),
94 struct breakpoint *>
95 breakpoint_map;
96
97 /* List of pending events the rocm target retrieved from the dbgapi. */
98 std::list<std::pair<amd_dbgapi_wave_id_t, amd_dbgapi_wave_stop_reason_t>>
99 wave_stop_events;
100
101 /* Map of rocm_notify_shared_library_info's for libraries that have been
102 registered to receive notifications when loading/unloading. */
103 std::unordered_map<decltype (amd_dbgapi_shared_library_id_t::handle),
104 struct rocm_notify_shared_library_info>
105 notify_solib_map;
106};
107
108static amd_dbgapi_event_id_t
109rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind
110 = AMD_DBGAPI_EVENT_KIND_NONE);
111
112/* Return the inferior's rocm_inferior_info struct. */
113static struct rocm_inferior_info *
114get_rocm_inferior_info (struct inferior *inferior = nullptr);
115
116static const target_info rocm_ops_info
117 = { "rocm", N_ ("ROCm GPU debugging support"),
118 N_ ("ROCm GPU debugging support") };
119
120static amd_dbgapi_log_level_t get_debug_amd_dbgapi_log_level ();
121
122struct rocm_target_ops final : public target_ops
123{
124 const target_info &
125 info () const override
126 {
127 return rocm_ops_info;
128 }
129 strata
130 stratum () const override
131 {
132 return arch_stratum;
133 }
134
36f3baab 135 void close () override;
abeeff98 136 void mourn_inferior () override;
96dd14e9 137 void detach (inferior *inf, int from_tty) override;
abeeff98
LM
138
139 void async (int enable) override;
140
141 ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
142 void resume (ptid_t, int, enum gdb_signal) override;
143 void commit_resume () override;
144 void stop (ptid_t ptid) override;
145
146 void fetch_registers (struct regcache *, int) override;
147 void store_registers (struct regcache *, int) override;
148
149 void update_thread_list () override;
150
151 struct gdbarch *thread_architecture (ptid_t) override;
152
153 std::string pid_to_str (ptid_t ptid) override;
154
155 const char *thread_name (thread_info *tp) override;
156
157 const char *extra_thread_info (thread_info *tp) override;
158
159 bool thread_alive (ptid_t ptid) override;
160
161 enum target_xfer_status xfer_partial (enum target_object object,
162 const char *annex, gdb_byte *readbuf,
163 const gdb_byte *writebuf,
164 ULONGEST offset, ULONGEST len,
165 ULONGEST *xfered_len) override;
166
167 bool
168 stopped_by_watchpoint () override
169 {
170 return !ptid_is_gpu (inferior_ptid)
171 && beneath ()->stopped_by_watchpoint ();
172 }
173
174 bool
175 stopped_data_address (CORE_ADDR *addr_p) override
176 {
177 return !ptid_is_gpu (inferior_ptid)
178 && beneath ()->stopped_data_address (addr_p);
179 }
180
181 bool
182 supports_stopped_by_sw_breakpoint () override
183 {
184 return true;
185 }
186
187 bool stopped_by_sw_breakpoint () override;
188
189 bool
190 stopped_by_hw_breakpoint () override
191 {
192 return !ptid_is_gpu (inferior_ptid)
193 && beneath ()->stopped_by_hw_breakpoint ();
194 }
195};
196
197/* ROCm's target vector. */
198static struct rocm_target_ops rocm_ops;
199
200/* ROCm breakpoint ops. */
201static struct breakpoint_ops rocm_breakpoint_ops;
202
203/* Per-inferior data key. */
204static const struct inferior_key<rocm_inferior_info> rocm_inferior_data;
205
206/* The read/write ends of the pipe registered as waitable file in the
207 event loop. */
208static int rocm_event_pipe[2] = { -1, -1 };
209
210/* Flush the event pipe. */
211
5cf3a303 212static void
abeeff98
LM
213async_file_flush (void)
214{
215 int ret;
216 char buf;
217
218 do
219 {
220 ret = read (rocm_event_pipe[0], &buf, 1);
221 }
222 while (ret >= 0 || (ret == -1 && errno == EINTR));
223}
224
225/* Put something (anything, doesn't matter what, or how much) in event
226 pipe, so that the select/poll in the event-loop realizes we have
227 something to process. */
228
229static void
230async_file_mark (void)
231{
232 int ret;
233
234 /* It doesn't really matter what the pipe contains, as long we end
235 up with something in it. Might as well flush the previous
236 left-overs. */
237 async_file_flush ();
238
239 do
240 {
241 ret = write (rocm_event_pipe[1], "+", 1);
242 }
243 while (ret == -1 && errno == EINTR);
244
245 /* Ignore EAGAIN. If the pipe is full, the event loop will already
246 be awakened anyway. */
247}
248
249/* Fetch the rocm_inferior_info data for the given inferior. */
250
251static struct rocm_inferior_info *
252get_rocm_inferior_info (struct inferior *inferior)
253{
254 if (!inferior)
255 inferior = current_inferior ();
256
257 struct rocm_inferior_info *info = rocm_inferior_data.get (inferior);
258
259 if (!info)
260 info = rocm_inferior_data.emplace (inferior);
261
262 return info;
263}
264
265/* Fetch the amd_dbgapi_process_id for the given inferior. */
266
267amd_dbgapi_process_id_t
268get_amd_dbgapi_process_id (struct inferior *inferior)
269{
270 return get_rocm_inferior_info (inferior)->process_id;
271}
272
9e275233
LM
273static void
274rocm_breakpoint_re_set (struct breakpoint *b)
275{
276}
277
abeeff98
LM
278static void
279rocm_breakpoint_check_status (struct bpstats *bs)
280{
281 struct rocm_inferior_info *info = get_rocm_inferior_info ();
282 amd_dbgapi_process_id_t process_id = info->process_id;
283 amd_dbgapi_status_t status;
284
285 bs->stop = 0;
286 bs->print_it = print_it_noop;
287
288 /* Find the address the breakpoint is set at. */
289 auto it = std::find_if (
290 info->breakpoint_map.begin (), info->breakpoint_map.end (),
291 [=] (const decltype (info->breakpoint_map)::value_type &value) {
292 return value.second == bs->breakpoint_at;
293 });
294
295 if (it == info->breakpoint_map.end ())
296 error (_ ("Could not find breakpoint_id for breakpoint at %#lx"),
297 bs->bp_location_at->address);
298
299 amd_dbgapi_breakpoint_id_t breakpoint_id{ it->first };
300 amd_dbgapi_breakpoint_action_t action;
301
7d43aaec
T
302 status = amd_dbgapi_report_breakpoint_hit (
303 process_id, breakpoint_id,
304 reinterpret_cast<amd_dbgapi_client_thread_id_t> (inferior_thread ()),
305 &action);
abeeff98
LM
306
307 if (status != AMD_DBGAPI_STATUS_SUCCESS)
308 error (_ ("amd_dbgapi_report_breakpoint_hit failed: breakpoint_%ld "
309 "at %#lx (rc=%d)"),
310 breakpoint_id.handle, bs->bp_location_at->address, status);
311
312 if (action == AMD_DBGAPI_BREAKPOINT_ACTION_RESUME)
313 return;
314
315 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
316 a breakpoint resume event for this breakpoint_id is seen. */
317
318 amd_dbgapi_event_id_t resume_event_id
319 = rocm_process_event_queue (AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
320
321 /* We should always get a breakpoint_resume event after processing all
322 events generated by reporting the breakpoint was hit. */
323 gdb_assert (resume_event_id.handle != AMD_DBGAPI_EVENT_NONE.handle);
324
325 amd_dbgapi_breakpoint_id_t resume_breakpoint_id;
326 status = amd_dbgapi_event_get_info (
327 process_id, resume_event_id, AMD_DBGAPI_EVENT_INFO_BREAKPOINT,
328 sizeof (resume_breakpoint_id), &resume_breakpoint_id);
329
330 if (status != AMD_DBGAPI_STATUS_SUCCESS)
331 error (_ ("amd_dbgapi_event_get_info failed (rc=%d)"), status);
332
333 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint]
334 sequences cannot interleave, so this breakpoint resume event must be
335 for our breakpoint_id. */
336 if (resume_breakpoint_id.handle != breakpoint_id.handle)
337 error (_ ("breakpoint resume event is not for this breakpoint. "
338 "Expected breakpoint_%ld, got breakpoint_%ld"),
339 breakpoint_id.handle, resume_breakpoint_id.handle);
340
341 amd_dbgapi_event_processed (process_id, resume_event_id);
342}
343
344static void
345rocm_target_dbgapi_activated ()
346{
347 /* FIXME: only push on the first activation. */
348 /* Engage the ROCm target_ops and so_ops. */
349 push_target (&rocm_ops);
350}
351
352static void
353rocm_target_dbgapi_deactivated ()
354{
355 /* FIXME: only unpush on the last activation. */
356 /* Disengage the ROCm target_ops. */
357 unpush_target (&rocm_ops);
358}
359
360bool
361rocm_target_ops::thread_alive (ptid_t ptid)
362{
363 if (!ptid_is_gpu (ptid))
364 return beneath ()->thread_alive (ptid);
365
366 /* Check that the wave_id is valid. */
367
368 inferior *inf = find_inferior_ptid (ptid);
369 if (!inf)
370 return false;
371
372 amd_dbgapi_wave_state_t state;
373 return amd_dbgapi_wave_get_info (
374 get_amd_dbgapi_process_id (inf), get_amd_dbgapi_wave_id (ptid),
375 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state), &state)
376 == AMD_DBGAPI_STATUS_SUCCESS;
377}
378
379const char *
380rocm_target_ops::thread_name (thread_info *tp)
381{
382 if (!ptid_is_gpu (tp->ptid))
383 return beneath ()->thread_name (tp);
384
223465e7
LM
385 /* Return the process's comm value—that is, the command name associated with
386 the process. */
abeeff98 387
223465e7
LM
388 char comm_path[128];
389 xsnprintf (comm_path, sizeof (comm_path), "/proc/%ld/comm",
390 (long)tp->ptid.pid ());
391
392 gdb_file_up comm_file = gdb_fopen_cloexec (comm_path, "r");
393 if (!comm_file)
394 return nullptr;
abeeff98 395
223465e7
LM
396#if !defined(TASK_COMM_LEN)
397#define TASK_COMM_LEN 16 /* As defined in the kernel's sched.h. */
398#endif
abeeff98 399
223465e7
LM
400 static char comm_buf[TASK_COMM_LEN];
401 const char *comm_value;
abeeff98 402
223465e7
LM
403 comm_value = fgets (comm_buf, sizeof (comm_buf), comm_file.get ());
404 comm_buf[sizeof (comm_buf) - 1] = '\0';
405
406 /* Make sure there is no newline at the end. */
407 if (comm_value)
408 {
409 for (int i = 0; i < sizeof (comm_buf); i++)
410 if (comm_buf[i] == '\n')
411 {
412 comm_buf[i] = '\0';
413 break;
414 }
abeeff98
LM
415 }
416
223465e7 417 return comm_value;
abeeff98
LM
418}
419
420std::string
421rocm_target_ops::pid_to_str (ptid_t ptid)
422{
423 if (!ptid_is_gpu (ptid))
424 {
425 return beneath ()->pid_to_str (ptid);
426 }
427
428 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
429 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (ptid);
430 amd_dbgapi_dispatch_id_t dispatch_id;
431 uint32_t group_ids[3], wave_in_group;
432
433 if (amd_dbgapi_wave_get_info (process_id, wave_id,
434 AMD_DBGAPI_WAVE_INFO_DISPATCH,
435 sizeof (dispatch_id), &dispatch_id)
436 != AMD_DBGAPI_STATUS_SUCCESS
437 || amd_dbgapi_wave_get_info (process_id, wave_id,
438 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD,
439 sizeof (group_ids), &group_ids)
440 != AMD_DBGAPI_STATUS_SUCCESS
441 || amd_dbgapi_wave_get_info (
442 process_id, wave_id,
443 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP,
444 sizeof (wave_in_group), &wave_in_group)
445 != AMD_DBGAPI_STATUS_SUCCESS)
8f156997 446 return std::string ("AMDGPU Thread");
abeeff98 447 else
8f156997 448 return string_printf ("AMDGPU Thread %ld.%ld (%d,%d,%d)/%d",
abeeff98
LM
449 dispatch_id.handle, wave_id.handle, group_ids[2],
450 group_ids[1], group_ids[0], wave_in_group);
451}
452
453const char *
454rocm_target_ops::extra_thread_info (thread_info *tp)
455{
456 if (!ptid_is_gpu (tp->ptid))
457 beneath ()->extra_thread_info (tp);
458
459 return NULL;
460}
461
462enum target_xfer_status
463rocm_target_ops::xfer_partial (enum target_object object, const char *annex,
464 gdb_byte *readbuf, const gdb_byte *writebuf,
465 ULONGEST offset, ULONGEST requested_len,
466 ULONGEST *xfered_len)
467{
468 gdb::optional<scoped_restore_current_thread> maybe_restore_thread;
469
470 if (ptid_is_gpu (inferior_ptid))
471 {
472 gdb_assert (requested_len && xfered_len && "checking invariants");
473
474 if (object != TARGET_OBJECT_MEMORY)
475 return TARGET_XFER_E_IO;
476
477 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
478 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid);
479
480 amd_dbgapi_architecture_id_t architecture_id;
481 amd_dbgapi_address_space_id_t address_space_id;
482
483 if (amd_dbgapi_wave_get_info (process_id, wave_id,
484 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE,
485 sizeof (architecture_id), &architecture_id)
486 != AMD_DBGAPI_STATUS_SUCCESS
487 || amd_dbgapi_architecture_get_info (
488 architecture_id,
489 AMD_DBGAPI_ARCHITECTURE_INFO_DEFAULT_GLOBAL_ADDRESS_SPACE,
490 sizeof (address_space_id), &address_space_id)
491 != AMD_DBGAPI_STATUS_SUCCESS)
edc83450 492 return TARGET_XFER_EOF;
abeeff98
LM
493
494 size_t len = requested_len;
495 amd_dbgapi_status_t status;
496
497 if (readbuf)
498 status = amd_dbgapi_read_memory (
499 process_id, wave_id, 0, address_space_id, offset, &len, readbuf);
500 else
501 status = amd_dbgapi_write_memory (
502 process_id, wave_id, 0, address_space_id, offset, &len, writebuf);
503
504 if (status != AMD_DBGAPI_STATUS_SUCCESS)
edc83450 505 return TARGET_XFER_EOF;
abeeff98
LM
506
507 *xfered_len = len;
508 return TARGET_XFER_OK;
509 }
510 else
511 return beneath ()->xfer_partial (object, annex, readbuf, writebuf, offset,
512 requested_len, xfered_len);
513}
514
515void
516rocm_target_ops::resume (ptid_t ptid, int step, enum gdb_signal signo)
517{
518 struct rocm_inferior_info *info = get_rocm_inferior_info ();
519
520 if (debug_infrun)
521 fprintf_unfiltered (
522 gdb_stdlog,
523 "\e[1;34minfrun: rocm_target_ops::resume ([%d,%ld,%ld])\e[0m\n",
524 ptid.pid (), ptid.lwp (), ptid.tid ());
525
526 /* Check if the thread focus is on the GPU device. */
527 if (ptid == minus_one_ptid || !ptid_is_gpu (ptid))
528 {
529 beneath ()->resume (ptid, step, signo);
530 if (ptid != minus_one_ptid)
531 return;
532 }
533
534 /* A specific PTID means `step only this process id'. */
535 bool resume_one = ptid != minus_one_ptid && !ptid.is_pid ();
536 gdb_assert (resume_one || !step);
537
538 if (!resume_one)
539 error (_ ("internal error - unimplemented "));
540
541 amd_dbgapi_process_set_progress (info->process_id,
542 AMD_DBGAPI_PROGRESS_NO_FORWARD);
543
544 amd_dbgapi_status_t status = amd_dbgapi_wave_resume (
545 info->process_id, get_amd_dbgapi_wave_id (ptid),
546 step ? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP
547 : AMD_DBGAPI_RESUME_MODE_NORMAL);
548 if (status != AMD_DBGAPI_STATUS_SUCCESS)
549 warning (_ ("Could not resume %s (rc=%d)"),
550 target_pid_to_str (ptid).c_str (), status);
551
552 info->commit_resume_all_start = true;
553}
554
555void
556rocm_target_ops::commit_resume ()
557{
558 struct rocm_inferior_info *info = get_rocm_inferior_info ();
559
560 if (debug_infrun)
561 fprintf_unfiltered (
562 gdb_stdlog,
563 "\e[1;34minfrun: rocm_target_ops::commit_resume ()\e[0m\n");
564
565 beneath ()->commit_resume ();
566
567 if (info->commit_resume_all_start)
568 {
569 amd_dbgapi_process_set_progress (info->process_id,
570 AMD_DBGAPI_PROGRESS_NORMAL);
571 info->commit_resume_all_start = false;
572 }
573
574 if (target_can_async_p ())
575 target_async (1);
576}
577
578static void
579rocm_target_stop_one_wave (ptid_t ptid)
580{
581 amd_dbgapi_status_t status;
582
583 status = amd_dbgapi_wave_stop (get_amd_dbgapi_process_id (),
584 get_amd_dbgapi_wave_id (ptid));
585
586 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
587 {
588 /* the wave must have exited, set the thread status to reflect that. */
589 auto *tp = find_thread_ptid (ptid);
590 gdb_assert (tp);
591
592 tp->state = THREAD_EXITED;
593 }
594 else if (status != AMD_DBGAPI_STATUS_SUCCESS)
595 warning (_ ("Could not stop %s (rc=%d)"),
596 target_pid_to_str (ptid).c_str (), status);
597}
598
599void
600rocm_target_ops::stop (ptid_t ptid)
601{
602 if (debug_infrun)
603 fprintf_unfiltered (
604 gdb_stdlog,
605 "\e[1;34minfrun: rocm_target_ops::stop ([%d,%ld,%ld])\e[0m\n",
606 ptid.pid (), ptid.lwp (), ptid.tid ());
607
608 if (ptid == minus_one_ptid || !ptid_is_gpu (ptid))
609 {
610 beneath ()->stop (ptid);
611 if (ptid != minus_one_ptid)
612 return;
613 }
614
615 if (ptid == minus_one_ptid)
616 error (_ ("internal error - unimplemented "));
617
618 rocm_target_stop_one_wave (ptid);
619}
620
621static void
622handle_target_event (int error, gdb_client_data client_data)
623{
624 struct rocm_inferior_info *info = get_rocm_inferior_info ();
625 amd_dbgapi_process_id_t process_id = info->process_id;
626
627 amd_dbgapi_process_set_progress (process_id, AMD_DBGAPI_PROGRESS_NO_FORWARD);
628
629 /* Flush the async file first. */
630 if (target_is_async_p ())
631 async_file_flush ();
632
633 rocm_process_event_queue ();
634
635 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
636 we can keep the process in progress_no_forward mode. The infrun loop
637 will enable forward progress when a thread is resumed. */
638 if (non_stop || info->wave_stop_events.empty ())
639 amd_dbgapi_process_set_progress (process_id, AMD_DBGAPI_PROGRESS_NORMAL);
640
641 if (!info->wave_stop_events.empty ())
642 inferior_event_handler (INF_REG_EVENT, nullptr);
643}
644
645void
646rocm_target_ops::async (int enable)
647{
648 beneath ()->async (enable);
649
650 if (enable)
651 {
652 if (rocm_event_pipe[0] != -1)
653 return;
654
655 if (gdb_pipe_cloexec (rocm_event_pipe) == -1)
656 internal_error (__FILE__, __LINE__, "creating event pipe failed.");
657
658 ::fcntl (rocm_event_pipe[0], F_SETFL, O_NONBLOCK);
659 ::fcntl (rocm_event_pipe[1], F_SETFL, O_NONBLOCK);
660
661 add_file_handler (rocm_event_pipe[0], handle_target_event, nullptr);
662
663 /* There may be pending events to handle. Tell the event loop
664 to poll them. */
665 async_file_mark ();
666 }
667 else
668 {
abeeff98
LM
669 if (rocm_event_pipe[0] == -1)
670 return;
671
36f3baab
LM
672 delete_file_handler (rocm_event_pipe[0]);
673
abeeff98
LM
674 ::close (rocm_event_pipe[0]);
675 ::close (rocm_event_pipe[1]);
676 rocm_event_pipe[0] = -1;
677 rocm_event_pipe[1] = -1;
678 }
679}
680
681static void
682rocm_process_one_event (amd_dbgapi_event_id_t event_id,
683 amd_dbgapi_event_kind_t event_kind)
684{
685 struct rocm_inferior_info *info = get_rocm_inferior_info ();
686 amd_dbgapi_process_id_t process_id = info->process_id;
687 amd_dbgapi_status_t status;
688
689 switch (event_kind)
690 {
691 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
692 {
693 amd_dbgapi_wave_id_t wave_id;
694 if ((status = amd_dbgapi_event_get_info (process_id, event_id,
695 AMD_DBGAPI_EVENT_INFO_WAVE,
696 sizeof (wave_id), &wave_id))
697 != AMD_DBGAPI_STATUS_SUCCESS)
698 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
699 event_id.handle, status);
700
701 amd_dbgapi_wave_stop_reason_t stop_reason;
702 status = amd_dbgapi_wave_get_info (process_id, wave_id,
703 AMD_DBGAPI_WAVE_INFO_STOP_REASON,
704 sizeof (stop_reason), &stop_reason);
705
706 if (status != AMD_DBGAPI_STATUS_SUCCESS
707 && status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID)
708 error (_ ("wave_get_info for wave_%ld failed (rc=%d)"),
709 wave_id.handle, status);
710
711 /* The wave may have exited, or the queue went into an error
712 state. In such cases, we will see another wave command
713 terminated event, and handle the wave termination then. */
714
715 if (status == AMD_DBGAPI_STATUS_SUCCESS)
716 info->wave_stop_events.emplace_back (
717 std::make_pair (wave_id, stop_reason));
718 }
719 break;
720
721 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED:
722 amd_dbgapi_code_object_list_updated.notify ();
723 break;
724
725 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME:
726 /* Breakpoint resume events should be handled by the breakpoint
727 action, and this code should not reach this. */
728 gdb_assert_not_reached (_ ("unhandled event kind"));
729 break;
730
731 case AMD_DBGAPI_EVENT_KIND_RUNTIME:
732 {
733 amd_dbgapi_runtime_state_t runtime_state;
734
735 if ((status = amd_dbgapi_event_get_info (
736 process_id, event_id, AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
737 sizeof (runtime_state), &runtime_state))
738 != AMD_DBGAPI_STATUS_SUCCESS)
739 error (_ ("event_get_info for event_%ld failed (rc=%d)"),
740 event_id.handle, status);
741
742 switch (runtime_state)
743 {
96dd14e9
LM
744 case AMD_DBGAPI_RUNTIME_STATE_LOADED_UNSUPPORTED:
745 warning (_ ("ROCgdb: low-level runtime version not supported"));
746 break;
747
abeeff98
LM
748 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUPPORTED:
749 amd_dbgapi_activated.notify ();
96dd14e9 750 info->activated = true;
abeeff98
LM
751 break;
752
753 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED:
96dd14e9
LM
754 if (info->activated)
755 amd_dbgapi_deactivated.notify ();
abeeff98
LM
756 break;
757 }
758 }
759 break;
760
761 default:
762 error (_ ("event kind (%d) not supported"), event_kind);
763 }
764
765 amd_dbgapi_event_processed (process_id, event_id);
766}
767
768/* Drain the amd_dbgapi event queue until an event of the given type is seen.
769 If no particular event kind is specified (AMD_DBGAPI_EVENT_KIND_NONE), the
770 event queue is completely drained. Wave stop events that are not returned
771 are re-queued into the current's process pending wave events. */
772static amd_dbgapi_event_id_t
773rocm_process_event_queue (amd_dbgapi_event_kind_t until_event_kind)
774{
775 struct rocm_inferior_info *info = get_rocm_inferior_info ();
776
777 while (true)
778 {
779 amd_dbgapi_event_id_t event_id;
780 amd_dbgapi_event_kind_t event_kind;
781
782 amd_dbgapi_status_t status = amd_dbgapi_next_pending_event (
783 info->process_id, &event_id, &event_kind);
784
785 if (status != AMD_DBGAPI_STATUS_SUCCESS)
786 error (_ ("next_pending_event failed (rc=%d)"), status);
787
788 if (event_id.handle == AMD_DBGAPI_EVENT_NONE.handle
789 || event_kind == until_event_kind)
790 return event_id;
791
792 rocm_process_one_event (event_id, event_kind);
793 }
794}
795
796ptid_t
797rocm_target_ops::wait (ptid_t ptid, struct target_waitstatus *ws,
798 int target_options)
799{
800 if (debug_infrun)
801 fprintf_unfiltered (gdb_stdlog,
802 "\e[1;34minfrun: rocm_target_ops::wait\e[0m\n");
803
804 if (!ptid_is_gpu (ptid))
805 {
806 ptid_t event_ptid = beneath ()->wait (ptid, ws, target_options);
807 if (event_ptid != minus_one_ptid)
808 return event_ptid;
809 }
810
811 struct rocm_inferior_info *info = get_rocm_inferior_info ();
812 amd_dbgapi_process_id_t process_id = info->process_id;
813
814 /* Drain all the events from the amd_dbgapi, and preserve the ordering. */
815 if (info->wave_stop_events.empty ())
816 {
817 amd_dbgapi_process_set_progress (process_id,
818 AMD_DBGAPI_PROGRESS_NO_FORWARD);
819
820 /* Flush the async file first. */
821 if (target_is_async_p ())
822 async_file_flush ();
823
824 rocm_process_event_queue ();
825
826 /* In all-stop mode, unless the event queue is empty (spurious wake-up),
827 we can keep the process in progress_no_forward mode. The infrun loop
828 will enable forward progress when a thread is resumed. */
829 if (non_stop || info->wave_stop_events.empty ())
830 amd_dbgapi_process_set_progress (process_id,
831 AMD_DBGAPI_PROGRESS_NORMAL);
832 }
833
834 if (info->wave_stop_events.empty ())
835 return minus_one_ptid;
836
837 amd_dbgapi_wave_id_t event_wave_id;
838 amd_dbgapi_wave_stop_reason_t stop_reason;
839
840 std::tie (event_wave_id, stop_reason) = info->wave_stop_events.front ();
841 info->wave_stop_events.pop_front ();
842
843 ptid_t event_ptid (current_inferior ()->pid, 1, event_wave_id.handle);
844
845 if (!find_thread_ptid (event_ptid))
846 {
847 add_thread_silent (event_ptid);
848 set_running (event_ptid, 1);
849 set_executing (event_ptid, 1);
850 }
851
852 /* Since we are manipulating the register cache for the event thread,
853 make sure it is the current thread. */
854 switch_to_thread (event_ptid);
855
856 /* By caching the PC now, we avoid having to suspend/resume the queue
857 later when we need to access it. */
858 amd_dbgapi_global_address_t stop_pc;
859 if (amd_dbgapi_wave_get_info (process_id, event_wave_id,
860 AMD_DBGAPI_WAVE_INFO_PC, sizeof (stop_pc),
861 &stop_pc)
862 == AMD_DBGAPI_STATUS_SUCCESS)
863 {
864 struct regcache *regcache = get_thread_regcache (event_ptid);
865 regcache->raw_supply (gdbarch_pc_regnum (regcache->arch ()), &stop_pc);
866 }
867 ws->kind = TARGET_WAITKIND_STOPPED;
868
4c064e0d 869 if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION)
abeeff98
LM
870 ws->value.sig = GDB_SIGNAL_SEGV;
871 else if (stop_reason
872 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL
873 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0
874 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW
875 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW
876 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT
877 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION
878 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0))
879 ws->value.sig = GDB_SIGNAL_FPE;
4c064e0d
LM
880 else if (stop_reason
881 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT
882 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP
883 | AMD_DBGAPI_WAVE_STOP_REASON_DEBUG_TRAP
884 | AMD_DBGAPI_WAVE_STOP_REASON_ASSERT_TRAP
885 | AMD_DBGAPI_WAVE_STOP_REASON_TRAP))
886 ws->value.sig = GDB_SIGNAL_TRAP;
abeeff98
LM
887 else
888 ws->value.sig = GDB_SIGNAL_0;
889
890 /* If there are more events in the list, mark the async file so that
891 rocm_target_ops::wait gets called again. */
892 if (target_is_async_p () && !info->wave_stop_events.empty ())
893 async_file_mark ();
894
895 return event_ptid;
896}
897
898bool
899rocm_target_ops::stopped_by_sw_breakpoint ()
900{
901 if (!ptid_is_gpu (inferior_ptid))
902 return beneath ()->supports_stopped_by_sw_breakpoint ()
903 && beneath ()->stopped_by_sw_breakpoint ();
904
905 /* FIXME: we should check that the wave is not single-stepping. */
906
907 struct regcache *regcache = get_thread_regcache (inferior_ptid);
908
909 CORE_ADDR bkpt_pc = regcache_read_pc (regcache)
910 - gdbarch_decr_pc_after_break (regcache->arch ());
911
912 return software_breakpoint_inserted_here_p (regcache->aspace (), bkpt_pc);
913}
914
36f3baab
LM
915void
916rocm_target_ops::close ()
917{
918 /* Unregister from the event loop. */
919 async (0);
920 beneath ()->close ();
921}
922
abeeff98
LM
923void
924rocm_target_ops::mourn_inferior ()
925{
96dd14e9
LM
926 auto *info = get_rocm_inferior_info ();
927 info->has_exited = true;
928
929 if (info->activated)
930 amd_dbgapi_deactivated.notify ();
931 amd_dbgapi_process_detach (info->process_id);
932 info->process_id = AMD_DBGAPI_PROCESS_NONE;
933
934 beneath ()->mourn_inferior ();
935
abeeff98
LM
936 /* FIXME: only unpush on the last activation. */
937 /* Disengage the ROCm target_ops. */
938 unpush_target (&rocm_ops);
96dd14e9 939}
abeeff98 940
96dd14e9
LM
941void
942rocm_target_ops::detach (inferior *inf, int from_tty)
943{
944 auto *info = get_rocm_inferior_info ();
945
946 if (info->activated)
947 amd_dbgapi_deactivated.notify ();
948 amd_dbgapi_process_detach (info->process_id);
949 info->process_id = AMD_DBGAPI_PROCESS_NONE;
950
951 beneath ()->detach (inf, from_tty);
abeeff98
LM
952}
953
954void
955rocm_target_ops::fetch_registers (struct regcache *regcache, int regno)
956{
957 struct gdbarch *gdbarch = regcache->arch ();
958 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
959
960 /* delegate to the host routines when not on the device */
961
962 if (!rocm_is_amdgcn_gdbarch (gdbarch))
963 {
964 beneath ()->fetch_registers (regcache, regno);
965 return;
966 }
967
968 inferior *inf = find_inferior_ptid (regcache->ptid ());
969 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id (inf);
970 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
971
972 gdb_byte raw[AMDGCN_MAX_REGISTER_SIZE];
973
974 amd_dbgapi_status_t status = amd_dbgapi_read_register (
975 process_id, wave_id, tdep->register_ids[regno], 0,
976 TYPE_LENGTH (register_type (gdbarch, regno)), raw);
977
978 if (status == AMD_DBGAPI_STATUS_SUCCESS)
979 {
980 regcache->raw_supply (regno, raw);
981 }
982 else if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_REGISTER_ID)
983 {
984 warning (_ ("Couldn't read register %s (#%d)."),
985 gdbarch_register_name (gdbarch, regno), regno);
986 }
987}
988
989void
990rocm_target_ops::store_registers (struct regcache *regcache, int regno)
991{
992 struct gdbarch *gdbarch = regcache->arch ();
993 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
994 gdb_byte raw[AMDGCN_MAX_REGISTER_SIZE];
995
996 if (!rocm_is_amdgcn_gdbarch (gdbarch))
997 {
998 beneath ()->store_registers (regcache, regno);
999 return;
1000 }
1001
1002 inferior *inf = find_inferior_ptid (regcache->ptid ());
1003 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id (inf);
1004 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ());
1005
1006 regcache->raw_collect (regno, &raw);
1007
1008 amd_dbgapi_status_t status = amd_dbgapi_write_register (
1009 process_id, wave_id, tdep->register_ids[regno], 0,
1010 TYPE_LENGTH (register_type (gdbarch, regno)), raw);
1011
1012 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1013 {
1014 warning (_ ("Couldn't write register %s (#%d)."),
1015 gdbarch_register_name (gdbarch, regno), regno);
1016 }
1017}
1018
1019/* Fix breakpoints created with an address location while the
1020 architecture was set to the host (could be fixed in core GDB). */
1021
1022static void
1023rocm_target_breakpoint_fixup (struct breakpoint *b)
1024{
1025 if (b->location.get ()
1026 && event_location_type (b->location.get ()) == ADDRESS_LOCATION
1027 && gdbarch_bfd_arch_info (b->loc->gdbarch)->arch == bfd_arch_amdgcn
1028 && gdbarch_bfd_arch_info (b->gdbarch)->arch != bfd_arch_amdgcn)
1029 {
1030 b->gdbarch = b->loc->gdbarch;
1031 }
1032}
1033
1034struct gdbarch *
1035rocm_target_ops::thread_architecture (ptid_t ptid)
1036{
1037 static std::result_of<decltype (&ptid_t::tid) (ptid_t)>::type last_tid = 0;
1038 static struct gdbarch *cached_arch = nullptr;
1039
1040 if (!ptid_is_gpu (ptid))
1041 return beneath ()->thread_architecture (ptid);
1042
1043 /* We can cache the gdbarch for a given wave_id (ptid::tid) because
1044 wave IDs are unique, and aren't reused. */
1045 if (ptid.tid () == last_tid)
1046 return cached_arch;
1047
1048 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
1049 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (ptid);
1050 amd_dbgapi_architecture_id_t architecture_id;
1051
1052 if (amd_dbgapi_wave_get_info (process_id, wave_id,
1053 AMD_DBGAPI_WAVE_INFO_ARCHITECTURE,
1054 sizeof (architecture_id), &architecture_id)
1055 != AMD_DBGAPI_STATUS_SUCCESS)
1056 error (_ ("Couldn't get architecture for wave_%ld"), ptid.tid ());
1057
1058 uint32_t elf_amdgpu_machine;
1059 if (amd_dbgapi_architecture_get_info (
1060 architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE,
1061 sizeof (elf_amdgpu_machine), &elf_amdgpu_machine)
1062 != AMD_DBGAPI_STATUS_SUCCESS)
1063 error (_ ("Couldn't get elf_amdgpu_machine for architecture_%ld"),
1064 architecture_id.handle);
1065
1066 struct gdbarch_info info;
1067 gdbarch_info_init (&info);
1068
1069 info.bfd_arch_info = bfd_lookup_arch (bfd_arch_amdgcn, elf_amdgpu_machine);
1070 info.byte_order = BFD_ENDIAN_LITTLE;
1071 info.osabi = GDB_OSABI_AMDGPU_HSA;
1072
1073 last_tid = ptid.tid ();
1074 if (!(cached_arch = gdbarch_find_by_info (info)))
1075 error (_ ("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine);
1076
1077 return cached_arch;
1078}
1079
1080void
1081rocm_target_ops::update_thread_list ()
1082{
1083 for (inferior *inf : all_inferiors ())
1084 {
9e275233 1085 amd_dbgapi_process_id_t process_id;
abeeff98
LM
1086 amd_dbgapi_wave_id_t *wave_list;
1087 size_t count;
1088
9e275233
LM
1089 process_id = get_amd_dbgapi_process_id (inf);
1090 if (process_id.handle == AMD_DBGAPI_PROCESS_NONE.handle)
1091 {
1092 /* The inferior may not be attached yet. */
1093 continue;
1094 }
1095
abeeff98
LM
1096 amd_dbgapi_changed_t changed;
1097 amd_dbgapi_status_t status;
1098 if ((status
1099 = amd_dbgapi_wave_list (process_id, &count, &wave_list, &changed))
1100 != AMD_DBGAPI_STATUS_SUCCESS)
9e275233 1101 error (_ ("amd_dbgapi_wave_list failed (rc=%d)"), status);
abeeff98
LM
1102
1103 if (changed == AMD_DBGAPI_CHANGED_NO)
1104 continue;
1105
1106 /* Create a set and free the wave list. */
1107 std::set<std::result_of<decltype (&ptid_t::tid) (ptid_t)>::type> threads;
1108 for (size_t i = 0; i < count; ++i)
1109 threads.emplace (wave_list[i].handle);
1110 xfree (wave_list);
1111
1112 /* Then prune the wave_ids that already have a thread_info. */
1113 for (thread_info *tp : inf->non_exited_threads ())
1114 if (ptid_is_gpu (tp->ptid))
1115 threads.erase (tp->ptid.tid ());
1116
1117 /* The wave_ids that are left require a new thread_info. */
1118 for (auto &&tid : threads)
1119 {
1120 ptid_t wave_ptid (inf->pid, 1, tid);
9e275233 1121 /* FIXME: is this really needed?
abeeff98
LM
1122 amd_dbgapi_wave_state_t state;
1123
1124 if (amd_dbgapi_wave_get_info (
1125 process_id, get_amd_dbgapi_wave_id (wave_ptid),
1126 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state), &state)
1127 != AMD_DBGAPI_STATUS_SUCCESS)
9e275233 1128 continue;*/
abeeff98
LM
1129
1130 add_thread_silent (wave_ptid);
1131 set_running (wave_ptid, 1);
1132 set_executing (wave_ptid, 1);
1133 }
1134 }
1135
1136 /* Give the beneath target a chance to do extra processing. */
1137 this->beneath ()->update_thread_list ();
1138}
1139
1140static void
1141rocm_target_solib_loaded (struct so_list *solib)
1142{
1143 /* Notify the amd_dbgapi that a shared library has been loaded. */
1144 for (auto &&value : get_rocm_inferior_info ()->notify_solib_map)
1145 /* TODO: If we want to support file name wildcards, change this code. */
1146 if (::strstr (solib->so_original_name, value.second.compare.c_str ())
1147 && !value.second.is_loaded)
1148 {
1149 value.second.solib = solib;
1150 value.second.is_loaded = true;
1151
1152 amd_dbgapi_report_shared_library (
1153 get_amd_dbgapi_process_id (),
1154 amd_dbgapi_shared_library_id_t{ value.first },
1155 AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED);
96dd14e9
LM
1156
1157 /* The rocm target may not be engaged yet, we need to process the
1158 events now in case there is a runtime event pending. */
1159 rocm_process_event_queue ();
abeeff98
LM
1160 }
1161}
1162
1163static void
1164rocm_target_solib_unloaded (struct so_list *solib)
1165{
1166 /* Notify the amd_dbgapi that a shared library will unload. */
1167 for (auto &&value : get_rocm_inferior_info ()->notify_solib_map)
1168 /* TODO: If we want to support file name wildcards, change this code. */
1169 if (::strstr (solib->so_original_name, value.second.compare.c_str ())
1170 && value.second.is_loaded)
1171 {
1172 struct rocm_inferior_info *info = get_rocm_inferior_info ();
1173
1174 amd_dbgapi_report_shared_library (
1175 info->process_id, amd_dbgapi_shared_library_id_t{ value.first },
1176 AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED);
1177
1178 /* Delete breakpoints that were left inserted in this shared library.
1179 */
1180 for (auto it = info->breakpoint_map.begin ();
1181 it != info->breakpoint_map.end ();)
1182 if (solib_contains_address_p (solib, it->second->loc->address))
1183 {
1184 warning (_ ("breakpoint_%ld is still inserted after "
1185 "shared_library_%ld was unloaded"),
1186 it->first, value.first);
1187 delete_breakpoint (it->second);
1188 it = info->breakpoint_map.erase (it);
1189 }
1190 else
1191 ++it;
1192
1193 value.second.solib = nullptr;
1194 value.second.is_loaded = false;
1195 }
1196}
1197
1198static void
1199rocm_target_inferior_created (struct target_ops *target, int from_tty)
1200{
1201 struct inferior *inf = current_inferior ();
1202 auto *info = get_rocm_inferior_info (inf);
1203 amd_dbgapi_status_t status;
1204
1205 if (!target_can_async_p ())
1206 {
96dd14e9 1207 warning (_ ("ROCgdb requires target-async, GPU debugging is disabled"));
abeeff98
LM
1208 return;
1209 }
1210
1211 gdb_assert (info->wave_stop_events.empty ());
1212
7d43aaec
T
1213 status = amd_dbgapi_process_attach (
1214 reinterpret_cast<amd_dbgapi_client_process_id_t> (inf),
1215 &info->process_id);
abeeff98
LM
1216
1217 if (status == AMD_DBGAPI_STATUS_ERROR_VERSION_MISMATCH)
1218 warning (_ ("The version of the kernel driver does not match the version "
1219 "required by the ROCm debugger library"));
1220
1221 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1222 {
1223 warning (_ ("Could not attach to process %d"), inf->pid);
1224 return;
1225 }
1226
1227 if (amd_dbgapi_process_get_info (info->process_id,
1228 AMD_DBGAPI_PROCESS_INFO_NOTIFIER,
1229 sizeof (info->notifier), &info->notifier)
1230 != AMD_DBGAPI_STATUS_SUCCESS)
1231 {
1232 warning (_ ("Could not retrieve process %d's notifier"), inf->pid);
1233 amd_dbgapi_process_detach (info->process_id);
1234 return;
1235 }
1236
1237 /* We add a file handler for events returned by the debugger api. We'll use
1238 this handler to signal our async handler that events are available. */
1239 add_file_handler (
1240 info->notifier,
1241 [] (int error, gdb_client_data client_data) {
1242 auto info_ = static_cast<struct rocm_inferior_info *> (client_data);
1243 int ret;
1244
1245 /* Drain the notifier pipe. */
1246 do
1247 {
1248 char buf;
1249 ret = read (info_->notifier, &buf, 1);
1250 }
1251 while (ret >= 0 || (ret == -1 && errno == EINTR));
1252
1253 /* Signal our async handler. */
1254 async_file_mark ();
1255 },
1256 info);
1257
1258 /* Attaching to the inferior may have generated runtime events, process
1259 them now. */
1260 rocm_process_event_queue ();
1261}
1262
1263static void
1264rocm_target_inferior_exit (struct inferior *inf)
1265{
1266 auto *info = get_rocm_inferior_info (inf);
abeeff98 1267
b8ff49b7
LM
1268 if (info->notifier != -1)
1269 delete_file_handler (info->notifier);
abeeff98 1270
96dd14e9
LM
1271 if (info->process_id.handle != AMD_DBGAPI_PROCESS_NONE.handle)
1272 amd_dbgapi_process_detach (info->process_id);
abeeff98
LM
1273
1274 /* Delete the breakpoints that are still active. */
1275 for (auto &&value : info->breakpoint_map)
1276 delete_breakpoint (value.second);
1277
1278 rocm_inferior_data.clear (inf);
1279}
1280
1281static cli_style_option warning_style ("rocm_warning", ui_file_style::RED);
1282static cli_style_option info_style ("rocm_info", ui_file_style::GREEN);
1283static cli_style_option verbose_style ("rocm_verbose", ui_file_style::BLUE);
1284
1285static amd_dbgapi_callbacks_t dbgapi_callbacks = {
1286 /* allocate_memory. */
0cf995bc 1287 .allocate_memory = malloc,
abeeff98
LM
1288
1289 /* deallocate_memory. */
0cf995bc 1290 .deallocate_memory = free,
abeeff98
LM
1291
1292 /* get_os_pid. */
1293 .get_os_pid = [] (amd_dbgapi_client_process_id_t client_process_id,
1294 pid_t *pid) -> amd_dbgapi_status_t {
7d43aaec 1295 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
243f18ba
LM
1296 struct rocm_inferior_info *info = get_rocm_inferior_info (inf);
1297
1298 if (info->has_exited)
1299 return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
abeeff98
LM
1300
1301 *pid = inf->pid;
1302 return AMD_DBGAPI_STATUS_SUCCESS;
1303 },
1304
1305 /* enable_notify_shared_library callback. */
1306 .enable_notify_shared_library
1307 = [] (amd_dbgapi_client_process_id_t client_process_id,
1308 const char *library_name, amd_dbgapi_shared_library_id_t library_id,
1309 amd_dbgapi_shared_library_state_t *library_state)
1310 -> amd_dbgapi_status_t {
7d43aaec 1311 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
abeeff98
LM
1312 struct rocm_inferior_info *info = get_rocm_inferior_info (inf);
1313
1314 if (!library_name || !library_state)
1315 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
1316
1317 if (info->notify_solib_map.find (library_id.handle)
1318 != info->notify_solib_map.end ())
1319 {
1320 /* This library id is already registered. */
1321 return AMD_DBGAPI_STATUS_ERROR;
1322 }
1323
1324 /* Check whether the library is already loaded. */
1325 bool is_loaded = false;
1326 struct so_list *solib;
1327 for (solib = inf->pspace->so_list; solib; solib = solib->next)
1328 if (::strstr (solib->so_original_name, library_name))
1329 {
1330 is_loaded = true;
1331 break;
1332 }
1333
1334 /* Check that the library_name is valid. If must not be empty, and
1335 should not have wildcard characters. */
1336 if (*library_name == '\0'
1337 || std::string (library_name).find_first_of ("*?[]")
1338 != std::string::npos)
1339 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
1340
1341 /* Add a new entry in the notify_solib_map. */
1342 if (!info->notify_solib_map
1343 .emplace (std::piecewise_construct,
1344 std::forward_as_tuple (library_id.handle),
1345 std::forward_as_tuple (rocm_notify_shared_library_info{
1346 library_name, solib, is_loaded }))
1347 .second)
1348 return AMD_DBGAPI_STATUS_ERROR;
1349
1350 *library_state = is_loaded ? AMD_DBGAPI_SHARED_LIBRARY_STATE_LOADED
1351 : AMD_DBGAPI_SHARED_LIBRARY_STATE_UNLOADED;
1352
1353 return AMD_DBGAPI_STATUS_SUCCESS;
1354 },
1355
1356 /* disable_notify_shared_library callback. */
1357 .disable_notify_shared_library
1358 = [] (amd_dbgapi_client_process_id_t client_process_id,
1359 amd_dbgapi_shared_library_id_t library_id) -> amd_dbgapi_status_t {
7d43aaec 1360 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
abeeff98
LM
1361 struct rocm_inferior_info *info = get_rocm_inferior_info (inf);
1362
1363 auto it = info->notify_solib_map.find (library_id.handle);
1364 if (it == info->notify_solib_map.end ())
1365 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID;
1366
1367 info->notify_solib_map.erase (it);
1368 return AMD_DBGAPI_STATUS_SUCCESS;
1369 },
1370
1371 /* get_symbol_address callback. */
1372 .get_symbol_address =
1373 [] (amd_dbgapi_client_process_id_t client_process_id,
1374 amd_dbgapi_shared_library_id_t library_id, const char *symbol_name,
1375 amd_dbgapi_global_address_t *address) {
7d43aaec 1376 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
abeeff98
LM
1377 struct rocm_inferior_info *info = get_rocm_inferior_info (inf);
1378
1379 auto it = info->notify_solib_map.find (library_id.handle);
1380 if (it == info->notify_solib_map.end ())
1381 return AMD_DBGAPI_STATUS_ERROR_INVALID_SHARED_LIBRARY_ID;
1382
1383 struct so_list *solib = it->second.solib;
1384 if (!solib)
1385 return AMD_DBGAPI_STATUS_ERROR_LIBRARY_NOT_LOADED;
1386
1387 solib_read_symbols (solib, 0);
1388 gdb_assert (solib->objfile);
1389
1390 struct bound_minimal_symbol msymbol
1391 = lookup_minimal_symbol (symbol_name, NULL, solib->objfile);
1392
1393 if (!msymbol.minsym || BMSYMBOL_VALUE_ADDRESS (msymbol) == 0)
1394 return AMD_DBGAPI_STATUS_ERROR_SYMBOL_NOT_FOUND;
1395
1396 *address = BMSYMBOL_VALUE_ADDRESS (msymbol);
1397 return AMD_DBGAPI_STATUS_SUCCESS;
1398 },
1399
1400 /* set_breakpoint callback. */
1401 .add_breakpoint =
1402 [] (amd_dbgapi_client_process_id_t client_process_id,
1403 amd_dbgapi_shared_library_id_t shared_library_id,
1404 amd_dbgapi_global_address_t address,
1405 amd_dbgapi_breakpoint_id_t breakpoint_id) {
7d43aaec 1406 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
abeeff98
LM
1407 struct rocm_inferior_info *info = get_rocm_inferior_info (inf);
1408
1409 /* Initialize the breakpoint ops lazily since we depend on
1410 bkpt_breakpoint_ops and we can't control the order in which
1411 initializers are called. */
1412 if (rocm_breakpoint_ops.check_status == NULL)
1413 {
1414 rocm_breakpoint_ops = bkpt_breakpoint_ops;
1415 rocm_breakpoint_ops.check_status = rocm_breakpoint_check_status;
9e275233 1416 rocm_breakpoint_ops.re_set = rocm_breakpoint_re_set;
abeeff98
LM
1417 }
1418
1419 auto it = info->breakpoint_map.find (breakpoint_id.handle);
1420 if (it != info->breakpoint_map.end ())
1421 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
1422
1423 /* Create a new breakpoint. */
1424 struct obj_section *section = find_pc_section (address);
1425 if (!section || !section->objfile)
1426 return AMD_DBGAPI_STATUS_ERROR;
1427
1428 event_location_up location
1429 = new_address_location (address, nullptr, 0);
1430 if (!create_breakpoint (
1431 get_objfile_arch (section->objfile), location.get (),
1432 /*cond_string*/ NULL, /*thread*/ -1, /*extra_sring*/ NULL,
1433 /*parse_extra*/ 0, /*tempflag*/ 0, /*bptype*/ bp_breakpoint,
1434 /*ignore_count*/ 0, /*pending_break*/ AUTO_BOOLEAN_FALSE,
1435 /*ops*/ &rocm_breakpoint_ops, /*from_tty*/ 0,
1436 /*enabled*/ 1, /*internal*/ 1, /*flags*/ 0))
1437 return AMD_DBGAPI_STATUS_ERROR;
1438
1439 /* Find our breakpoint in the breakpoint list. */
1440 auto bp_loc = std::make_pair (inf->aspace, address);
1441 auto bp = breakpoint_find_if (
1442 [] (struct breakpoint *b, void *data) {
1443 auto *arg = static_cast<decltype (&bp_loc)> (data);
1444 if (b->ops == &rocm_breakpoint_ops && b->loc
1445 && b->loc->pspace->aspace == arg->first
1446 && b->loc->address == arg->second)
1447 return 1;
1448 return 0;
1449 },
1450 reinterpret_cast<void *> (&bp_loc));
1451
1452 if (!bp)
1453 error (_ ("Could not find breakpoint"));
1454
1455 info->breakpoint_map.emplace (breakpoint_id.handle, bp);
1456 return AMD_DBGAPI_STATUS_SUCCESS;
1457 },
1458
1459 /* remove_breakpoint callback. */
1460 .remove_breakpoint =
1461 [] (amd_dbgapi_client_process_id_t client_process_id,
1462 amd_dbgapi_breakpoint_id_t breakpoint_id) {
7d43aaec 1463 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
abeeff98
LM
1464 struct rocm_inferior_info *info = get_rocm_inferior_info (inf);
1465
1466 auto it = info->breakpoint_map.find (breakpoint_id.handle);
1467 if (it == info->breakpoint_map.end ())
1468 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
1469
1470 delete_breakpoint (it->second);
1471 info->breakpoint_map.erase (it);
1472
1473 return AMD_DBGAPI_STATUS_SUCCESS;
1474 },
1475
1476 /* set_breakpoint_state callback. */
1477 .set_breakpoint_state =
1478 [] (amd_dbgapi_client_process_id_t client_process_id,
1479 amd_dbgapi_breakpoint_id_t breakpoint_id,
1480 amd_dbgapi_breakpoint_state_t breakpoint_state) {
7d43aaec 1481 inferior *inf = reinterpret_cast<inferior *> (client_process_id);
abeeff98
LM
1482 struct rocm_inferior_info *info = get_rocm_inferior_info (inf);
1483
1484 auto it = info->breakpoint_map.find (breakpoint_id.handle);
1485 if (it == info->breakpoint_map.end ())
1486 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID;
1487
1488 if (breakpoint_state == AMD_DBGAPI_BREAKPOINT_STATE_ENABLE)
1489 it->second->enable_state = bp_enabled;
1490 else if (breakpoint_state == AMD_DBGAPI_BREAKPOINT_STATE_DISABLE)
1491 it->second->enable_state = bp_disabled;
1492 else
1493 return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
1494
1495 return AMD_DBGAPI_STATUS_SUCCESS;
1496 },
1497
1498 .log_message
1499 = [] (amd_dbgapi_log_level_t level, const char *message) -> void {
1500 gdb::optional<target_terminal::scoped_restore_terminal_state> tstate;
1501
1502 if (level > get_debug_amd_dbgapi_log_level ())
1503 return;
1504
1505 if (target_supports_terminal_ours ())
1506 {
1507 tstate.emplace ();
1508 target_terminal::ours_for_output ();
1509 }
1510
1511 if (filtered_printing_initialized ())
1512 wrap_here ("");
1513
1514 struct ui_file *out_file
1515 = (level >= AMD_DBGAPI_LOG_LEVEL_INFO) ? gdb_stdlog : gdb_stderr;
1516
1517 switch (level)
1518 {
1519 case AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR:
1520 fputs_unfiltered ("[amd-dbgapi]: ", out_file);
1521 break;
1522 case AMD_DBGAPI_LOG_LEVEL_WARNING:
1523 fputs_styled ("[amd-dbgapi]: ", warning_style.style (), out_file);
1524 break;
1525 case AMD_DBGAPI_LOG_LEVEL_INFO:
1526 fputs_styled ("[amd-dbgapi]: ", info_style.style (), out_file);
1527 break;
1528 case AMD_DBGAPI_LOG_LEVEL_VERBOSE:
1529 fputs_styled ("[amd-dbgapi]: ", verbose_style.style (), out_file);
1530 break;
1531 }
1532
1533 fputs_unfiltered (message, out_file);
1534 fputs_unfiltered ("\n", out_file);
1535 }
1536};
1537
1538/* Implementation of `_wave_id' variable. */
1539
1540static struct value *
1541rocm_wave_id_make_value (struct gdbarch *gdbarch, struct internalvar *var,
1542 void *ignore)
1543{
1544 if (ptid_is_gpu (inferior_ptid))
1545 {
1546 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
1547 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid);
1548 uint32_t group_ids[3], wave_in_group;
1549
1550 if (amd_dbgapi_wave_get_info (process_id, wave_id,
1551 AMD_DBGAPI_WAVE_INFO_WORK_GROUP_COORD,
1552 sizeof (group_ids), &group_ids)
1553 == AMD_DBGAPI_STATUS_SUCCESS
1554 && amd_dbgapi_wave_get_info (
1555 process_id, wave_id,
1556 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORK_GROUP,
1557 sizeof (wave_in_group), &wave_in_group)
1558 == AMD_DBGAPI_STATUS_SUCCESS)
1559 {
1560 std::string wave_id_str
1561 = string_printf ("(%d,%d,%d)/%d", group_ids[2], group_ids[1],
1562 group_ids[0], wave_in_group);
1563
1564 return value_cstring (wave_id_str.data (), wave_id_str.length () + 1,
1565 builtin_type (gdbarch)->builtin_char);
1566 }
1567 }
1568
1569 return allocate_value (builtin_type (gdbarch)->builtin_void);
1570}
1571
1572static const struct internalvar_funcs rocm_wave_id_funcs
1573 = { rocm_wave_id_make_value, NULL, NULL };
1574
1575/* List of set/show debug amd_dbgapi commands. */
1576struct cmd_list_element *set_debug_amd_dbgapi_list;
1577struct cmd_list_element *show_debug_amd_dbgapi_list;
1578
1579static void
1580set_debug_amd_dbgapi (const char *arg, int from_tty)
1581{
1582 help_list (set_debug_amd_dbgapi_list, "set debug amd-dbgapi ",
1583 (enum command_class) - 1, gdb_stdout);
1584}
1585
1586static void
1587show_debug_amd_dbgapi (const char *args, int from_tty)
1588{
1589 cmd_show_list (show_debug_amd_dbgapi_list, from_tty, "");
1590}
1591
1592constexpr char amd_dbgapi_log_level_off[] = "off";
1593constexpr char amd_dbgapi_log_level_error[] = "error";
1594constexpr char amd_dbgapi_log_level_warning[] = "warning";
1595constexpr char amd_dbgapi_log_level_info[] = "info";
1596constexpr char amd_dbgapi_log_level_verbose[] = "verbose";
1597
1598constexpr const char *debug_amd_dbgapi_log_level_enums[]
1599 = { [AMD_DBGAPI_LOG_LEVEL_NONE] = amd_dbgapi_log_level_off,
1600 [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR] = amd_dbgapi_log_level_error,
1601 [AMD_DBGAPI_LOG_LEVEL_WARNING] = amd_dbgapi_log_level_warning,
1602 [AMD_DBGAPI_LOG_LEVEL_INFO] = amd_dbgapi_log_level_info,
1603 [AMD_DBGAPI_LOG_LEVEL_VERBOSE] = amd_dbgapi_log_level_verbose,
1604 nullptr };
1605
1606static const char *debug_amd_dbgapi_log_level = amd_dbgapi_log_level_error;
1607
1608static amd_dbgapi_log_level_t
1609get_debug_amd_dbgapi_log_level ()
1610{
1611 size_t pos;
1612 for (pos = 0; debug_amd_dbgapi_log_level_enums[pos]; ++pos)
1613 if (debug_amd_dbgapi_log_level == debug_amd_dbgapi_log_level_enums[pos])
1614 break;
1615
1616 gdb_assert (debug_amd_dbgapi_log_level_enums[pos]);
1617 return static_cast<amd_dbgapi_log_level_t> (pos);
1618}
1619
1620static void
1621set_debug_amd_dbgapi_log_level (const char *args, int from_tty,
1622 struct cmd_list_element *c)
1623{
1624 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1625}
1626
1627static void
1628show_debug_amd_dbgapi_log_level (struct ui_file *file, int from_tty,
1629 struct cmd_list_element *c,
1630 const char *value)
1631{
1632 fprintf_filtered (file, _ ("The amd-dbgapi log level is %s.\n"), value);
1633}
1634
1635static void
1636info_agents_command (const char *args, int from_tty)
1637{
1638 amd_dbgapi_process_id_t process_id = get_amd_dbgapi_process_id ();
1639 struct ui_out *uiout = current_uiout;
1640 amd_dbgapi_status_t status;
1641
1642 amd_dbgapi_agent_id_t *agent_list;
1643 size_t count = 0;
1644
1645 if (process_id.handle != AMD_DBGAPI_PROCESS_NONE.handle
1646 && (status
1647 = amd_dbgapi_agent_list (process_id, &count, &agent_list, nullptr))
1648 != AMD_DBGAPI_STATUS_SUCCESS)
1649 error (_ ("amd_dbgapi_agent_list failed (rc=%d)"), status);
1650
1651 if (!count && !uiout->is_mi_like_p ())
1652 {
1653 uiout->field_string (NULL,
1654 _ ("No agents are currently active.\n"));
1655 return;
1656 }
1657
1658 /* Calculate the maximum size needed to print the agents names. */
1659 std::vector<std::string> agent_names (count);
1660
1661 size_t max_name_len = 0;
1662 for (size_t i = 0; i < count; ++i)
1663 {
1664 char *agent_name;
1665
1666 if ((status = amd_dbgapi_agent_get_info (
1667 process_id, agent_list[i], AMD_DBGAPI_AGENT_INFO_NAME,
1668 sizeof (agent_name), &agent_name))
1669 != AMD_DBGAPI_STATUS_SUCCESS)
1670 {
1671 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID)
1672 agent_names[i] = "N/A";
1673 else
1674 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status);
1675 }
1676 else
1677 {
1678 agent_names[i] = agent_name;
1679 xfree (agent_name);
1680 }
1681
1682 max_name_len = std::max (max_name_len, agent_names[i].size ());
1683 }
1684
1685 /* Header: */
1686 ui_out_emit_table table_emmitter (uiout, 7, count, "InfoRocmDevicesTable");
1687
1688 uiout->table_header (2, ui_left, "agent_id", "Id");
1689 uiout->table_header (8, ui_left, "location_id", "PCI Slot");
1690 uiout->table_header (std::max (11ul, max_name_len), ui_left, "name",
1691 "Device Name");
1692 uiout->table_header (14, ui_left, "num_se", "Shader Engines");
1693 uiout->table_header (13, ui_left, "num_cu", "Compute Units");
1694 uiout->table_header (7, ui_left, "simd", "SIMD/CU");
1695 uiout->table_header (15, ui_left, "waves", "Wavefronts/SIMD");
1696 uiout->table_body ();
1697
1698 /* Rows: */
1699 for (size_t i = 0; i < count; ++i)
1700 {
1701 ui_out_emit_tuple tuple_emitter (uiout, "InfoRocmDevicesRow");
1702
1703 /* agent */
1704 uiout->field_signed ("agent_id", agent_list[i].handle);
1705
1706 /* location */
1707 uint32_t location_id;
1708 if ((status = amd_dbgapi_agent_get_info (
1709 process_id, agent_list[i], AMD_DBGAPI_AGENT_INFO_PCIE_SLOT,
1710 sizeof (location_id), &location_id))
1711 != AMD_DBGAPI_STATUS_SUCCESS)
1712 {
1713 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID)
1714 uiout->field_string ("location_id", "N/A");
1715 else
1716 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status);
1717 }
1718 else
1719 uiout->field_string (
1720 "location_id",
1721 string_printf ("%02x:%02x.%d", (location_id >> 8) & 0xFF,
1722 (location_id >> 3) & 0x1F, location_id & 0x7));
1723
1724 /* name */
1725 uiout->field_string ("name", agent_names[i]);
1726
1727 /* num_se, num_cu, simd, waves */
1728
1729#define UIOUT_FIELD_INT(name, query) \
1730 uint32_t name; \
1731 if ((status = amd_dbgapi_agent_get_info (process_id, agent_list[i], query, \
1732 sizeof (name), &name)) \
1733 != AMD_DBGAPI_STATUS_SUCCESS) \
1734 { \
1735 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_AGENT_ID) \
1736 uiout->field_string (#name, "N/A"); \
1737 else \
1738 error (_ ("amd_dbgapi_agent_get_info failed (rc=%d"), status); \
1739 } \
1740 else \
1741 uiout->field_signed (#name, name);
1742
1743 UIOUT_FIELD_INT (num_se, AMD_DBGAPI_AGENT_INFO_SHADER_ENGINE_COUNT);
1744 UIOUT_FIELD_INT (num_cu, AMD_DBGAPI_AGENT_INFO_COMPUTE_UNIT_COUNT);
1745 UIOUT_FIELD_INT (simd, AMD_DBGAPI_AGENT_INFO_NUM_SIMD_PER_COMPUTE_UNIT);
1746 UIOUT_FIELD_INT (waves, AMD_DBGAPI_AGENT_INFO_MAX_WAVES_PER_SIMD);
1747
1748#undef UIOUT_FIELD_INT
1749
1750 uiout->text ("\n");
1751 }
1752
1753 xfree (agent_list);
1754 gdb_flush (gdb_stdout);
1755}
1756
1757/* -Wmissing-prototypes */
1758extern initialize_file_ftype _initialize_rocm_tdep;
1759
1760void
1761_initialize_rocm_tdep (void)
1762{
48e5c3f7
LM
1763 /* Make sure the loaded debugger library version is greater than or equal to
1764 the one used to build ROCgdb. */
1765 uint32_t major, minor, patch;
1766 amd_dbgapi_get_version (&major, &minor, &patch);
1767 if (major != AMD_DBGAPI_VERSION_MAJOR || minor < AMD_DBGAPI_VERSION_MINOR)
1768 error (
1769 _ ("amd-dbgapi library version mismatch, got %d.%d.%d, need %d.%d+"),
1770 major, minor, patch, AMD_DBGAPI_VERSION_MAJOR,
1771 AMD_DBGAPI_VERSION_MINOR);
1772
abeeff98 1773 /* Initialize the ROCm Debug API. */
48e5c3f7
LM
1774 amd_dbgapi_status_t status = amd_dbgapi_initialize (&dbgapi_callbacks);
1775 if (status != AMD_DBGAPI_STATUS_SUCCESS)
1776 error (_ ("amd-dbgapi failed to initialize (rc=%d)"), status);
abeeff98
LM
1777
1778 /* Set the initial log level. */
1779 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_log_level ());
1780
1781 /* Install observers. */
1782 gdb::observers::breakpoint_created.attach (rocm_target_breakpoint_fixup);
1783 gdb::observers::solib_loaded.attach (rocm_target_solib_loaded);
1784 gdb::observers::solib_unloaded.attach (rocm_target_solib_unloaded);
1785 gdb::observers::inferior_created.attach (rocm_target_inferior_created);
1786 gdb::observers::inferior_exit.attach (rocm_target_inferior_exit);
1787
1788 amd_dbgapi_activated.attach (rocm_target_dbgapi_activated);
1789 amd_dbgapi_deactivated.attach (rocm_target_dbgapi_deactivated);
1790
1791 create_internalvar_type_lazy ("_wave_id", &rocm_wave_id_funcs, NULL);
1792
1793 add_prefix_cmd (
1794 "amd-dbgapi", no_class, set_debug_amd_dbgapi,
1795 _ ("Generic command for setting amd-dbgapi debugging flags"),
1796 &set_debug_amd_dbgapi_list, "set debug amd-dbgapi ", 0, &setdebuglist);
1797
1798 add_prefix_cmd (
1799 "amd-dbgapi", no_class, show_debug_amd_dbgapi,
1800 _ ("Generic command for showing amd-dbgapi debugging flags"),
1801 &show_debug_amd_dbgapi_list, "show debug amd-dbgapi ", 0,
1802 &showdebuglist);
1803
1804 add_setshow_enum_cmd (
1805 "log-level", class_maintenance, debug_amd_dbgapi_log_level_enums,
1806 &debug_amd_dbgapi_log_level, _ ("Set the amd-dbgapi log level."),
1807 _ ("Show the amd-dbgapi log level."),
1808 _ ("off == no logging is enabled\n"
1809 "error == fatal errors are reported\n"
1810 "warning == fatal errors and warnings are reported\n"
1811 "info == fatal errors, warnings, and info messages are reported\n"
1812 "verbose == all messages are reported"),
1813 set_debug_amd_dbgapi_log_level, show_debug_amd_dbgapi_log_level,
1814 &set_debug_amd_dbgapi_list, &show_debug_amd_dbgapi_list);
1815
1816 add_cmd ("agents", class_info, info_agents_command,
1817 _ ("Info about currently active agents."), &infolist);
1818}
This page took 0.091841 seconds and 4 git commands to generate.