# Copyright (C) 2022-2024 Free Software Foundation, Inc. # Copyright (C) 2022-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 . # Code running on a GPU can be loaded directly from a memory buffer. In such # situation no actual file is ever used. To support this, GDB accesses the # objfile directly from the buffer in the memory of the debuggee. However, # some programs might be tempted to dispose of (or reuse) the memory buffer # containing the objfile's image as soon as they transferred the machine code # to the device. If they do that, they might destroy debug information GDB # requires, without GDB being aware of it. This can lead to crashes if GDB # tries to decode random data. # # To prevent that, GDB makes a copy of the entire objfile when it first # encounters it. # # This test checks that GDB can handle a program which disposes of its objfile # buffer while the associated code is still running on the device. # # In addition, it forces GDB to reload the objfile after it has been # corrupted, to make sure GDB won't crash if it attaches to a running # program and encounters already-corrupted images. # # Test different variants of corrupted images: # # - fully zeroed-out buffer # - corrupted section offset in ELF header load_lib rocm.exp require allow_hip_tests standard_testfile .cpp set hipmodule_path [standard_output_file ${testfile}.hipfb] if { [gdb_compile $srcdir/$subdir/$srcfile \ $hipmodule_path object \ { debug hip additional_flags=--cuda-device-only } ] != "" } { return -1 } if { [build_executable "failed to prepare" ${testfile} ${srcfile} \ {debug hip}] } { return -1 } with_rocm_gpu_lock { foreach_with_prefix mode {zero shoff} { clean_restart $::binfile gdb_test_no_output "set args $mode $hipmodule_path" "set args" runto "printId" allow-pending # Frame #1 normally looks like "#1 0x... in kernel () at ...", # but under -O1/-O2/-O3 the return address can fall on the # entry instruction of kernel(), in which case GDB omits the # leading "0x... in " prefix and prints just "#1 kernel () at # ...". Accept either form. gdb_test "bt" \ [multi_line \ "#0\[ \t\]*printId \\(\\) at \[^\r\n\]+" \ "#1\[ \t\]*(${::hex} in )?kernel \\(\\) at \[^\r\n\]+"] # Now force GDB to reload the shared library, to make sure it # doesn't crash when it finds the corrupted code object image. # # Depending on the runtime version, GDB might be given the address # of either 1) the original code object given to the runtime, or 2) a # copy of the original code done by the runtime during load. # # In case #1, the client has scrambled the memory after the code object # has been loaded, making it an invalid ELF. We need to make sure that # reloading it does not cause GDB to crash. In case #2, we just # reload the same binary image, which will work fine. set any "\[^\r\n\]" gdb_test_no_output "nosharedlibrary" gdb_test "info shared" "memory://.*" } }