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