1/* Target used to communicate with the AMD Debugger API. 2 3 Copyright (C) 2019-2024 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 21#include "amd-dbgapi-target.h" 22#include "amdgpu-tdep.h" 23#include "async-event.h" 24#include "cli/cli-cmds.h" 25#include "cli/cli-decode.h" 26#include "cli/cli-style.h" 27#include "inf-loop.h" 28#include "inferior.h" 29#include "objfiles.h" 30#include "observable.h" 31#include "registry.h" 32#include "solib.h" 33#include "target.h" 34 35/* When true, print debug messages relating to the amd-dbgapi target. */ 36 37static bool debug_amd_dbgapi = false; 38 39/* Make a copy of S styled in green. */ 40 41static std::string 42make_green (const char *s) 43{ 44 cli_style_option style (nullptr, ui_file_style::GREEN); 45 string_file sf (true); 46 gdb_printf (&sf, "%ps", styled_string (style.style(), s)); 47 return sf.release (); 48} 49 50/* Debug module names. "amd-dbgapi" is for the target debug messages (this 51 file), whereas "amd-dbgapi-lib" is for logging messages output by the 52 amd-dbgapi library. */ 53 54static const char *amd_dbgapi_debug_module_unstyled = "amd-dbgapi"; 55static const char *amd_dbgapi_lib_debug_module_unstyled 56 = "amd-dbgapi-lib"; 57 58/* Styled variants of the above. */ 59 60static const std::string amd_dbgapi_debug_module_styled 61 = make_green (amd_dbgapi_debug_module_unstyled); 62static const std::string amd_dbgapi_lib_debug_module_styled 63 = make_green (amd_dbgapi_lib_debug_module_unstyled); 64 65/* Return the styled or unstyled variant of the amd-dbgapi module name, 66 depending on whether gdb_stdlog can emit colors. */ 67 68static const char * 69amd_dbgapi_debug_module () 70{ 71 if (gdb_stdlog->can_emit_style_escape ()) 72 return amd_dbgapi_debug_module_styled.c_str (); 73 else 74 return amd_dbgapi_debug_module_unstyled; 75} 76 77/* Same as the above, but for the amd-dbgapi-lib module name. */ 78 79static const char * 80amd_dbgapi_lib_debug_module () 81{ 82 if (gdb_stdlog->can_emit_style_escape ()) 83 return amd_dbgapi_lib_debug_module_styled.c_str (); 84 else 85 return amd_dbgapi_lib_debug_module_unstyled; 86} 87 88/* Print an amd-dbgapi debug statement. */ 89 90#define amd_dbgapi_debug_printf(fmt, ...) \ 91 debug_prefixed_printf_cond (debug_amd_dbgapi, \ 92 amd_dbgapi_debug_module (), \ 93 fmt, ##__VA_ARGS__) 94 95/* Print amd-dbgapi start/end debug statements. */ 96 97#define AMD_DBGAPI_SCOPED_DEBUG_START_END(fmt, ...) \ 98 scoped_debug_start_end (debug_amd_dbgapi, amd_dbgapi_debug_module (), \ 99 fmt, ##__VA_ARGS__) 100 101/* inferior_created observer token. */ 102 103static gdb::observers::token amd_dbgapi_target_inferior_created_observer_token; 104 105const gdb::observers::token & 106get_amd_dbgapi_target_inferior_created_observer_token () 107{ 108 return amd_dbgapi_target_inferior_created_observer_token; 109} 110 111/* A type holding coordinates, etc. info for a given wave. */ 112 113struct wave_coordinates 114{ 115 /* The wave. Set by the ctor. */ 116 amd_dbgapi_wave_id_t wave_id; 117 118 /* All these fields are initialized here to a value that is printed 119 as "?". */ 120 amd_dbgapi_dispatch_id_t dispatch_id = AMD_DBGAPI_DISPATCH_NONE; 121 amd_dbgapi_queue_id_t queue_id = AMD_DBGAPI_QUEUE_NONE; 122 amd_dbgapi_agent_id_t agent_id = AMD_DBGAPI_AGENT_NONE; 123 uint32_t group_ids[3] {UINT32_MAX, UINT32_MAX, UINT32_MAX}; 124 uint32_t wave_in_group = UINT32_MAX; 125 126 explicit wave_coordinates (amd_dbgapi_wave_id_t wave_id) 127 : wave_id (wave_id) 128 {} 129 130 /* Return the target ID string for the wave this wave_coordinates is 131 for. */ 132 std::string to_string () const; 133 134 /* Pull out coordinates info from the amd-dbgapi library. */ 135 void fetch (); 136}; 137 138/* A type holding info about a given wave. */ 139 140struct wave_info 141{ 142 /* We cache the coordinates info because we need it after a wave 143 exits. The wave's ID is here. */ 144 wave_coordinates coords; 145 146 /* The last resume_mode passed to amd_dbgapi_wave_resume for this 147 wave. We track this because we are guaranteed to see a 148 WAVE_COMMAND_TERMINATED event if a stepping wave terminates, and 149 we need to know to not delete such a wave until we process that 150 event. */ 151 amd_dbgapi_resume_mode_t last_resume_mode = AMD_DBGAPI_RESUME_MODE_NORMAL; 152 153 /* Whether we've called amd_dbgapi_wave_stop for this wave and are 154 waiting for its stop event. Similarly, we track this because 155 we're guaranteed to get a WAVE_COMMAND_TERMINATED event if the 156 wave terminates while being stopped. */ 157 bool stopping = false; 158 159 explicit wave_info (amd_dbgapi_wave_id_t wave_id) 160 : coords (wave_id) 161 { 162 coords.fetch (); 163 } 164}; 165 166/* Big enough to hold the size of the largest register in bytes. */ 167#define AMDGPU_MAX_REGISTER_SIZE 256 168 169/* amd-dbgapi-specific inferior data. */ 170 171struct amd_dbgapi_inferior_info 172{ 173 explicit amd_dbgapi_inferior_info (inferior *inf, 174 bool precise_memory_requested = false) 175 : inf (inf) 176 { 177 precise_memory.requested = precise_memory_requested; 178 } 179 180 /* Backlink to inferior. */ 181 inferior *inf; 182 183 /* The amd_dbgapi_process_id for this inferior. */ 184 amd_dbgapi_process_id_t process_id = AMD_DBGAPI_PROCESS_NONE; 185 186 /* The amd_dbgapi_notifier_t for this inferior. */ 187 amd_dbgapi_notifier_t notifier = -1; 188 189 /* The status of the inferior's runtime support. */ 190 amd_dbgapi_runtime_state_t runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED; 191 192 /* This value mirrors the current "forward progress needed" value for this 193 process in amd-dbgapi. It is used to avoid unnecessary calls to 194 amd_dbgapi_process_set_progress, to reduce the noise in the logs. 195 196 Initialized to true, since that's the default in amd-dbgapi too. */ 197 bool forward_progress_required = true; 198 199 struct 200 { 201 /* Whether precise memory reporting is requested. */ 202 bool requested; 203 204 /* Whether precise memory was requested and successfully enabled by 205 dbgapi (it may not be available for the current hardware, for 206 instance). */ 207 bool enabled = false; 208 } precise_memory; 209 210 std::unordered_map<decltype (amd_dbgapi_breakpoint_id_t::handle), 211 struct breakpoint *> 212 breakpoint_map; 213 214 /* List of pending events the amd-dbgapi target retrieved from the dbgapi. */ 215 std::list<std::pair<ptid_t, target_waitstatus>> wave_events; 216 217 /* Map of wave ID to wave_info. We cache wave_info objects because 218 we need to access the info after the wave is gone, in the thread 219 exit nofication. E.g.: 220 [AMDGPU Wave 1:4:1:1 (0,0,0)/0 exited] 221 222 wave_info objects are added when we first see the wave, and 223 removed from a thread_deleted observer. */ 224 std::unordered_map<decltype (amd_dbgapi_wave_id_t::handle), wave_info> 225 wave_info_map; 226}; 227 228static amd_dbgapi_event_id_t process_event_queue 229 (amd_dbgapi_process_id_t process_id, 230 amd_dbgapi_event_kind_t until_event_kind = AMD_DBGAPI_EVENT_KIND_NONE); 231 232static const target_info amd_dbgapi_target_info = { 233 "amd-dbgapi", 234 N_("AMD Debugger API"), 235 N_("GPU debugging using the AMD Debugger API") 236}; 237 238static amd_dbgapi_log_level_t get_debug_amd_dbgapi_lib_log_level (); 239 240struct amd_dbgapi_target final : public target_ops 241{ 242 const target_info & 243 info () const override 244 { 245 return amd_dbgapi_target_info; 246 } 247 strata 248 stratum () const override 249 { 250 return arch_stratum; 251 } 252 253 void close () override; 254 void mourn_inferior () override; 255 void detach (inferior *inf, int from_tty) override; 256 257 void async (bool enable) override; 258 259 bool has_pending_events () override; 260 ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override; 261 void resume (ptid_t, int, enum gdb_signal) override; 262 void commit_resumed () override; 263 void stop (ptid_t ptid) override; 264 265 void fetch_registers (struct regcache *, int) override; 266 void store_registers (struct regcache *, int) override; 267 268 void update_thread_list () override; 269 270 struct gdbarch *thread_architecture (ptid_t) override; 271 272 void thread_events (int enable) override; 273 274 std::string pid_to_str (ptid_t ptid) override; 275 276 const char *thread_name (thread_info *tp) override; 277 278 const char *extra_thread_info (thread_info *tp) override; 279 280 bool thread_alive (ptid_t ptid) override; 281 282 enum target_xfer_status xfer_partial (enum target_object object, 283 const char *annex, gdb_byte *readbuf, 284 const gdb_byte *writebuf, 285 ULONGEST offset, ULONGEST len, 286 ULONGEST *xfered_len) override; 287 288 bool stopped_by_watchpoint () override; 289 290 bool stopped_by_sw_breakpoint () override; 291 bool stopped_by_hw_breakpoint () override; 292 293private: 294 /* True if we must report thread events. */ 295 bool m_report_thread_events = false; 296 297 /* Cache for the last value returned by thread_architecture. */ 298 gdbarch *m_cached_arch = nullptr; 299 ptid_t::tid_type m_cached_arch_tid = 0; 300}; 301 302static struct amd_dbgapi_target the_amd_dbgapi_target; 303 304/* Per-inferior data key. */ 305 306static const registry<inferior>::key<amd_dbgapi_inferior_info> 307 amd_dbgapi_inferior_data; 308 309/* Fetch the amd_dbgapi_inferior_info data for the given inferior. */ 310 311static struct amd_dbgapi_inferior_info * 312get_amd_dbgapi_inferior_info (struct inferior *inferior) 313{ 314 amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (inferior); 315 316 if (info == nullptr) 317 info = amd_dbgapi_inferior_data.emplace (inferior, inferior); 318 319 return info; 320} 321 322/* The async event handler registered with the event loop, indicating that we 323 might have events to report to the core and that we'd like our wait method 324 to be called. 325 326 This is nullptr when async is disabled and non-nullptr when async is 327 enabled. 328 329 It is marked when a notifier fd tells us there's an event available. The 330 callback triggers handle_inferior_event in order to pull the event from 331 amd-dbgapi and handle it. */ 332 333static async_event_handler *amd_dbgapi_async_event_handler = nullptr; 334 335std::string 336wave_coordinates::to_string () const 337{ 338 std::string str = "AMDGPU Wave"; 339 340 str += (agent_id != AMD_DBGAPI_AGENT_NONE 341 ? string_printf (" %ld", agent_id.handle) 342 : " ?"); 343 344 str += (queue_id != AMD_DBGAPI_QUEUE_NONE 345 ? string_printf (":%ld", queue_id.handle) 346 : ":?"); 347 348 str += (dispatch_id != AMD_DBGAPI_DISPATCH_NONE 349 ? string_printf (":%ld", dispatch_id.handle) 350 : ":?"); 351 352 str += string_printf (":%ld", wave_id.handle); 353 354 str += (group_ids[0] != UINT32_MAX 355 ? string_printf (" (%d,%d,%d)", group_ids[0], group_ids[1], 356 group_ids[2]) 357 : " (?,?,?)"); 358 359 str += (wave_in_group != UINT32_MAX 360 ? string_printf ("/%d", wave_in_group) 361 : "/?"); 362 363 return str; 364} 365 366/* Read in wave_info for WAVE_ID. */ 367 368void 369wave_coordinates::fetch () 370{ 371 /* Any field that fails to be read is left with its in-class 372 initialized value, which is printed as "?". */ 373 374 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_AGENT, 375 sizeof (agent_id), &agent_id); 376 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_QUEUE, 377 sizeof (queue_id), &queue_id); 378 amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_DISPATCH, 379 sizeof (dispatch_id), &dispatch_id); 380 381 amd_dbgapi_wave_get_info (wave_id, 382 AMD_DBGAPI_WAVE_INFO_WORKGROUP_COORD, 383 sizeof (group_ids), &group_ids); 384 385 amd_dbgapi_wave_get_info (wave_id, 386 AMD_DBGAPI_WAVE_INFO_WAVE_NUMBER_IN_WORKGROUP, 387 sizeof (wave_in_group), &wave_in_group); 388} 389 390/* Get the wave_info object for TP, from the wave_info map. It is 391 assumed that the wave is in the map. */ 392 393static wave_info & 394get_thread_wave_info (thread_info *tp) 395{ 396 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (tp->inf); 397 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (tp->ptid); 398 399 auto it = info->wave_info_map.find (wave_id.handle); 400 gdb_assert (it != info->wave_info_map.end ()); 401 402 return it->second; 403} 404 405/* Clear our async event handler. */ 406 407static void 408async_event_handler_clear () 409{ 410 gdb_assert (amd_dbgapi_async_event_handler != nullptr); 411 clear_async_event_handler (amd_dbgapi_async_event_handler); 412} 413 414/* Mark our async event handler. */ 415 416static void 417async_event_handler_mark () 418{ 419 gdb_assert (amd_dbgapi_async_event_handler != nullptr); 420 mark_async_event_handler (amd_dbgapi_async_event_handler); 421} 422 423/* Set forward progress requirement to REQUIRE for all processes of PROC_TARGET 424 matching PTID. */ 425 426static void 427require_forward_progress (ptid_t ptid, process_stratum_target *proc_target, 428 bool require) 429{ 430 for (inferior *inf : all_inferiors (proc_target)) 431 { 432 if (ptid != minus_one_ptid && inf->pid != ptid.pid ()) 433 continue; 434 435 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 436 437 if (info->process_id == AMD_DBGAPI_PROCESS_NONE) 438 continue; 439 440 /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */ 441 if (info->forward_progress_required == require) 442 continue; 443 444 amd_dbgapi_status_t status 445 = amd_dbgapi_process_set_progress 446 (info->process_id, (require 447 ? AMD_DBGAPI_PROGRESS_NORMAL 448 : AMD_DBGAPI_PROGRESS_NO_FORWARD)); 449 gdb_assert (status == AMD_DBGAPI_STATUS_SUCCESS); 450 451 info->forward_progress_required = require; 452 453 /* If ptid targets a single inferior and we have found it, no need to 454 continue. */ 455 if (ptid != minus_one_ptid) 456 break; 457 } 458} 459 460/* See amd-dbgapi-target.h. */ 461 462amd_dbgapi_process_id_t 463get_amd_dbgapi_process_id (inferior *inf) 464{ 465 return get_amd_dbgapi_inferior_info (inf)->process_id; 466} 467 468/* A breakpoint dbgapi wants us to insert, to handle shared library 469 loading/unloading. */ 470 471struct amd_dbgapi_target_breakpoint : public code_breakpoint 472{ 473 amd_dbgapi_target_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) 474 : code_breakpoint (gdbarch, bp_breakpoint) 475 { 476 symtab_and_line sal; 477 sal.pc = address; 478 sal.section = find_pc_overlay (sal.pc); 479 sal.pspace = current_program_space; 480 add_location (sal); 481 482 pspace = current_program_space; 483 disposition = disp_donttouch; 484 } 485 486 void re_set () override; 487 void check_status (struct bpstat *bs) override; 488}; 489 490void 491amd_dbgapi_target_breakpoint::re_set () 492{ 493 /* Nothing. */ 494} 495 496void 497amd_dbgapi_target_breakpoint::check_status (struct bpstat *bs) 498{ 499 struct inferior *inf = current_inferior (); 500 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 501 amd_dbgapi_status_t status; 502 503 bs->stop = 0; 504 bs->print_it = print_it_noop; 505 506 /* Find the address the breakpoint is set at. */ 507 auto match_breakpoint 508 = [bs] (const decltype (info->breakpoint_map)::value_type &value) 509 { return value.second == bs->breakpoint_at; }; 510 auto it 511 = std::find_if (info->breakpoint_map.begin (), info->breakpoint_map.end (), 512 match_breakpoint); 513 514 if (it == info->breakpoint_map.end ()) 515 error (_("Could not find breakpoint_id for breakpoint at %s"), 516 paddress (inf->arch (), bs->bp_location_at->address)); 517 518 amd_dbgapi_breakpoint_id_t breakpoint_id { it->first }; 519 amd_dbgapi_breakpoint_action_t action; 520 521 status = amd_dbgapi_report_breakpoint_hit 522 (breakpoint_id, 523 reinterpret_cast<amd_dbgapi_client_thread_id_t> (inferior_thread ()), 524 &action); 525 526 if (status != AMD_DBGAPI_STATUS_SUCCESS) 527 error (_("amd_dbgapi_report_breakpoint_hit failed for breakpoint %ld " 528 "at %s (%s)"), 529 breakpoint_id.handle, paddress (inf->arch (), bs->bp_location_at->address), 530 get_status_string (status)); 531 532 if (action == AMD_DBGAPI_BREAKPOINT_ACTION_RESUME) 533 return; 534 535 /* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until 536 a breakpoint resume event for this breakpoint_id is seen. */ 537 amd_dbgapi_event_id_t resume_event_id 538 = process_event_queue (info->process_id, 539 AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME); 540 541 /* We should always get a breakpoint_resume event after processing all 542 events generated by reporting the breakpoint hit. */ 543 gdb_assert (resume_event_id != AMD_DBGAPI_EVENT_NONE); 544 545 amd_dbgapi_breakpoint_id_t resume_breakpoint_id; 546 status = amd_dbgapi_event_get_info (resume_event_id, 547 AMD_DBGAPI_EVENT_INFO_BREAKPOINT, 548 sizeof (resume_breakpoint_id), 549 &resume_breakpoint_id); 550 551 if (status != AMD_DBGAPI_STATUS_SUCCESS) 552 error (_("amd_dbgapi_event_get_info failed (%s)"), get_status_string (status)); 553 554 /* The debugger API guarantees that [breakpoint_hit...resume_breakpoint] 555 sequences cannot interleave, so this breakpoint resume event must be 556 for our breakpoint_id. */ 557 if (resume_breakpoint_id != breakpoint_id) 558 error (_("breakpoint resume event is not for this breakpoint. " 559 "Expected breakpoint_%ld, got breakpoint_%ld"), 560 breakpoint_id.handle, resume_breakpoint_id.handle); 561 562 amd_dbgapi_event_processed (resume_event_id); 563} 564 565bool 566amd_dbgapi_target::thread_alive (ptid_t ptid) 567{ 568 if (!ptid_is_gpu (ptid)) 569 return beneath ()->thread_alive (ptid); 570 571 /* Check that the wave_id is valid. */ 572 573 amd_dbgapi_wave_state_t state; 574 amd_dbgapi_status_t status 575 = amd_dbgapi_wave_get_info (get_amd_dbgapi_wave_id (ptid), 576 AMD_DBGAPI_WAVE_INFO_STATE, sizeof (state), 577 &state); 578 return status == AMD_DBGAPI_STATUS_SUCCESS; 579} 580 581const char * 582amd_dbgapi_target::thread_name (thread_info *tp) 583{ 584 if (!ptid_is_gpu (tp->ptid)) 585 return beneath ()->thread_name (tp); 586 587 return nullptr; 588} 589 590std::string 591amd_dbgapi_target::pid_to_str (ptid_t ptid) 592{ 593 if (!ptid_is_gpu (ptid)) 594 return beneath ()->pid_to_str (ptid); 595 596 process_stratum_target *proc_target = current_inferior ()->process_target (); 597 inferior *inf = find_inferior_pid (proc_target, ptid.pid ()); 598 gdb_assert (inf != nullptr); 599 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 600 601 auto wave_id = get_amd_dbgapi_wave_id (ptid); 602 603 auto it = info->wave_info_map.find (wave_id.handle); 604 if (it != info->wave_info_map.end ()) 605 return it->second.coords.to_string (); 606 607 /* A wave we don't know about. Shouldn't usually happen, but 608 asserting and bringing down the session is a bit too harsh. Just 609 print all unknown info as "?"s. */ 610 return wave_coordinates (wave_id).to_string (); 611} 612 613const char * 614amd_dbgapi_target::extra_thread_info (thread_info *tp) 615{ 616 if (!ptid_is_gpu (tp->ptid)) 617 beneath ()->extra_thread_info (tp); 618 619 return nullptr; 620} 621 622target_xfer_status 623amd_dbgapi_target::xfer_partial (enum target_object object, const char *annex, 624 gdb_byte *readbuf, const gdb_byte *writebuf, 625 ULONGEST offset, ULONGEST requested_len, 626 ULONGEST *xfered_len) 627{ 628 std::optional<scoped_restore_current_thread> maybe_restore_thread; 629 630 if (!ptid_is_gpu (inferior_ptid)) 631 return beneath ()->xfer_partial (object, annex, readbuf, writebuf, offset, 632 requested_len, xfered_len); 633 634 gdb_assert (requested_len > 0); 635 gdb_assert (xfered_len != nullptr); 636 637 if (object != TARGET_OBJECT_MEMORY) 638 return TARGET_XFER_E_IO; 639 640 amd_dbgapi_process_id_t process_id 641 = get_amd_dbgapi_process_id (current_inferior ()); 642 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid); 643 644 size_t len = requested_len; 645 amd_dbgapi_status_t status; 646 647 if (readbuf != nullptr) 648 status = amd_dbgapi_read_memory (process_id, wave_id, 0, 649 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL, 650 offset, &len, readbuf); 651 else 652 status = amd_dbgapi_write_memory (process_id, wave_id, 0, 653 AMD_DBGAPI_ADDRESS_SPACE_GLOBAL, 654 offset, &len, writebuf); 655 656 if (status != AMD_DBGAPI_STATUS_SUCCESS) 657 return TARGET_XFER_E_IO; 658 659 *xfered_len = len; 660 return TARGET_XFER_OK; 661} 662 663bool 664amd_dbgapi_target::stopped_by_watchpoint () 665{ 666 if (!ptid_is_gpu (inferior_ptid)) 667 return beneath ()->stopped_by_watchpoint (); 668 669 return false; 670} 671 672void 673amd_dbgapi_target::resume (ptid_t scope_ptid, int step, enum gdb_signal signo) 674{ 675 amd_dbgapi_debug_printf ("scope_ptid = %s", scope_ptid.to_string ().c_str ()); 676 677 /* The amd_dbgapi_exceptions_t matching SIGNO will only be used if the 678 thread which is the target of the signal SIGNO is a GPU thread. If so, 679 make sure that there is a corresponding amd_dbgapi_exceptions_t for SIGNO 680 before we try to resume any thread. */ 681 amd_dbgapi_exceptions_t exception = AMD_DBGAPI_EXCEPTION_NONE; 682 if (ptid_is_gpu (inferior_ptid)) 683 { 684 switch (signo) 685 { 686 case GDB_SIGNAL_BUS: 687 exception = AMD_DBGAPI_EXCEPTION_WAVE_APERTURE_VIOLATION; 688 break; 689 case GDB_SIGNAL_SEGV: 690 exception = AMD_DBGAPI_EXCEPTION_WAVE_MEMORY_VIOLATION; 691 break; 692 case GDB_SIGNAL_ILL: 693 exception = AMD_DBGAPI_EXCEPTION_WAVE_ILLEGAL_INSTRUCTION; 694 break; 695 case GDB_SIGNAL_FPE: 696 exception = AMD_DBGAPI_EXCEPTION_WAVE_MATH_ERROR; 697 break; 698 case GDB_SIGNAL_ABRT: 699 exception = AMD_DBGAPI_EXCEPTION_WAVE_ABORT; 700 break; 701 case GDB_SIGNAL_TRAP: 702 exception = AMD_DBGAPI_EXCEPTION_WAVE_TRAP; 703 break; 704 case GDB_SIGNAL_0: 705 exception = AMD_DBGAPI_EXCEPTION_NONE; 706 break; 707 default: 708 error (_("Resuming with signal %s is not supported by this agent."), 709 gdb_signal_to_name (signo)); 710 } 711 } 712 713 if (!ptid_is_gpu (inferior_ptid) || scope_ptid != inferior_ptid) 714 { 715 beneath ()->resume (scope_ptid, step, signo); 716 717 /* If the request is for a single thread, we are done. */ 718 if (scope_ptid == inferior_ptid) 719 return; 720 } 721 722 process_stratum_target *proc_target = current_inferior ()->process_target (); 723 724 /* Disable forward progress requirement. */ 725 require_forward_progress (scope_ptid, proc_target, false); 726 727 for (thread_info *thread : all_non_exited_threads (proc_target, scope_ptid)) 728 { 729 if (!ptid_is_gpu (thread->ptid)) 730 continue; 731 732 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid); 733 amd_dbgapi_status_t status; 734 735 wave_info &wi = get_thread_wave_info (thread); 736 amd_dbgapi_resume_mode_t &resume_mode = wi.last_resume_mode; 737 amd_dbgapi_exceptions_t wave_exception; 738 if (thread->ptid == inferior_ptid) 739 { 740 resume_mode = (step 741 ? AMD_DBGAPI_RESUME_MODE_SINGLE_STEP 742 : AMD_DBGAPI_RESUME_MODE_NORMAL); 743 wave_exception = exception; 744 } 745 else 746 { 747 resume_mode = AMD_DBGAPI_RESUME_MODE_NORMAL; 748 wave_exception = AMD_DBGAPI_EXCEPTION_NONE; 749 } 750 751 status = amd_dbgapi_wave_resume (wave_id, resume_mode, wave_exception); 752 if (status != AMD_DBGAPI_STATUS_SUCCESS 753 /* Ignore the error that wave is no longer valid as that could 754 indicate that the process has exited. GDB treats resuming a 755 thread that no longer exists as being successful. */ 756 && status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID) 757 error (_("wave_resume for wave_%ld failed (%s)"), wave_id.handle, 758 get_status_string (status)); 759 760 wi.stopping = false; 761 } 762} 763 764void 765amd_dbgapi_target::commit_resumed () 766{ 767 amd_dbgapi_debug_printf ("called"); 768 769 beneath ()->commit_resumed (); 770 771 process_stratum_target *proc_target = current_inferior ()->process_target (); 772 require_forward_progress (minus_one_ptid, proc_target, true); 773} 774 775/* Return a string version of RESUME_MODE, for debug log purposes. */ 776 777static const char * 778resume_mode_to_string (amd_dbgapi_resume_mode_t resume_mode) 779{ 780 switch (resume_mode) 781 { 782 case AMD_DBGAPI_RESUME_MODE_NORMAL: 783 return "normal"; 784 case AMD_DBGAPI_RESUME_MODE_SINGLE_STEP: 785 return "step"; 786 } 787 gdb_assert_not_reached ("invalid amd_dbgapi_resume_mode_t"); 788} 789 790void 791amd_dbgapi_target::stop (ptid_t ptid) 792{ 793 amd_dbgapi_debug_printf ("ptid = %s", ptid.to_string ().c_str ()); 794 795 bool many_threads = ptid == minus_one_ptid || ptid.is_pid (); 796 797 if (!ptid_is_gpu (ptid) || many_threads) 798 { 799 beneath ()->stop (ptid); 800 801 /* The request is for a single thread, we are done. */ 802 if (!many_threads) 803 return; 804 } 805 806 auto stop_one_thread = [this] (thread_info *thread) 807 { 808 gdb_assert (thread != nullptr); 809 810 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid); 811 amd_dbgapi_wave_state_t state; 812 amd_dbgapi_status_t status 813 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STATE, 814 sizeof (state), &state); 815 if (status == AMD_DBGAPI_STATUS_SUCCESS) 816 { 817 /* If the wave is already known to be stopped then do nothing. */ 818 if (state == AMD_DBGAPI_WAVE_STATE_STOP) 819 return; 820 821 status = amd_dbgapi_wave_stop (wave_id); 822 if (status == AMD_DBGAPI_STATUS_SUCCESS) 823 { 824 wave_info &wi = get_thread_wave_info (thread); 825 wi.stopping = true; 826 return; 827 } 828 829 if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID) 830 error (_("wave_stop for wave_%ld failed (%s)"), wave_id.handle, 831 get_status_string (status)); 832 } 833 else if (status != AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID) 834 error (_("wave_get_info for wave_%ld failed (%s)"), wave_id.handle, 835 get_status_string (status)); 836 837 /* The status is AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID. The wave 838 could have terminated since the last time the wave list was 839 refreshed. */ 840 841 wave_info &wi = get_thread_wave_info (thread); 842 wi.stopping = true; 843 844 amd_dbgapi_debug_printf ("got AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID " 845 "for wave_%ld, last_resume_mode=%s, " 846 "report_thread_events=%d", 847 wave_id.handle, 848 resume_mode_to_string (wi.last_resume_mode), 849 m_report_thread_events); 850 851 /* If the wave was stepping when it terminated, then it is 852 guaranteed that we will see a WAVE_COMMAND_TERMINATED event 853 for it. Don't report a thread exit event or delete the 854 thread yet, until we see such event. */ 855 if (wi.last_resume_mode == AMD_DBGAPI_RESUME_MODE_SINGLE_STEP) 856 return; 857 858 if (m_report_thread_events) 859 { 860 get_amd_dbgapi_inferior_info (thread->inf)->wave_events.emplace_back 861 (thread->ptid, target_waitstatus ().set_thread_exited (0)); 862 863 if (target_is_async_p ()) 864 async_event_handler_mark (); 865 } 866 867 delete_thread_silent (thread); 868 }; 869 870 process_stratum_target *proc_target = current_inferior ()->process_target (); 871 872 /* Disable forward progress requirement. */ 873 require_forward_progress (ptid, proc_target, false); 874 875 if (!many_threads) 876 { 877 /* No need to iterate all non-exited threads if the request is to stop a 878 specific thread. */ 879 stop_one_thread (proc_target->find_thread (ptid)); 880 return; 881 } 882 883 for (auto *inf : all_inferiors (proc_target)) 884 /* Use the threads_safe iterator since stop_one_thread may delete the 885 thread if it has exited. */ 886 for (auto *thread : inf->threads_safe ()) 887 if (thread->state != THREAD_EXITED && thread->ptid.matches (ptid) 888 && ptid_is_gpu (thread->ptid)) 889 stop_one_thread (thread); 890} 891 892/* Callback for our async event handler. */ 893 894static void 895handle_target_event (gdb_client_data client_data) 896{ 897 inferior_event_handler (INF_REG_EVENT); 898} 899 900struct scoped_amd_dbgapi_event_processed 901{ 902 scoped_amd_dbgapi_event_processed (amd_dbgapi_event_id_t event_id) 903 : m_event_id (event_id) 904 { 905 gdb_assert (event_id != AMD_DBGAPI_EVENT_NONE); 906 } 907 908 ~scoped_amd_dbgapi_event_processed () 909 { 910 amd_dbgapi_status_t status = amd_dbgapi_event_processed (m_event_id); 911 if (status != AMD_DBGAPI_STATUS_SUCCESS) 912 warning (_("Failed to acknowledge amd-dbgapi event %" PRIu64), 913 m_event_id.handle); 914 } 915 916 DISABLE_COPY_AND_ASSIGN (scoped_amd_dbgapi_event_processed); 917 918private: 919 amd_dbgapi_event_id_t m_event_id; 920}; 921 922/* Called when a dbgapi notifier fd is readable. CLIENT_DATA is the 923 amd_dbgapi_inferior_info object corresponding to the notifier. */ 924 925static void 926dbgapi_notifier_handler (int err, gdb_client_data client_data) 927{ 928 amd_dbgapi_inferior_info *info = (amd_dbgapi_inferior_info *) client_data; 929 int ret; 930 931 /* Drain the notifier pipe. */ 932 do 933 { 934 char buf; 935 ret = read (info->notifier, &buf, 1); 936 } 937 while (ret >= 0 || (ret == -1 && errno == EINTR)); 938 939 if (info->inf->target_is_pushed (&the_amd_dbgapi_target)) 940 { 941 /* The amd-dbgapi target is pushed: signal our async handler, the event 942 will be consumed through our wait method. */ 943 944 async_event_handler_mark (); 945 } 946 else 947 { 948 /* The amd-dbgapi target is not pushed: if there's an event, the only 949 expected one is one of the RUNTIME kind. If the event tells us the 950 inferior as activated the ROCm runtime, push the amd-dbgapi 951 target. */ 952 953 amd_dbgapi_event_id_t event_id; 954 amd_dbgapi_event_kind_t event_kind; 955 amd_dbgapi_status_t status 956 = amd_dbgapi_process_next_pending_event (info->process_id, &event_id, 957 &event_kind); 958 if (status != AMD_DBGAPI_STATUS_SUCCESS) 959 error (_("next_pending_event failed (%s)"), get_status_string (status)); 960 961 if (event_id == AMD_DBGAPI_EVENT_NONE) 962 return; 963 964 gdb_assert (event_kind == AMD_DBGAPI_EVENT_KIND_RUNTIME); 965 966 scoped_amd_dbgapi_event_processed mark_event_processed (event_id); 967 968 amd_dbgapi_runtime_state_t runtime_state; 969 status = amd_dbgapi_event_get_info (event_id, 970 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE, 971 sizeof (runtime_state), 972 &runtime_state); 973 if (status != AMD_DBGAPI_STATUS_SUCCESS) 974 error (_("event_get_info for event_%ld failed (%s)"), 975 event_id.handle, get_status_string (status)); 976 977 switch (runtime_state) 978 { 979 case AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS: 980 gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED); 981 info->runtime_state = runtime_state; 982 amd_dbgapi_debug_printf ("pushing amd-dbgapi target"); 983 info->inf->push_target (&the_amd_dbgapi_target); 984 985 /* The underlying target will already be async if we are running, but not if 986 we are attaching. */ 987 if (info->inf->process_target ()->is_async_p ()) 988 { 989 scoped_restore_current_thread restore_thread; 990 switch_to_inferior_no_thread (info->inf); 991 992 /* Make sure our async event handler is created. */ 993 target_async (true); 994 } 995 break; 996 997 case AMD_DBGAPI_RUNTIME_STATE_UNLOADED: 998 gdb_assert (info->runtime_state 999 == AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION); 1000 info->runtime_state = runtime_state; 1001 break; 1002 1003 case AMD_DBGAPI_RUNTIME_STATE_LOADED_ERROR_RESTRICTION: 1004 gdb_assert (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED); 1005 info->runtime_state = runtime_state; 1006 warning (_("amd-dbgapi: unable to enable GPU debugging " 1007 "due to a restriction error")); 1008 break; 1009 } 1010 } 1011} 1012 1013void 1014amd_dbgapi_target::async (bool enable) 1015{ 1016 beneath ()->async (enable); 1017 1018 if (enable) 1019 { 1020 if (amd_dbgapi_async_event_handler != nullptr) 1021 { 1022 /* Already enabled. */ 1023 return; 1024 } 1025 1026 /* The library gives us one notifier file descriptor per inferior (even 1027 the ones that have not yet loaded their runtime). Register them 1028 all with the event loop. */ 1029 process_stratum_target *proc_target 1030 = current_inferior ()->process_target (); 1031 1032 for (inferior *inf : all_non_exited_inferiors (proc_target)) 1033 { 1034 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 1035 1036 if (info->notifier != -1) 1037 add_file_handler (info->notifier, dbgapi_notifier_handler, info, 1038 string_printf ("amd-dbgapi notifier for pid %d", 1039 inf->pid)); 1040 } 1041 1042 amd_dbgapi_async_event_handler 1043 = create_async_event_handler (handle_target_event, nullptr, 1044 "amd-dbgapi"); 1045 1046 /* There may be pending events to handle. Tell the event loop to poll 1047 them. */ 1048 async_event_handler_mark (); 1049 } 1050 else 1051 { 1052 if (amd_dbgapi_async_event_handler == nullptr) 1053 return; 1054 1055 for (inferior *inf : all_inferiors ()) 1056 { 1057 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 1058 1059 if (info->notifier != -1) 1060 delete_file_handler (info->notifier); 1061 } 1062 1063 delete_async_event_handler (&amd_dbgapi_async_event_handler); 1064 } 1065} 1066 1067/* Make a ptid for a GPU wave. See comment on ptid_is_gpu for more details. */ 1068 1069static ptid_t 1070make_gpu_ptid (ptid_t::pid_type pid, amd_dbgapi_wave_id_t wave_id) 1071{ 1072 return ptid_t (pid, 1, wave_id.handle); 1073} 1074 1075/* When a thread is deleted, remove its wave_info from the inferior's 1076 wave_info map. */ 1077 1078static void 1079amd_dbgapi_thread_deleted (thread_info *tp) 1080{ 1081 if (tp->inf->target_at (arch_stratum) == &the_amd_dbgapi_target 1082 && ptid_is_gpu (tp->ptid)) 1083 { 1084 amd_dbgapi_inferior_info *info = amd_dbgapi_inferior_data.get (tp->inf); 1085 auto wave_id = get_amd_dbgapi_wave_id (tp->ptid); 1086 auto it = info->wave_info_map.find (wave_id.handle); 1087 gdb_assert (it != info->wave_info_map.end ()); 1088 info->wave_info_map.erase (it); 1089 } 1090} 1091 1092/* Register WAVE_PTID as a new thread in INF's thread list, and record 1093 its wave_info in the inferior's wave_info map. */ 1094 1095static thread_info * 1096add_gpu_thread (inferior *inf, ptid_t wave_ptid) 1097{ 1098 process_stratum_target *proc_target = inf->process_target (); 1099 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 1100 1101 auto wave_id = get_amd_dbgapi_wave_id (wave_ptid); 1102 1103 if (!info->wave_info_map.try_emplace (wave_id.handle, 1104 wave_info (wave_id)).second) 1105 internal_error ("wave ID %ld already in map", wave_id.handle); 1106 1107 /* Create new GPU threads silently to avoid spamming the terminal 1108 with thousands of "[New Thread ...]" messages. */ 1109 thread_info *thread = add_thread_silent (proc_target, wave_ptid); 1110 set_running (proc_target, wave_ptid, true); 1111 set_executing (proc_target, wave_ptid, true); 1112 return thread; 1113} 1114 1115/* Process an event that was just pulled out of the amd-dbgapi library. */ 1116 1117static void 1118process_one_event (amd_dbgapi_event_id_t event_id, 1119 amd_dbgapi_event_kind_t event_kind) 1120{ 1121 /* Automatically mark this event processed when going out of scope. */ 1122 scoped_amd_dbgapi_event_processed mark_event_processed (event_id); 1123 1124 amd_dbgapi_process_id_t process_id; 1125 amd_dbgapi_status_t status 1126 = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_PROCESS, 1127 sizeof (process_id), &process_id); 1128 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1129 error (_("event_get_info for event_%ld failed (%s)"), event_id.handle, 1130 get_status_string (status)); 1131 1132 amd_dbgapi_os_process_id_t pid; 1133 status = amd_dbgapi_process_get_info (process_id, 1134 AMD_DBGAPI_PROCESS_INFO_OS_ID, 1135 sizeof (pid), &pid); 1136 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1137 error (_("process_get_info for process_%ld failed (%s)"), 1138 process_id.handle, get_status_string (status)); 1139 1140 auto *proc_target = current_inferior ()->process_target (); 1141 inferior *inf = find_inferior_pid (proc_target, pid); 1142 gdb_assert (inf != nullptr); 1143 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 1144 1145 switch (event_kind) 1146 { 1147 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED: 1148 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP: 1149 { 1150 amd_dbgapi_wave_id_t wave_id; 1151 status 1152 = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_WAVE, 1153 sizeof (wave_id), &wave_id); 1154 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1155 error (_("event_get_info for event_%ld failed (%s)"), 1156 event_id.handle, get_status_string (status)); 1157 1158 ptid_t event_ptid = make_gpu_ptid (pid, wave_id); 1159 target_waitstatus ws; 1160 1161 amd_dbgapi_wave_stop_reasons_t stop_reason; 1162 status = amd_dbgapi_wave_get_info (wave_id, 1163 AMD_DBGAPI_WAVE_INFO_STOP_REASON, 1164 sizeof (stop_reason), &stop_reason); 1165 if (status == AMD_DBGAPI_STATUS_ERROR_INVALID_WAVE_ID 1166 && event_kind == AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED) 1167 ws.set_thread_exited (0); 1168 else if (status == AMD_DBGAPI_STATUS_SUCCESS) 1169 { 1170 if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_APERTURE_VIOLATION) 1171 ws.set_stopped (GDB_SIGNAL_BUS); 1172 else if (stop_reason 1173 & AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION) 1174 ws.set_stopped (GDB_SIGNAL_SEGV); 1175 else if (stop_reason 1176 & AMD_DBGAPI_WAVE_STOP_REASON_ILLEGAL_INSTRUCTION) 1177 ws.set_stopped (GDB_SIGNAL_ILL); 1178 else if (stop_reason 1179 & (AMD_DBGAPI_WAVE_STOP_REASON_FP_INPUT_DENORMAL 1180 | AMD_DBGAPI_WAVE_STOP_REASON_FP_DIVIDE_BY_0 1181 | AMD_DBGAPI_WAVE_STOP_REASON_FP_OVERFLOW 1182 | AMD_DBGAPI_WAVE_STOP_REASON_FP_UNDERFLOW 1183 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INEXACT 1184 | AMD_DBGAPI_WAVE_STOP_REASON_FP_INVALID_OPERATION 1185 | AMD_DBGAPI_WAVE_STOP_REASON_INT_DIVIDE_BY_0)) 1186 ws.set_stopped (GDB_SIGNAL_FPE); 1187 else if (stop_reason 1188 & (AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT 1189 | AMD_DBGAPI_WAVE_STOP_REASON_WATCHPOINT 1190 | AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP 1191 | AMD_DBGAPI_WAVE_STOP_REASON_DEBUG_TRAP 1192 | AMD_DBGAPI_WAVE_STOP_REASON_TRAP)) 1193 ws.set_stopped (GDB_SIGNAL_TRAP); 1194 else if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_ASSERT_TRAP) 1195 ws.set_stopped (GDB_SIGNAL_ABRT); 1196 else 1197 ws.set_stopped (GDB_SIGNAL_0); 1198 1199 thread_info *thread = proc_target->find_thread (event_ptid); 1200 if (thread == nullptr) 1201 thread = add_gpu_thread (inf, event_ptid); 1202 1203 /* If the wave is stopped because of a software breakpoint, the 1204 program counter needs to be adjusted so that it points to the 1205 breakpoint instruction. */ 1206 if ((stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT) != 0) 1207 { 1208 regcache *regcache = get_thread_regcache (thread); 1209 gdbarch *gdbarch = regcache->arch (); 1210 1211 CORE_ADDR pc = regcache_read_pc (regcache); 1212 CORE_ADDR adjusted_pc 1213 = pc - gdbarch_decr_pc_after_break (gdbarch); 1214 1215 if (adjusted_pc != pc) 1216 regcache_write_pc (regcache, adjusted_pc); 1217 } 1218 } 1219 else 1220 error (_("wave_get_info for wave_%ld failed (%s)"), 1221 wave_id.handle, get_status_string (status)); 1222 1223 info->wave_events.emplace_back (event_ptid, ws); 1224 break; 1225 } 1226 1227 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED: 1228 /* We get here when the following sequence of events happens: 1229 1230 - the inferior hits the amd-dbgapi "r_brk" internal breakpoint 1231 - amd_dbgapi_target_breakpoint::check_status calls 1232 amd_dbgapi_report_breakpoint_hit, which queues an event of this 1233 kind in dbgapi 1234 - amd_dbgapi_target_breakpoint::check_status calls 1235 process_event_queue, which pulls the event out of dbgapi, and 1236 gets us here 1237 1238 When amd_dbgapi_target_breakpoint::check_status is called, the current 1239 inferior is the inferior that hit the breakpoint, which should still be 1240 the case now. */ 1241 gdb_assert (inf == current_inferior ()); 1242 handle_solib_event (); 1243 break; 1244 1245 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME: 1246 /* Breakpoint resume events should be handled by the breakpoint 1247 action, and this code should not reach this. */ 1248 gdb_assert_not_reached ("unhandled event kind"); 1249 break; 1250 1251 case AMD_DBGAPI_EVENT_KIND_RUNTIME: 1252 { 1253 amd_dbgapi_runtime_state_t runtime_state; 1254 1255 status = amd_dbgapi_event_get_info (event_id, 1256 AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE, 1257 sizeof (runtime_state), 1258 &runtime_state); 1259 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1260 error (_("event_get_info for event_%ld failed (%s)"), 1261 event_id.handle, get_status_string (status)); 1262 1263 gdb_assert (runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED); 1264 gdb_assert 1265 (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS); 1266 1267 info->runtime_state = runtime_state; 1268 1269 gdb_assert (inf->target_is_pushed (&the_amd_dbgapi_target)); 1270 inf->unpush_target (&the_amd_dbgapi_target); 1271 } 1272 break; 1273 1274 default: 1275 error (_("event kind (%d) not supported"), event_kind); 1276 } 1277} 1278 1279/* Return a textual version of KIND. */ 1280 1281static const char * 1282event_kind_str (amd_dbgapi_event_kind_t kind) 1283{ 1284 switch (kind) 1285 { 1286 case AMD_DBGAPI_EVENT_KIND_NONE: 1287 return "NONE"; 1288 1289 case AMD_DBGAPI_EVENT_KIND_WAVE_STOP: 1290 return "WAVE_STOP"; 1291 1292 case AMD_DBGAPI_EVENT_KIND_WAVE_COMMAND_TERMINATED: 1293 return "WAVE_COMMAND_TERMINATED"; 1294 1295 case AMD_DBGAPI_EVENT_KIND_CODE_OBJECT_LIST_UPDATED: 1296 return "CODE_OBJECT_LIST_UPDATED"; 1297 1298 case AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME: 1299 return "BREAKPOINT_RESUME"; 1300 1301 case AMD_DBGAPI_EVENT_KIND_RUNTIME: 1302 return "RUNTIME"; 1303 1304 case AMD_DBGAPI_EVENT_KIND_QUEUE_ERROR: 1305 return "QUEUE_ERROR"; 1306 } 1307 1308 gdb_assert_not_reached ("unhandled amd_dbgapi_event_kind_t value"); 1309} 1310 1311/* Drain the dbgapi event queue of a given process_id, or of all processes if 1312 process_id is AMD_DBGAPI_PROCESS_NONE. Stop processing the events if an 1313 event of a given kind is requested and `process_id` is not 1314 AMD_DBGAPI_PROCESS_NONE. Wave stop events that are not returned are queued 1315 into their inferior's amd_dbgapi_inferior_info pending wave events. */ 1316 1317static amd_dbgapi_event_id_t 1318process_event_queue (amd_dbgapi_process_id_t process_id, 1319 amd_dbgapi_event_kind_t until_event_kind) 1320{ 1321 /* An event of a given type can only be requested from a single 1322 process_id. */ 1323 gdb_assert (until_event_kind == AMD_DBGAPI_EVENT_KIND_NONE 1324 || process_id != AMD_DBGAPI_PROCESS_NONE); 1325 1326 while (true) 1327 { 1328 amd_dbgapi_event_id_t event_id; 1329 amd_dbgapi_event_kind_t event_kind; 1330 1331 amd_dbgapi_status_t status 1332 = amd_dbgapi_process_next_pending_event (process_id, &event_id, 1333 &event_kind); 1334 1335 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1336 error (_("next_pending_event failed (%s)"), get_status_string (status)); 1337 1338 if (event_kind != AMD_DBGAPI_EVENT_KIND_NONE) 1339 amd_dbgapi_debug_printf ("Pulled event from dbgapi: " 1340 "event_id.handle = %" PRIu64 ", " 1341 "event_kind = %s", 1342 event_id.handle, 1343 event_kind_str (event_kind)); 1344 1345 if (event_id == AMD_DBGAPI_EVENT_NONE || event_kind == until_event_kind) 1346 return event_id; 1347 1348 process_one_event (event_id, event_kind); 1349 } 1350} 1351 1352bool 1353amd_dbgapi_target::has_pending_events () 1354{ 1355 if (amd_dbgapi_async_event_handler != nullptr 1356 && async_event_handler_marked (amd_dbgapi_async_event_handler)) 1357 return true; 1358 1359 return beneath ()->has_pending_events (); 1360} 1361 1362/* Pop one pending event from the per-inferior structures. 1363 1364 If PID is not -1, restrict the search to the inferior with that pid. */ 1365 1366static std::pair<ptid_t, target_waitstatus> 1367consume_one_event (int pid) 1368{ 1369 auto *target = current_inferior ()->process_target (); 1370 struct amd_dbgapi_inferior_info *info = nullptr; 1371 1372 if (pid == -1) 1373 { 1374 for (inferior *inf : all_inferiors (target)) 1375 { 1376 info = get_amd_dbgapi_inferior_info (inf); 1377 if (!info->wave_events.empty ()) 1378 break; 1379 } 1380 1381 gdb_assert (info != nullptr); 1382 } 1383 else 1384 { 1385 inferior *inf = find_inferior_pid (target, pid); 1386 1387 gdb_assert (inf != nullptr); 1388 info = get_amd_dbgapi_inferior_info (inf); 1389 } 1390 1391 if (info->wave_events.empty ()) 1392 return { minus_one_ptid, {} }; 1393 1394 auto event = info->wave_events.front (); 1395 info->wave_events.pop_front (); 1396 1397 return event; 1398} 1399 1400ptid_t 1401amd_dbgapi_target::wait (ptid_t ptid, struct target_waitstatus *ws, 1402 target_wait_flags target_options) 1403{ 1404 gdb_assert (!current_inferior ()->process_target ()->commit_resumed_state); 1405 gdb_assert (ptid == minus_one_ptid || ptid.is_pid ()); 1406 1407 amd_dbgapi_debug_printf ("ptid = %s", ptid.to_string ().c_str ()); 1408 1409 ptid_t event_ptid = beneath ()->wait (ptid, ws, target_options); 1410 if (event_ptid != minus_one_ptid) 1411 { 1412 if (ws->kind () == TARGET_WAITKIND_EXITED 1413 || ws->kind () == TARGET_WAITKIND_SIGNALLED) 1414 { 1415 /* This inferior has exited so drain its dbgapi event queue. */ 1416 while (consume_one_event (event_ptid.pid ()).first 1417 != minus_one_ptid) 1418 ; 1419 } 1420 return event_ptid; 1421 } 1422 1423 gdb_assert (ws->kind () == TARGET_WAITKIND_NO_RESUMED 1424 || ws->kind () == TARGET_WAITKIND_IGNORE); 1425 1426 /* Flush the async handler first. */ 1427 if (target_is_async_p ()) 1428 async_event_handler_clear (); 1429 1430 /* There may be more events to process (either already in `wave_events` or 1431 that we need to fetch from dbgapi. Mark the async event handler so that 1432 amd_dbgapi_target::wait gets called again and again, until it eventually 1433 returns minus_one_ptid. */ 1434 auto more_events = make_scope_exit ([] () 1435 { 1436 if (target_is_async_p ()) 1437 async_event_handler_mark (); 1438 }); 1439 1440 auto *proc_target = current_inferior ()->process_target (); 1441 1442 /* Disable forward progress for the specified pid in ptid if it isn't 1443 minus_on_ptid, or all attached processes if ptid is minus_one_ptid. */ 1444 require_forward_progress (ptid, proc_target, false); 1445 1446 target_waitstatus gpu_waitstatus; 1447 std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ()); 1448 if (event_ptid == minus_one_ptid) 1449 { 1450 /* Drain the events for the current inferior from the amd_dbgapi and 1451 preserve the ordering. */ 1452 auto info = get_amd_dbgapi_inferior_info (current_inferior ()); 1453 process_event_queue (info->process_id, AMD_DBGAPI_EVENT_KIND_NONE); 1454 1455 std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ()); 1456 if (event_ptid == minus_one_ptid) 1457 { 1458 /* If we requested a specific ptid, and nothing came out, assume 1459 another ptid may have more events, otherwise, keep the 1460 async_event_handler flushed. */ 1461 if (ptid == minus_one_ptid) 1462 more_events.release (); 1463 1464 if (ws->kind () == TARGET_WAITKIND_NO_RESUMED) 1465 { 1466 /* We can't easily check that all GPU waves are stopped, and no 1467 new waves can be created (the GPU has fixed function hardware 1468 to create new threads), so even if the target beneath returns 1469 waitkind_no_resumed, we have to report waitkind_ignore if GPU 1470 debugging is enabled for at least one resumed inferior handled 1471 by the amd-dbgapi target. */ 1472 1473 for (inferior *inf : all_inferiors ()) 1474 if (inf->target_at (arch_stratum) == &the_amd_dbgapi_target 1475 && get_amd_dbgapi_inferior_info (inf)->runtime_state 1476 == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS) 1477 { 1478 ws->set_ignore (); 1479 break; 1480 } 1481 } 1482 1483 /* There are no events to report, return the target beneath's 1484 waitstatus (either IGNORE or NO_RESUMED). */ 1485 return minus_one_ptid; 1486 } 1487 } 1488 1489 *ws = gpu_waitstatus; 1490 return event_ptid; 1491} 1492 1493bool 1494amd_dbgapi_target::stopped_by_sw_breakpoint () 1495{ 1496 if (!ptid_is_gpu (inferior_ptid)) 1497 return beneath ()->stopped_by_sw_breakpoint (); 1498 1499 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (inferior_ptid); 1500 1501 amd_dbgapi_wave_stop_reasons_t stop_reason; 1502 amd_dbgapi_status_t status 1503 = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STOP_REASON, 1504 sizeof (stop_reason), &stop_reason); 1505 1506 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1507 return false; 1508 1509 return (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_BREAKPOINT) != 0; 1510} 1511 1512bool 1513amd_dbgapi_target::stopped_by_hw_breakpoint () 1514{ 1515 if (!ptid_is_gpu (inferior_ptid)) 1516 return beneath ()->stopped_by_hw_breakpoint (); 1517 1518 return false; 1519} 1520 1521/* Set the process' memory access reporting precision mode. 1522 1523 Warn if the requested mode is not supported on at least one agent in the 1524 process. 1525 1526 Error out if setting the requested mode failed for some other reason. */ 1527 1528static void 1529set_process_memory_precision (amd_dbgapi_inferior_info &info) 1530{ 1531 auto mode = (info.precise_memory.requested 1532 ? AMD_DBGAPI_MEMORY_PRECISION_PRECISE 1533 : AMD_DBGAPI_MEMORY_PRECISION_NONE); 1534 amd_dbgapi_status_t status 1535 = amd_dbgapi_set_memory_precision (info.process_id, mode); 1536 1537 if (status == AMD_DBGAPI_STATUS_SUCCESS) 1538 info.precise_memory.enabled = info.precise_memory.requested; 1539 else if (status == AMD_DBGAPI_STATUS_ERROR_NOT_SUPPORTED) 1540 warning (_("AMDGPU precise memory access reporting could not be enabled.")); 1541 else if (status != AMD_DBGAPI_STATUS_SUCCESS) 1542 error (_("amd_dbgapi_set_memory_precision failed (%s)"), 1543 get_status_string (status)); 1544} 1545 1546/* Make the amd-dbgapi library attach to the process behind INF. 1547 1548 Note that this is unrelated to the "attach" GDB concept / command. 1549 1550 By attaching to the process, we get a notifier fd that tells us when it 1551 activates the ROCm runtime and when there are subsequent debug events. */ 1552 1553static void 1554attach_amd_dbgapi (inferior *inf) 1555{ 1556 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num); 1557 1558 if (!target_can_async_p ()) 1559 { 1560 warning (_("The amd-dbgapi target requires the target beneath to be " 1561 "asynchronous, GPU debugging is disabled")); 1562 return; 1563 } 1564 1565 /* dbgapi can't attach to a vfork child (a process born from a vfork that 1566 hasn't exec'ed yet) while we are still attached to the parent. It would 1567 not be useful for us to attach to vfork children anyway, because vfork 1568 children are very restricted in what they can do (see vfork(2)) and aren't 1569 going to launch some GPU programs that we need to debug. To avoid this 1570 problem, we don't push the amd-dbgapi target / attach dbgapi in vfork 1571 children. If a vfork child execs, we'll try enabling the amd-dbgapi target 1572 through the inferior_execd observer. */ 1573 if (inf->vfork_parent != nullptr) 1574 return; 1575 1576 auto *info = get_amd_dbgapi_inferior_info (inf); 1577 1578 /* Are we already attached? */ 1579 if (info->process_id != AMD_DBGAPI_PROCESS_NONE) 1580 { 1581 amd_dbgapi_debug_printf 1582 ("already attached: process_id = %" PRIu64, info->process_id.handle); 1583 return; 1584 } 1585 1586 amd_dbgapi_status_t status 1587 = amd_dbgapi_process_attach 1588 (reinterpret_cast<amd_dbgapi_client_process_id_t> (inf), 1589 &info->process_id); 1590 if (status == AMD_DBGAPI_STATUS_ERROR_RESTRICTION) 1591 { 1592 warning (_("amd-dbgapi: unable to enable GPU debugging due to a " 1593 "restriction error")); 1594 return; 1595 } 1596 else if (status != AMD_DBGAPI_STATUS_SUCCESS) 1597 { 1598 warning (_("amd-dbgapi: could not attach to process %d (%s), GPU " 1599 "debugging will not be available."), inf->pid, 1600 get_status_string (status)); 1601 return; 1602 } 1603 1604 if (amd_dbgapi_process_get_info (info->process_id, 1605 AMD_DBGAPI_PROCESS_INFO_NOTIFIER, 1606 sizeof (info->notifier), &info->notifier) 1607 != AMD_DBGAPI_STATUS_SUCCESS) 1608 { 1609 amd_dbgapi_process_detach (info->process_id); 1610 info->process_id = AMD_DBGAPI_PROCESS_NONE; 1611 warning (_("amd-dbgapi: could not retrieve process %d's notifier, GPU " 1612 "debugging will not be available."), inf->pid); 1613 return; 1614 } 1615 1616 amd_dbgapi_debug_printf ("process_id = %" PRIu64 ", notifier fd = %d", 1617 info->process_id.handle, info->notifier); 1618 1619 set_process_memory_precision (*info); 1620 1621 /* If GDB is attaching to a process that has the runtime loaded, there will 1622 already be a "runtime loaded" event available. Consume it and push the 1623 target. */ 1624 dbgapi_notifier_handler (0, info); 1625 1626 add_file_handler (info->notifier, dbgapi_notifier_handler, info, 1627 "amd-dbgapi notifier"); 1628} 1629 1630static void maybe_reset_amd_dbgapi (); 1631 1632/* Make the amd-dbgapi library detach from INF. 1633 1634 Note that this us unrelated to the "detach" GDB concept / command. 1635 1636 This undoes what attach_amd_dbgapi does. */ 1637 1638static void 1639detach_amd_dbgapi (inferior *inf) 1640{ 1641 AMD_DBGAPI_SCOPED_DEBUG_START_END ("inf num = %d", inf->num); 1642 1643 auto *info = get_amd_dbgapi_inferior_info (inf); 1644 1645 if (info->process_id == AMD_DBGAPI_PROCESS_NONE) 1646 return; 1647 1648 info->runtime_state = AMD_DBGAPI_RUNTIME_STATE_UNLOADED; 1649 1650 amd_dbgapi_status_t status = amd_dbgapi_process_detach (info->process_id); 1651 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1652 warning (_("amd-dbgapi: could not detach from process %d (%s)"), 1653 inf->pid, get_status_string (status)); 1654 1655 gdb_assert (info->notifier != -1); 1656 delete_file_handler (info->notifier); 1657 1658 /* This is a noop if the target is not pushed. */ 1659 inf->unpush_target (&the_amd_dbgapi_target); 1660 1661 /* Delete the breakpoints that are still active. */ 1662 for (auto &&value : info->breakpoint_map) 1663 delete_breakpoint (value.second); 1664 1665 /* Reset the amd_dbgapi_inferior_info, except for precise_memory_mode. */ 1666 *info = amd_dbgapi_inferior_info (inf, info->precise_memory.requested); 1667 1668 maybe_reset_amd_dbgapi (); 1669} 1670 1671void 1672amd_dbgapi_target::mourn_inferior () 1673{ 1674 detach_amd_dbgapi (current_inferior ()); 1675 beneath ()->mourn_inferior (); 1676} 1677 1678void 1679amd_dbgapi_target::detach (inferior *inf, int from_tty) 1680{ 1681 /* We're about to resume the waves by detaching the dbgapi library from the 1682 inferior, so we need to remove all breakpoints that are still inserted. 1683 1684 Breakpoints may still be inserted because the inferior may be running in 1685 non-stop mode, or because GDB changed the default setting to leave all 1686 breakpoints inserted in all-stop mode when all threads are stopped. */ 1687 remove_breakpoints_inf (inf); 1688 1689 detach_amd_dbgapi (inf); 1690 beneath ()->detach (inf, from_tty); 1691} 1692 1693void 1694amd_dbgapi_target::fetch_registers (struct regcache *regcache, int regno) 1695{ 1696 if (!ptid_is_gpu (regcache->ptid ())) 1697 { 1698 beneath ()->fetch_registers (regcache, regno); 1699 return; 1700 } 1701 1702 struct gdbarch *gdbarch = regcache->arch (); 1703 gdb_assert (is_amdgpu_arch (gdbarch)); 1704 1705 amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch); 1706 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ()); 1707 gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE]; 1708 amd_dbgapi_status_t status 1709 = amd_dbgapi_read_register (wave_id, tdep->register_ids[regno], 0, 1710 register_type (gdbarch, regno)->length (), 1711 raw); 1712 1713 if (status == AMD_DBGAPI_STATUS_SUCCESS) 1714 regcache->raw_supply (regno, raw); 1715 else if (status != AMD_DBGAPI_STATUS_ERROR_REGISTER_NOT_AVAILABLE) 1716 warning (_("Couldn't read register %s (#%d) (%s)."), 1717 gdbarch_register_name (gdbarch, regno), regno, 1718 get_status_string (status)); 1719} 1720 1721void 1722amd_dbgapi_target::store_registers (struct regcache *regcache, int regno) 1723{ 1724 if (!ptid_is_gpu (regcache->ptid ())) 1725 { 1726 beneath ()->store_registers (regcache, regno); 1727 return; 1728 } 1729 1730 struct gdbarch *gdbarch = regcache->arch (); 1731 gdb_assert (is_amdgpu_arch (gdbarch)); 1732 1733 gdb_byte raw[AMDGPU_MAX_REGISTER_SIZE]; 1734 regcache->raw_collect (regno, &raw); 1735 1736 amdgpu_gdbarch_tdep *tdep = get_amdgpu_gdbarch_tdep (gdbarch); 1737 1738 /* If the register has read-only bits, invalidate the value in the regcache 1739 as the value actually written may differ. */ 1740 if (tdep->register_properties[regno] 1741 & AMD_DBGAPI_REGISTER_PROPERTY_READONLY_BITS) 1742 regcache->invalidate (regno); 1743 1744 /* Invalidate all volatile registers if this register has the invalidate 1745 volatile property. For example, writing to VCC may change the content 1746 of STATUS.VCCZ. */ 1747 if (tdep->register_properties[regno] 1748 & AMD_DBGAPI_REGISTER_PROPERTY_INVALIDATE_VOLATILE) 1749 { 1750 for (size_t r = 0; r < tdep->register_properties.size (); ++r) 1751 if (tdep->register_properties[r] & AMD_DBGAPI_REGISTER_PROPERTY_VOLATILE) 1752 regcache->invalidate (r); 1753 } 1754 1755 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (regcache->ptid ()); 1756 amd_dbgapi_status_t status 1757 = amd_dbgapi_write_register (wave_id, tdep->register_ids[regno], 0, 1758 register_type (gdbarch, regno)->length (), 1759 raw); 1760 1761 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1762 warning (_("Couldn't write register %s (#%d)."), 1763 gdbarch_register_name (gdbarch, regno), regno); 1764} 1765 1766struct gdbarch * 1767amd_dbgapi_target::thread_architecture (ptid_t ptid) 1768{ 1769 if (!ptid_is_gpu (ptid)) 1770 return beneath ()->thread_architecture (ptid); 1771 1772 /* We can cache the gdbarch for a given wave_id (ptid::tid) because 1773 wave IDs are unique, and aren't reused. */ 1774 if (ptid.tid () == m_cached_arch_tid) 1775 return m_cached_arch; 1776 1777 amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (ptid); 1778 amd_dbgapi_architecture_id_t architecture_id; 1779 amd_dbgapi_status_t status; 1780 1781 status = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_ARCHITECTURE, 1782 sizeof (architecture_id), 1783 &architecture_id); 1784 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1785 error (_("Couldn't get architecture for wave_%ld"), ptid.tid ()); 1786 1787 uint32_t elf_amdgpu_machine; 1788 status = amd_dbgapi_architecture_get_info 1789 (architecture_id, AMD_DBGAPI_ARCHITECTURE_INFO_ELF_AMDGPU_MACHINE, 1790 sizeof (elf_amdgpu_machine), &elf_amdgpu_machine); 1791 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1792 error (_("Couldn't get elf_amdgpu_machine for architecture_%ld"), 1793 architecture_id.handle); 1794 1795 struct gdbarch_info info; 1796 info.bfd_arch_info = bfd_lookup_arch (bfd_arch_amdgcn, elf_amdgpu_machine); 1797 info.byte_order = BFD_ENDIAN_LITTLE; 1798 1799 m_cached_arch_tid = ptid.tid (); 1800 m_cached_arch = gdbarch_find_by_info (info); 1801 if (m_cached_arch == nullptr) 1802 error (_("Couldn't get elf_amdgpu_machine (%#x)"), elf_amdgpu_machine); 1803 1804 return m_cached_arch; 1805} 1806 1807void 1808amd_dbgapi_target::thread_events (int enable) 1809{ 1810 m_report_thread_events = enable; 1811 beneath ()->thread_events (enable); 1812} 1813 1814void 1815amd_dbgapi_target::update_thread_list () 1816{ 1817 for (inferior *inf : all_inferiors ()) 1818 { 1819 amd_dbgapi_process_id_t process_id 1820 = get_amd_dbgapi_process_id (inf); 1821 if (process_id == AMD_DBGAPI_PROCESS_NONE) 1822 { 1823 /* The inferior may not be attached yet. */ 1824 continue; 1825 } 1826 1827 size_t count; 1828 amd_dbgapi_wave_id_t *wave_list; 1829 amd_dbgapi_changed_t changed; 1830 amd_dbgapi_status_t status 1831 = amd_dbgapi_process_wave_list (process_id, &count, &wave_list, 1832 &changed); 1833 if (status != AMD_DBGAPI_STATUS_SUCCESS) 1834 error (_("amd_dbgapi_wave_list failed (%s)"), 1835 get_status_string (status)); 1836 1837 if (changed == AMD_DBGAPI_CHANGED_NO) 1838 continue; 1839 1840 /* Create a set and free the wave list. */ 1841 std::set<ptid_t::tid_type> threads; 1842 for (size_t i = 0; i < count; ++i) 1843 threads.emplace (wave_list[i].handle); 1844 1845 xfree (wave_list); 1846 1847 /* Prune the wave_ids that already have a thread_info. Any thread_info 1848 which does not have a corresponding wave_id represents a wave which 1849 is gone at this point and should be deleted. */ 1850 for (thread_info *tp : inf->threads_safe ()) 1851 if (ptid_is_gpu (tp->ptid) && tp->state != THREAD_EXITED) 1852 { 1853 auto it = threads.find (tp->ptid.tid ()); 1854 1855 if (it == threads.end ()) 1856 { 1857 auto wave_id = get_amd_dbgapi_wave_id (tp->ptid); 1858 wave_info &wi = get_thread_wave_info (tp); 1859 1860 /* Waves that were stepping or in progress of being 1861 stopped are guaranteed to report a 1862 WAVE_COMMAND_TERMINATED event if they terminate. 1863 Don't delete such threads until we see the 1864 event. */ 1865 if (wi.last_resume_mode == AMD_DBGAPI_RESUME_MODE_SINGLE_STEP 1866 || wi.stopping) 1867 { 1868 amd_dbgapi_debug_printf 1869 ("wave_%ld disappeared, keeping it" 1870 " (last_resume_mode=%s, stopping=%d)", 1871 wave_id.handle, 1872 resume_mode_to_string (wi.last_resume_mode), 1873 wi.stopping); 1874 } 1875 else 1876 { 1877 amd_dbgapi_debug_printf ("wave_%ld disappeared, deleting it", 1878 wave_id.handle); 1879 delete_thread_silent (tp); 1880 } 1881 } 1882 else 1883 threads.erase (it); 1884 } 1885 1886 /* The wave_ids that are left require a new thread_info. */ 1887 for (ptid_t::tid_type tid : threads) 1888 { 1889 ptid_t wave_ptid 1890 = make_gpu_ptid (inf->pid, amd_dbgapi_wave_id_t {tid}); 1891 add_gpu_thread (inf, wave_ptid); 1892 } 1893 } 1894 1895 /* Give the beneath target a chance to do extra processing. */ 1896 this->beneath ()->update_thread_list (); 1897} 1898 1899/* inferior_created observer. */ 1900 1901static void 1902amd_dbgapi_target_inferior_created (inferior *inf) 1903{ 1904 /* If the inferior is not running on the native target (e.g. it is running 1905 on a remote target), we don't want to deal with it. */ 1906 if (inf->process_target () != get_native_target ()) 1907 return; 1908 1909 attach_amd_dbgapi (inf); 1910} 1911 1912/* Callback called when an inferior is cloned. */ 1913 1914static void 1915amd_dbgapi_target_inferior_cloned (inferior *original_inferior, 1916 inferior *new_inferior) 1917{ 1918 auto *orig_info = get_amd_dbgapi_inferior_info (original_inferior); 1919 auto *new_info = get_amd_dbgapi_inferior_info (new_inferior); 1920 1921 /* At this point, the process is not started. Therefore it is sufficient to 1922 copy the precise memory request, it will be applied when the process 1923 starts. */ 1924 gdb_assert (new_info->process_id == AMD_DBGAPI_PROCESS_NONE); 1925 new_info->precise_memory.requested = orig_info->precise_memory.requested; 1926} 1927 1928/* inferior_execd observer. */ 1929 1930static void 1931amd_dbgapi_inferior_execd (inferior *exec_inf, inferior *follow_inf) 1932{ 1933 /* The inferior has EXEC'd and the process image has changed. The dbgapi is 1934 attached to the old process image, so we need to detach and re-attach to 1935 the new process image. */ 1936 detach_amd_dbgapi (exec_inf); 1937 1938 /* If using "follow-exec-mode new", carry over the precise-memory setting 1939 to the new inferior (otherwise, FOLLOW_INF and ORIG_INF point to the same 1940 inferior, so this is a no-op). */ 1941 get_amd_dbgapi_inferior_info (follow_inf)->precise_memory.requested 1942 = get_amd_dbgapi_inferior_info (exec_inf)->precise_memory.requested; 1943 1944 attach_amd_dbgapi (follow_inf); 1945} 1946 1947/* inferior_forked observer. */ 1948 1949static void 1950amd_dbgapi_inferior_forked (inferior *parent_inf, inferior *child_inf, 1951 target_waitkind fork_kind) 1952{ 1953 if (child_inf != nullptr) 1954 { 1955 /* Copy precise-memory requested value from parent to child. */ 1956 amd_dbgapi_inferior_info *parent_info 1957 = get_amd_dbgapi_inferior_info (parent_inf); 1958 amd_dbgapi_inferior_info *child_info 1959 = get_amd_dbgapi_inferior_info (child_inf); 1960 child_info->precise_memory.requested 1961 = parent_info->precise_memory.requested; 1962 1963 if (fork_kind != TARGET_WAITKIND_VFORKED) 1964 { 1965 scoped_restore_current_thread restore_thread; 1966 switch_to_thread (*child_inf->threads ().begin ()); 1967 attach_amd_dbgapi (child_inf); 1968 } 1969 } 1970} 1971 1972/* inferior_exit observer. 1973 1974 This covers normal exits, but also detached inferiors (including detached 1975 fork parents). */ 1976 1977static void 1978amd_dbgapi_inferior_exited (inferior *inf) 1979{ 1980 detach_amd_dbgapi (inf); 1981} 1982 1983/* inferior_pre_detach observer. */ 1984 1985static void 1986amd_dbgapi_inferior_pre_detach (inferior *inf) 1987{ 1988 /* We need to amd-dbgapi-detach before we ptrace-detach. If the amd-dbgapi 1989 target isn't pushed, do that now. If the amd-dbgapi target is pushed, 1990 we'll do it in amd_dbgapi_target::detach. */ 1991 if (!inf->target_is_pushed (&the_amd_dbgapi_target)) 1992 detach_amd_dbgapi (inf); 1993} 1994 1995/* get_os_pid callback. */ 1996 1997static amd_dbgapi_status_t 1998amd_dbgapi_get_os_pid_callback 1999 (amd_dbgapi_client_process_id_t client_process_id, pid_t *pid) 2000{ 2001 inferior *inf = reinterpret_cast<inferior *> (client_process_id); 2002 2003 if (inf->pid == 0) 2004 return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED; 2005 2006 *pid = inf->pid; 2007 return AMD_DBGAPI_STATUS_SUCCESS; 2008} 2009 2010/* insert_breakpoint callback. */ 2011 2012static amd_dbgapi_status_t 2013amd_dbgapi_insert_breakpoint_callback 2014 (amd_dbgapi_client_process_id_t client_process_id, 2015 amd_dbgapi_global_address_t address, 2016 amd_dbgapi_breakpoint_id_t breakpoint_id) 2017{ 2018 inferior *inf = reinterpret_cast<inferior *> (client_process_id); 2019 struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 2020 2021 auto it = info->breakpoint_map.find (breakpoint_id.handle); 2022 if (it != info->breakpoint_map.end ()) 2023 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID; 2024 2025 /* We need to find the address in the given inferior's program space. */ 2026 scoped_restore_current_thread restore_thread; 2027 switch_to_inferior_no_thread (inf); 2028 2029 /* Create a new breakpoint. */ 2030 struct obj_section *section = find_pc_section (address); 2031 if (section == nullptr || section->objfile == nullptr) 2032 return AMD_DBGAPI_STATUS_ERROR; 2033 2034 std::unique_ptr<breakpoint> bp_up 2035 (new amd_dbgapi_target_breakpoint (section->objfile->arch (), address)); 2036 2037 breakpoint *bp = install_breakpoint (true, std::move (bp_up), 1); 2038 2039 info->breakpoint_map.emplace (breakpoint_id.handle, bp); 2040 return AMD_DBGAPI_STATUS_SUCCESS; 2041} 2042 2043/* remove_breakpoint callback. */ 2044 2045static amd_dbgapi_status_t 2046amd_dbgapi_remove_breakpoint_callback 2047 (amd_dbgapi_client_process_id_t client_process_id, 2048 amd_dbgapi_breakpoint_id_t breakpoint_id) 2049{ 2050 inferior *inf = reinterpret_cast<inferior *> (client_process_id); 2051 struct amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 2052 2053 auto it = info->breakpoint_map.find (breakpoint_id.handle); 2054 if (it == info->breakpoint_map.end ()) 2055 return AMD_DBGAPI_STATUS_ERROR_INVALID_BREAKPOINT_ID; 2056 2057 delete_breakpoint (it->second); 2058 info->breakpoint_map.erase (it); 2059 2060 return AMD_DBGAPI_STATUS_SUCCESS; 2061} 2062 2063/* signal_received observer. */ 2064 2065static void 2066amd_dbgapi_target_signal_received (gdb_signal sig) 2067{ 2068 amd_dbgapi_inferior_info *info 2069 = get_amd_dbgapi_inferior_info (current_inferior ()); 2070 2071 if (info->process_id == AMD_DBGAPI_PROCESS_NONE) 2072 return; 2073 2074 if (!ptid_is_gpu (inferior_thread ()->ptid)) 2075 return; 2076 2077 if (sig != GDB_SIGNAL_SEGV && sig != GDB_SIGNAL_BUS) 2078 return; 2079 2080 if (!info->precise_memory.enabled) 2081 gdb_printf (_("\ 2082Warning: precise memory violation signal reporting is not enabled, reported\n\ 2083location may not be accurate. See \"show amdgpu precise-memory\".\n")); 2084} 2085 2086/* Style for some kinds of messages. */ 2087 2088static cli_style_option fatal_error_style 2089 ("amd_dbgapi_fatal_error", ui_file_style::RED); 2090static cli_style_option warning_style 2091 ("amd_dbgapi_warning", ui_file_style::YELLOW); 2092 2093/* BLACK + BOLD means dark gray. */ 2094static cli_style_option trace_style 2095 ("amd_dbgapi_trace", ui_file_style::BLACK, ui_file_style::BOLD); 2096 2097/* log_message callback. */ 2098 2099static void 2100amd_dbgapi_log_message_callback (amd_dbgapi_log_level_t level, 2101 const char *message) 2102{ 2103 std::optional<target_terminal::scoped_restore_terminal_state> tstate; 2104 2105 if (target_supports_terminal_ours ()) 2106 { 2107 tstate.emplace (); 2108 target_terminal::ours_for_output (); 2109 } 2110 2111 /* Error and warning messages are meant to be printed to the user. */ 2112 if (level == AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR 2113 || level == AMD_DBGAPI_LOG_LEVEL_WARNING) 2114 { 2115 begin_line (); 2116 ui_file_style style = (level == AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR 2117 ? fatal_error_style : warning_style).style (); 2118 gdb_printf (gdb_stderr, "%ps\n", styled_string (style, message)); 2119 return; 2120 } 2121 2122 /* Print other messages as debug logs. TRACE and VERBOSE messages are 2123 very verbose, print them dark grey so it's easier to spot other messages 2124 through the flood. */ 2125 if (level >= AMD_DBGAPI_LOG_LEVEL_TRACE) 2126 { 2127 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%ps", 2128 styled_string (trace_style.style (), message)); 2129 return; 2130 } 2131 2132 debug_prefixed_printf (amd_dbgapi_lib_debug_module (), nullptr, "%s", 2133 message); 2134} 2135 2136/* Callbacks passed to amd_dbgapi_initialize. */ 2137 2138static amd_dbgapi_callbacks_t dbgapi_callbacks = { 2139 .allocate_memory = malloc, 2140 .deallocate_memory = free, 2141 .get_os_pid = amd_dbgapi_get_os_pid_callback, 2142 .insert_breakpoint = amd_dbgapi_insert_breakpoint_callback, 2143 .remove_breakpoint = amd_dbgapi_remove_breakpoint_callback, 2144 .log_message = amd_dbgapi_log_message_callback, 2145}; 2146 2147void 2148amd_dbgapi_target::close () 2149{ 2150 if (amd_dbgapi_async_event_handler != nullptr) 2151 delete_async_event_handler (&amd_dbgapi_async_event_handler); 2152} 2153 2154/* Callback for "show amdgpu precise-memory". */ 2155 2156static void 2157show_precise_memory_mode (struct ui_file *file, int from_tty, 2158 struct cmd_list_element *c, const char *value) 2159{ 2160 amd_dbgapi_inferior_info *info 2161 = get_amd_dbgapi_inferior_info (current_inferior ()); 2162 2163 gdb_printf (file, 2164 _("AMDGPU precise memory access reporting is %s " 2165 "(currently %s).\n"), 2166 info->precise_memory.requested ? "on" : "off", 2167 info->precise_memory.enabled ? "enabled" : "disabled"); 2168} 2169 2170/* Callback for "set amdgpu precise-memory". */ 2171 2172static void 2173set_precise_memory_mode (bool value) 2174{ 2175 amd_dbgapi_inferior_info *info 2176 = get_amd_dbgapi_inferior_info (current_inferior ()); 2177 2178 info->precise_memory.requested = value; 2179 2180 if (info->process_id != AMD_DBGAPI_PROCESS_NONE) 2181 set_process_memory_precision (*info); 2182} 2183 2184/* Return whether precise-memory is requested for the current inferior. */ 2185 2186static bool 2187get_precise_memory_mode () 2188{ 2189 amd_dbgapi_inferior_info *info 2190 = get_amd_dbgapi_inferior_info (current_inferior ()); 2191 2192 return info->precise_memory.requested; 2193} 2194 2195/* List of set/show amdgpu commands. */ 2196struct cmd_list_element *set_amdgpu_list; 2197struct cmd_list_element *show_amdgpu_list; 2198 2199/* List of set/show debug amd-dbgapi-lib commands. */ 2200struct cmd_list_element *set_debug_amd_dbgapi_lib_list; 2201struct cmd_list_element *show_debug_amd_dbgapi_lib_list; 2202 2203/* Mapping from amd-dbgapi log level enum values to text. */ 2204 2205static constexpr const char *debug_amd_dbgapi_lib_log_level_enums[] = 2206{ 2207 /* [AMD_DBGAPI_LOG_LEVEL_NONE] = */ "off", 2208 /* [AMD_DBGAPI_LOG_LEVEL_FATAL_ERROR] = */ "error", 2209 /* [AMD_DBGAPI_LOG_LEVEL_WARNING] = */ "warning", 2210 /* [AMD_DBGAPI_LOG_LEVEL_INFO] = */ "info", 2211 /* [AMD_DBGAPI_LOG_LEVEL_TRACE] = */ "trace", 2212 /* [AMD_DBGAPI_LOG_LEVEL_VERBOSE] = */ "verbose", 2213 nullptr 2214}; 2215 2216/* Storage for "set debug amd-dbgapi-lib log-level". */ 2217 2218static const char *debug_amd_dbgapi_lib_log_level 2219 = debug_amd_dbgapi_lib_log_level_enums[AMD_DBGAPI_LOG_LEVEL_WARNING]; 2220 2221/* Get the amd-dbgapi library log level requested by the user. */ 2222 2223static amd_dbgapi_log_level_t 2224get_debug_amd_dbgapi_lib_log_level () 2225{ 2226 for (size_t pos = 0; 2227 debug_amd_dbgapi_lib_log_level_enums[pos] != nullptr; 2228 ++pos) 2229 if (debug_amd_dbgapi_lib_log_level 2230 == debug_amd_dbgapi_lib_log_level_enums[pos]) 2231 return static_cast<amd_dbgapi_log_level_t> (pos); 2232 2233 gdb_assert_not_reached ("invalid log level"); 2234} 2235 2236/* Callback for "set debug amd-dbgapi log-level", apply the selected log level 2237 to the library. */ 2238 2239static void 2240set_debug_amd_dbgapi_lib_log_level (const char *args, int from_tty, 2241 struct cmd_list_element *c) 2242{ 2243 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ()); 2244} 2245 2246/* Callback for "show debug amd-dbgapi log-level". */ 2247 2248static void 2249show_debug_amd_dbgapi_lib_log_level (struct ui_file *file, int from_tty, 2250 struct cmd_list_element *c, 2251 const char *value) 2252{ 2253 gdb_printf (file, _("The amd-dbgapi library log level is %s.\n"), value); 2254} 2255 2256/* If the amd-dbgapi library is not attached to any process, finalize and 2257 re-initialize it so that the handle ID numbers will all start from the 2258 beginning again. This is only for convenience, not essential. */ 2259 2260static void 2261maybe_reset_amd_dbgapi () 2262{ 2263 for (inferior *inf : all_non_exited_inferiors ()) 2264 { 2265 amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf); 2266 2267 if (info->process_id != AMD_DBGAPI_PROCESS_NONE) 2268 return; 2269 } 2270 2271 amd_dbgapi_status_t status = amd_dbgapi_finalize (); 2272 if (status != AMD_DBGAPI_STATUS_SUCCESS) 2273 error (_("amd-dbgapi failed to finalize (%s)"), 2274 get_status_string (status)); 2275 2276 status = amd_dbgapi_initialize (&dbgapi_callbacks); 2277 if (status != AMD_DBGAPI_STATUS_SUCCESS) 2278 error (_("amd-dbgapi failed to initialize (%s)"), 2279 get_status_string (status)); 2280} 2281 2282extern initialize_file_ftype _initialize_amd_dbgapi_target; 2283 2284void 2285_initialize_amd_dbgapi_target () 2286{ 2287 /* Make sure the loaded debugger library version is greater than or equal to 2288 the one used to build GDB. */ 2289 uint32_t major, minor, patch; 2290 amd_dbgapi_get_version (&major, &minor, &patch); 2291 if (major != AMD_DBGAPI_VERSION_MAJOR || minor < AMD_DBGAPI_VERSION_MINOR) 2292 error (_("amd-dbgapi library version mismatch, got %d.%d.%d, need %d.%d+"), 2293 major, minor, patch, AMD_DBGAPI_VERSION_MAJOR, 2294 AMD_DBGAPI_VERSION_MINOR); 2295 2296 /* Initialize the AMD Debugger API. */ 2297 amd_dbgapi_status_t status = amd_dbgapi_initialize (&dbgapi_callbacks); 2298 if (status != AMD_DBGAPI_STATUS_SUCCESS) 2299 error (_("amd-dbgapi failed to initialize (%s)"), 2300 get_status_string (status)); 2301 2302 /* Set the initial log level. */ 2303 amd_dbgapi_set_log_level (get_debug_amd_dbgapi_lib_log_level ()); 2304 2305 /* Install observers. */ 2306 gdb::observers::inferior_cloned.attach (amd_dbgapi_target_inferior_cloned, 2307 "amd-dbgapi"); 2308 gdb::observers::signal_received.attach (amd_dbgapi_target_signal_received, 2309 "amd-dbgapi"); 2310 gdb::observers::inferior_created.attach 2311 (amd_dbgapi_target_inferior_created, 2312 amd_dbgapi_target_inferior_created_observer_token, "amd-dbgapi"); 2313 gdb::observers::inferior_execd.attach (amd_dbgapi_inferior_execd, "amd-dbgapi"); 2314 gdb::observers::inferior_forked.attach (amd_dbgapi_inferior_forked, "amd-dbgapi"); 2315 gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi"); 2316 gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi"); 2317 gdb::observers::thread_deleted.attach (amd_dbgapi_thread_deleted, "amd-dbgapi"); 2318 2319 add_basic_prefix_cmd ("amdgpu", no_class, 2320 _("Generic command for setting amdgpu flags."), 2321 &set_amdgpu_list, 0, &setlist); 2322 2323 add_show_prefix_cmd ("amdgpu", no_class, 2324 _("Generic command for showing amdgpu flags."), 2325 &show_amdgpu_list, 0, &showlist); 2326 2327 add_setshow_boolean_cmd ("precise-memory", no_class, 2328 _("Set precise-memory mode."), 2329 _("Show precise-memory mode."), _("\ 2330If on, precise memory reporting is enabled if/when the inferior is running.\n\ 2331If off (default), precise memory reporting is disabled."), 2332 set_precise_memory_mode, 2333 get_precise_memory_mode, 2334 show_precise_memory_mode, 2335 &set_amdgpu_list, &show_amdgpu_list); 2336 2337 add_basic_prefix_cmd ("amd-dbgapi-lib", no_class, 2338 _("Generic command for setting amd-dbgapi library " 2339 "debugging flags."), 2340 &set_debug_amd_dbgapi_lib_list, 0, &setdebuglist); 2341 2342 add_show_prefix_cmd ("amd-dbgapi-lib", no_class, 2343 _("Generic command for showing amd-dbgapi library " 2344 "debugging flags."), 2345 &show_debug_amd_dbgapi_lib_list, 0, &showdebuglist); 2346 2347 add_setshow_enum_cmd ("log-level", class_maintenance, 2348 debug_amd_dbgapi_lib_log_level_enums, 2349 &debug_amd_dbgapi_lib_log_level, 2350 _("Set the amd-dbgapi library log level."), 2351 _("Show the amd-dbgapi library log level."), 2352 _("off == no logging is enabled\n" 2353 "error == fatal errors are reported\n" 2354 "warning == fatal errors and warnings are reported\n" 2355 "info == fatal errors, warnings, and info " 2356 "messages are reported\n" 2357 "trace == fatal errors, warnings, info, and " 2358 "API tracing messages are reported\n" 2359 "verbose == all messages are reported"), 2360 set_debug_amd_dbgapi_lib_log_level, 2361 show_debug_amd_dbgapi_lib_log_level, 2362 &set_debug_amd_dbgapi_lib_list, 2363 &show_debug_amd_dbgapi_lib_list); 2364 2365 add_setshow_boolean_cmd ("amd-dbgapi", class_maintenance, 2366 &debug_amd_dbgapi, 2367 _("Set debugging of amd-dbgapi target."), 2368 _("Show debugging of amd-dbgapi target."), 2369 _("\ 2370When on, print debug messages relating to the amd-dbgapi target."), 2371 nullptr, nullptr, 2372 &setdebuglist, &showdebuglist); 2373} 2374