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