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