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