CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
333 lines
9.9 KiB
Plaintext
333 lines
9.9 KiB
Plaintext
# Copyright (C) 2026 Free Software Foundation, Inc.
|
|
# Copyright (C) 2026 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 <http://www.gnu.org/licenses/>.
|
|
|
|
# Test catching HIP's API errors:
|
|
#
|
|
# 1. The executable is loaded and started.
|
|
# 2. The executable is loaded but not started.
|
|
# 3. There's no executable set yet.
|
|
# 4. Two API errors are returned and caught.
|
|
# 5. Implicit (stub) execution in the form of "kernel<<<...>>>();"
|
|
# 6. Conditional catch of 1 error, using $_hiperr, while there are 2 errors.
|
|
# 7. Temporary catch of the first error, while there are 2 errors.
|
|
# 8. $_hiperr is printed correctly when debug symbols are available.
|
|
# 9. $_hiperr is printed correctly without debug symbols.
|
|
# This one checks if "catch hiperr" works without debug symbols as well.
|
|
|
|
load_lib rocm.exp
|
|
|
|
require allow_hip_tests
|
|
|
|
standard_testfile .cpp
|
|
|
|
if {[prepare_for_testing "failed to prepare debug version of ${testfile}" \
|
|
${::testfile}.dbg ${::srcfile} {debug hip}]} {
|
|
return -1
|
|
}
|
|
|
|
if {[prepare_for_testing "failed to prepare non-debug version of ${testfile}" \
|
|
${::testfile}.nodbg ${::srcfile} {hip}]} {
|
|
return -1
|
|
}
|
|
|
|
# Reference error parameters for HIP API calls:
|
|
# hipSetDevice (...)
|
|
# hipGetDevice (...)
|
|
# hipLaunchKernel (...)
|
|
#
|
|
# See init_reference_hip_errors.
|
|
|
|
set hip_set_device_err_no ""
|
|
set hip_set_device_err_name ""
|
|
set hip_set_device_err_str ""
|
|
set hip_get_device_err_no ""
|
|
set hip_get_device_err_name ""
|
|
set hip_get_device_err_str ""
|
|
set hip_launch_kernel_err_no ""
|
|
set hip_launch_kernel_err_name ""
|
|
set hip_launch_kernel_err_str ""
|
|
|
|
# Retrieve the value of EXP in the inferior, as a string value
|
|
# (using "print /s"). DEFAULT is used as fallback if print fails.
|
|
|
|
proc get_string_valueof {exp default} {
|
|
set val ${default}
|
|
gdb_test_multiple "print /s ${exp}" "get string value of \"${exp}\"" {
|
|
-re -wrap "^${::valnum_re} = $::hex \"(\[^\"\]*)\"" {
|
|
set val $expect_out(1,string)
|
|
pass $gdb_test_name
|
|
}
|
|
}
|
|
return ${val}
|
|
}
|
|
|
|
# Get the reference values from the program (which is run with "ref" argument)
|
|
|
|
proc init_reference_hip_errors {} {
|
|
foreach func {set_device get_device launch_kernel} {
|
|
set ::hip_${func}_err_no [get_integer_valueof "hip_${func}_err.no" bad]
|
|
gdb_assert {[set ::hip_${func}_err_no] != "bad"} \
|
|
"hip_${func}_err_no initialized"
|
|
|
|
set ::hip_${func}_err_name [get_string_valueof "hip_${func}_err.name" bad]
|
|
gdb_assert {[set ::hip_${func}_err_name] != "bad"} \
|
|
"hip_${func}_err_name initialized"
|
|
|
|
set ::hip_${func}_err_str [get_string_valueof "hip_${func}_err.str" bad]
|
|
gdb_assert {[set ::hip_${func}_err_str] != "bad"} \
|
|
"hip_${func}_err_str initialized"
|
|
}
|
|
}
|
|
|
|
# Set a hiperr catchpoint and check if it set accordingly. If TEMP is
|
|
# true, then a temporary version (tcatch) is used. Differences between the
|
|
# permanent and temporary are:
|
|
#
|
|
# catch hiperr vs. tcatch hiperr
|
|
# Catchpoint <number> ... vs. Temporary catchpoint <number> ...
|
|
# info breakpoints
|
|
# <number> catchpoint keep ... vs. <number> catchpoint del ...
|
|
|
|
proc catch_hiperr {{temp false}} {
|
|
if {!$temp} {
|
|
set cmd "catch hiperr"
|
|
set type "Catchpoint"
|
|
set catch_test_name "set catchpoint"
|
|
set disp "keep"
|
|
} else {
|
|
set cmd "tcatch hiperr"
|
|
set type "Temporary catchpoint"
|
|
set catch_test_name "set temporary catchpoint"
|
|
set disp "del"
|
|
}
|
|
|
|
gdb_test "$cmd" "$type $::decimal \\(HIP error\\)" "$catch_test_name"
|
|
|
|
gdb_test "info break" \
|
|
"$::decimal\[ \t\]+catchpoint\[ \t\]+$disp\[ \t\]+y\[ \t\]+catch hiperr" \
|
|
"check breakpoints"
|
|
}
|
|
|
|
# Set a conditional "catch hiperr" that checks the error number is NUMBER.
|
|
|
|
proc catch_hiperr_cond {number} {
|
|
gdb_test "catch hiperr if \$_hiperr == $number" \
|
|
"Catchpoint $::decimal \\(HIP error\\)" \
|
|
"set conditional catchpoint"
|
|
}
|
|
|
|
# Execute CMD (e.g. "run" or "cont") and look for two lines
|
|
# in the output:
|
|
#
|
|
# Thread 1 "hip" hit Catchpoint 1 (HIP error)
|
|
# (...) hipErrorInvalidDevice (101): invalid device ordinal
|
|
# ^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^^^^^^
|
|
# NAME NUMBER STR
|
|
#
|
|
# As the last step, also check that $_hiperr is equal to NUMBER.
|
|
# If TEMP is true, the catchpoint is temporary.
|
|
|
|
proc check_hiperr_is_caught {cmd number name str {temp false}} {
|
|
if {!$temp} {
|
|
set type "Catchpoint"
|
|
} else {
|
|
set type "Temporary catchpoint"
|
|
}
|
|
set hit_line "Thread $::decimal .* hit $type $::decimal \\(HIP error\\)"
|
|
set err_line "HIP API call failed with error $name \\($number\\): $str\r\n.*"
|
|
|
|
gdb_test "$cmd" "${hit_line}\r\n${err_line}" "caught $name"
|
|
gdb_test "p/d \$_hiperr" "= $number" "\$_hiperr must be $number"
|
|
}
|
|
|
|
# Execute CMD and check the reported hiperr catchpoint against the
|
|
# reference values for hipSetDevice (...). TEMP, if true, indicates
|
|
# the catchpoint must be a temporary one.
|
|
|
|
proc check_hip_set_device_err {cmd {temp false}} {
|
|
check_hiperr_is_caught $cmd \
|
|
$::hip_set_device_err_no \
|
|
$::hip_set_device_err_name \
|
|
$::hip_set_device_err_str \
|
|
$temp
|
|
}
|
|
|
|
# Execute CMD and check the reported hiperr catchpoint against the
|
|
# reference values for hipGetDevice (...).
|
|
|
|
proc check_hip_get_device_err {cmd} {
|
|
check_hiperr_is_caught $cmd \
|
|
$::hip_get_device_err_no \
|
|
$::hip_get_device_err_name \
|
|
$::hip_get_device_err_str
|
|
}
|
|
|
|
# Execute CMD and check the reported hiperr catchpoint against the
|
|
# reference values for kernel<<<...>>> ().
|
|
|
|
proc check_hip_launch_kernel_err {cmd} {
|
|
check_hiperr_is_caught $cmd \
|
|
$::hip_launch_kernel_err_no \
|
|
$::hip_launch_kernel_err_name \
|
|
$::hip_launch_kernel_err_str
|
|
}
|
|
|
|
proc do_test {} {
|
|
with_rocm_gpu_lock {
|
|
|
|
clean_restart ${::testfile}.dbg
|
|
if {![runto_main]} {
|
|
return
|
|
}
|
|
gdb_test_multiple "info symbol __hipOnError" \
|
|
"check if __hipOnError symbol exists" {
|
|
-re -wrap "^__hipOnError in section .text of .*" {
|
|
pass $gdb_test_name
|
|
}
|
|
-re -wrap ".*" {
|
|
unsupported "no __hipOnError symbol was found"
|
|
return
|
|
}
|
|
}
|
|
|
|
# Let all the errors occur and their values be recorded by the program.
|
|
with_test_prefix "getting reference values" {
|
|
clean_restart ${::testfile}.dbg
|
|
gdb_test_no_output "set args ref"
|
|
if {![runto [gdb_get_line_number \
|
|
"Break after reference initialization"]]} {
|
|
return
|
|
}
|
|
init_reference_hip_errors
|
|
}
|
|
|
|
with_test_prefix "after starting" {
|
|
clean_restart ${::testfile}.dbg
|
|
gdb_test_no_output "set args one"
|
|
runto_main
|
|
catch_hiperr
|
|
check_hip_set_device_err "cont"
|
|
}
|
|
|
|
with_test_prefix "after loading" {
|
|
clean_restart ${::testfile}.dbg
|
|
gdb_test_no_output "set args one"
|
|
catch_hiperr
|
|
check_hip_set_device_err "run"
|
|
}
|
|
|
|
with_test_prefix "before loading" {
|
|
clean_restart
|
|
catch_hiperr
|
|
gdb_load ${::binfile}.dbg
|
|
gdb_test_no_output "set args one"
|
|
check_hip_set_device_err "run"
|
|
}
|
|
|
|
with_test_prefix "two catchpoints" {
|
|
clean_restart ${::testfile}.dbg
|
|
gdb_test_no_output "set args two"
|
|
catch_hiperr
|
|
check_hip_set_device_err "run"
|
|
check_hip_get_device_err "cont"
|
|
}
|
|
|
|
with_test_prefix "stub kernel launch" {
|
|
clean_restart ${::testfile}.dbg
|
|
gdb_test_no_output "set args launch"
|
|
catch_hiperr
|
|
check_hip_launch_kernel_err "run"
|
|
gdb_test "backtrace" \
|
|
".*__hipOnError.*hipLaunchKernel.*__device_stub__kernel.*" \
|
|
"call stack"
|
|
}
|
|
|
|
with_test_prefix "conditional catchpoint" {
|
|
clean_restart ${::testfile}.dbg
|
|
gdb_test_no_output "set args two"
|
|
catch_hiperr_cond $::hip_get_device_err_no
|
|
check_hip_get_device_err "run"
|
|
}
|
|
|
|
with_test_prefix "temporary catchpoint" {
|
|
clean_restart ${::testfile}.dbg
|
|
gdb_test_no_output "set args two"
|
|
catch_hiperr true
|
|
check_hip_set_device_err "run" true
|
|
gdb_test "continue" \
|
|
"Inferior $::decimal .* exited normally.*" \
|
|
"no more catches"
|
|
}
|
|
|
|
# With the debug symbols (with "hipError_t" type), $_hiperr
|
|
# must be printed as an enum like hipErrorSomething.
|
|
with_test_prefix "prints of \$_hiperr with debug symbols" {
|
|
clean_restart ${::testfile}.dbg
|
|
gdb_test_no_output "set args one"
|
|
runto_main
|
|
# Without any error, "$_hiperr" must be "void".
|
|
gdb_test "p \$_hiperr" " = void" "not in scope"
|
|
|
|
# Check "hipError_t" type is known.
|
|
set type_found false
|
|
gdb_test_multiple "info types hipError_t" \
|
|
"check if hipError_t type exists" {
|
|
-re ".*File \[^\r\n\]+:\r\n" {
|
|
set type_found true
|
|
exp_continue
|
|
}
|
|
-re "$::gdb_prompt $" {
|
|
gdb_assert {$type_found} $gdb_test_name
|
|
}
|
|
}
|
|
|
|
catch_hiperr
|
|
gdb_test "cont" ".*call failed.*$::hip_set_device_err_name.*" \
|
|
"caught $::hip_set_device_err_name"
|
|
gdb_test "p \$_hiperr" " = $::hip_set_device_err_name" \
|
|
"print as $::hip_set_device_err_name"
|
|
}
|
|
|
|
# Without the debug symbols (no "hipError_t" type),
|
|
# $_hiperr must be printed as a number.
|
|
with_test_prefix "print \$_hiperr without debug symbols" {
|
|
clean_restart ${::testfile}.nodbg
|
|
gdb_test_no_output "set args launch"
|
|
runto_main
|
|
|
|
# Check "hipError_t" type is not detected.
|
|
set type_found true
|
|
gdb_test_multiple "info types hipError_t" \
|
|
"check hipError_t type existence" {
|
|
-re -wrap "\r\nAll types matching regular expression \"hipError_t\":" {
|
|
set type_found false
|
|
pass $gdb_test_name
|
|
}
|
|
}
|
|
gdb_assert {!$type_found} "there must be no hipError_t"
|
|
|
|
catch_hiperr
|
|
check_hip_launch_kernel_err "cont"
|
|
gdb_test "p \$_hiperr" " = $::hip_launch_kernel_err_no" \
|
|
"print as $::hip_launch_kernel_err_no"
|
|
}
|
|
}
|
|
}
|
|
|
|
do_test
|