# Copyright (C) 2020-2024 Free Software Foundation, Inc. # Copyright (C) 2020-2024 Advanced Micro Devices, Inc. All rights reserved. # This file is part of GDB. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Test stepping over breakpoints using displaced stepping. Some instructions, # for example s_getpc, s_swappc, s_setpc, etc... are simulated by the debugger # API library, so make sure the instruction behaves as expected. load_lib rocm.exp require allow_hip_tests standard_testfile .cpp if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug hip}]} { return -1 } proc set_regs { regs val test } { global gdb_prompt set all_passed 1 foreach reg ${regs} { set one_passed 0 set cmd_re [string_to_regexp "set \$${reg} = ${val}"] gdb_test_multiple "set \$${reg} = ${val}" $test { -re "^$cmd_re\r\n$gdb_prompt $" { set one_passed 1 } } if {!$one_passed} { set all_passed 0 break } } if {$all_passed} { pass $test } } with_rocm_gpu_lock { gdb_test_no_output "set displaced-stepping on" if ![runto_main] { fail "can't run to main" return -1 } gdb_breakpoint "kernel" temporary allow-pending qualified gdb_continue_to_breakpoint "kernel" gdb_breakpoint "GETPC" gdb_breakpoint "SWAPPC" gdb_breakpoint "CALL" gdb_breakpoint "SETPC" gdb_breakpoint "END_OF_COMMON_TESTS" gdb_continue_to_breakpoint "getpc" with_test_prefix "getpc" { gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_get_?pc_(i|b)64\[ \t\]+s\\\[4:5\\\]" set_regs { "s4" "s5" } 0 "clear s4,s5" # sample output: 0x00007ffff609140c 36 asm(" .globl GETPC \n\t" gdb_test "stepi" "$::hex\\s+$::decimal\\s+asm\\\(\\\".*" "simulate" gdb_test "p ((uint64_t)\$s5<<32 | (uint32_t)\$s4) == \$pc" \ " = true" "check s4,s5" gdb_continue_to_breakpoint "swappc" } with_test_prefix "swappc" { gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_swap_?pc_(i|b)64\[ \t\]+s\\\[4:5\\\], s\\\[6:7\\\]" # sample output: Thread 7 ... hit Breakpoint 5, ... in kernel gdb_test "stepi" "Thread $::decimal.*hit Breakpoint $::decimal.*in kernel.*" \ "simulate" gdb_test "p ((uint64_t)\$s5<<32 | (uint32_t)\$s4) == (\$pc - 4)" \ " = true" "check s4,s5" } with_test_prefix "call" { gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_call_(i|b)64\[ \t\]+s\\\[4:5\\\], 1" gdb_test "stepi" "$::hex\\s+$::decimal\\s+asm\\\(\\\".*" "simulate" gdb_test "p ((uint64_t)\$s5<<32 | (uint32_t)\$s4) == (\$pc - 4)" \ " = true" "check s4,s5" gdb_continue_to_breakpoint "setpc" } with_test_prefix "setpc" { gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_set_?pc_(i|b)64\[ \t\]+s\\\[6:7\\\]" gdb_test "stepi" "Thread $::decimal.*hit Breakpoint $::decimal.*in kernel.*" \ "simulate" gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_nop\[ \t\]+1" \ "reach end of common tests" } set arch 0x[get_current_gpu_arch] if {$arch >= 0x1250} { gdb_breakpoint "ADD_PC_PLUS_POS_IMM" gdb_breakpoint "ADD_PC_PLUS_NEG_IMM" gdb_breakpoint "ADD_PC_PLUS_POS_REGVAL" gdb_breakpoint "ADD_PC_PLUS_NEG_REGVAL" gdb_continue_to_breakpoint "add_pc_i64 +" with_test_prefix "add_pc_i64 +" { gdb_test "p \$s8" \ " = 1" "test number in s8" gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_add_pc_i64\[ \t\]+\[^s\].*" \ "s_add_pc_i64 with an immediate value" # sample output: 0x00007ffff6091568 66 asm(".if (.amdgcn.gfx_... gdb_test "stepi" "$::hex\\s+$::decimal\\s+asm\\\(\\\".*" "simulate" gdb_continue_to_breakpoint "add_pc_i64 -" } with_test_prefix "add_pc_i64 -" { gdb_test "p \$s8" \ " = 2" "test number in s8" gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_add_pc_i64\[ \t\]+\[^s\].*" \ "s_add_pc_i64 with another immediate value" gdb_test "stepi" "$::hex\\s+$::decimal\\s+asm\\\(\\\".*" "simulate" gdb_continue_to_breakpoint "add_pc_i64 -" } with_test_prefix "add_pc_i64 -" { gdb_test "p \$s8" \ " = 3" "test number in s8" gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_add_pc_i64\[ \t\]+s\\\[4:5\\\]" \ "s_add_pc_i64 with a register pair" gdb_test "stepi" "$::hex\\s+$::decimal\\s+asm\\\(\\\".*" "simulate" gdb_continue_to_breakpoint "add_pc_i64 +" } with_test_prefix "add_pc_i64 +" { gdb_test "p \$s8" \ " = 4" "test number in s8" gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_add_pc_i64\[ \t\]+s\\\[6:7\\\]" \ "s_add_pc_i64 with another register pair" gdb_test "stepi" "$::hex\\s+$::decimal\\s+asm\\\(\\\".*" "simulate" gdb_test "x/i \$pc" \ "=> $::hex <\[^\r\n\]*>:\[ \t\]+s_nop\[ \t\]+2" \ "reach end of s_add_pc_i64 test" } } }