From dae0e0bde7985a29b1e7bb8df05518733890459d Mon Sep 17 00:00:00 2001 From: Ben Ashbaugh Date: Sat, 18 Apr 2026 17:34:37 +0200 Subject: [PATCH 1/3] add a control to omit the compile count --- docs/controls.md | 4 + intercept/src/controls.h | 1 + intercept/src/intercept.cpp | 166 ++++-------------------------------- intercept/src/intercept.h | 98 +++++++++++++++++---- 4 files changed, 102 insertions(+), 167 deletions(-) diff --git a/docs/controls.md b/docs/controls.md index c8a53f69..0a8ec381 100644 --- a/docs/controls.md +++ b/docs/controls.md @@ -443,6 +443,10 @@ If set to a nonzero value, the Intercept Layer for OpenCL Applications will only If set to a nonzero value, the Intercept Layer for OpenCL Applications will omit the program number from dumped file names and hash tracking. This can produce deterministic results even if programs are built in a non-deterministic order (say, by multiple threads). +##### `OmitCompileCount` (bool) + +If set to a nonzero value, the Intercept Layer for OpenCL Applications will omit the compile count from dumped file names and hash tracking. This can reduce the number of files that are dumped if the same program is compiled multiple times. + ##### `SimpleDumpProgramSource` (bool) If set to a nonzero value, the Intercept Layer for OpenCL Applications will dump the last string(s) passed to clCreateProgramWithSource() to the file kernel.cl, and the last program options passed to clBuildProgram() to the file kernel.txt. These files will be dumped to the application's working directory. If an application fails to compile a program and exits the program immediately after detecting a compile failure SimpleDumpProgram may be all that is needed to identify the program and program options that are failing to compile. diff --git a/intercept/src/controls.h b/intercept/src/controls.h index 8a66ba03..0a656821 100644 --- a/intercept/src/controls.h +++ b/intercept/src/controls.h @@ -97,6 +97,7 @@ CLI_CONTROL( bool, PerformanceTimingConditional, false, "If s CLI_CONTROL_SEPARATOR( Controls for Dumping and Injecting Programs and Build Options: ) CLI_CONTROL( bool, OmitProgramNumber, false, "If set to a nonzero value, the Intercept Layer for OpenCL Applications will omit the program number from dumped file names and hash tracking. This can produce deterministic results even if programs are built in a non-deterministic order (say, by multiple threads)." ) +CLI_CONTROL( bool, OmitCompileCount, false, "If set to a nonzero value, the Intercept Layer for OpenCL Applications will omit the compile count from dumped file names and hash tracking. This can reduce the number of files that are dumped if the same program is compiled multiple times." ) CLI_CONTROL( bool, SimpleDumpProgramSource, false, "If set to a nonzero value, the Intercept Layer for OpenCL Applications will dump the last string(s) passed to clCreateProgramWithSource() to the file kernel.cl, and the last program options passed to clBuildProgram() to the file kernel.txt. These files will be dumped to the application's working directory. If an application fails to compile a program and exits the program immediately after detecting a compile failure SimpleDumpProgram may be all that is needed to identify the program and program options that are failing to compile." ) CLI_CONTROL( bool, DumpProgramSourceScript, false, "If set to a nonzero value, the Intercept Layer for OpenCL Applications will dump every string passed to clCreateProgramWithSource() to its own file. The directory names and file names for the dumped files match the directory names and file names expected by a modified OpenCL conformance test script to capture kernels. This setting overrides SimpleDumpProgramSource, and if it is set to a nonzero value then the value of SimpleDumpProgramSource is ignored." ) CLI_CONTROL( bool, DumpProgramSource, false, "If set to a nonzero value, the Intercept Layer for OpenCL Applications will dump every string passed to clCreateProgramWithSource() to its own file. The file name will have the form \"CLI___source.cl\". Program options will be dumped to the same directory with the file name \"CLI______options.txt\", where API is an empty string for clBuildProgram(), \"compile\" for clCompileProgram(), and \"link\" for clLinkProgram(). This setting can be used for information purposes to see all kernels that are used by an application or to dump programs for program injection. This setting overrides DumpProgramSourceScript and SimpleDumpProgramSource, and if it is set to a nozero value then the values of DumpProgramSourceScript and SimpleDumpProgramSource will be ignored." ) diff --git a/intercept/src/intercept.cpp b/intercept/src/intercept.cpp index 82b9a144..3d50d54d 100644 --- a/intercept/src/intercept.cpp +++ b/intercept/src/intercept.cpp @@ -3308,27 +3308,11 @@ void CLIntercept::logBuild( errorCode == CL_SUCCESS ) { const SProgramInfo& programInfo = m_ProgramInfoMap[ program ]; - - char numberString[256] = ""; - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( numberString, 256, "%08X_%04u_%08X", - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( numberString, 256, "%04u_%08X_%04u_%08X", - programInfo.ProgramNumber, - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } + std::string hashString = getProgramInfoHashString( programInfo ); logf( "Build Info for program %p (%s) for %u device(s):\n", program, - numberString, + hashString.c_str(), numDevices ); float buildTimeMS = buildDuration.count(); @@ -5364,26 +5348,10 @@ void CLIntercept::dumpProgramOptions( // CLI____ // Leave off the extension for now. { - char numberString[256] = ""; - - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( numberString, 256, "%08X_%04u_%08X", - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( numberString, 256, "%04u_%08X_%04u_%08X", - programInfo.ProgramNumber, - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } + std::string hashString = getProgramInfoHashString( programInfo ); fileName += "/CLI_"; - fileName += numberString; + fileName += hashString; } // Now make directories as appropriate. @@ -5433,26 +5401,10 @@ void CLIntercept::dumpProgramBuildLog( // CLI____ // Leave off the extension for now. { - char numberString[256] = ""; - - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( numberString, 256, "%08X_%04u_%08X", - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( numberString, 256, "%04u_%08X_%04u_%08X", - programInfo.ProgramNumber, - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } + std::string hashString = getProgramInfoHashString( programInfo ); fileName += "/CLI_"; - fileName += numberString; + fileName += hashString; } // Now make directories as appropriate. { @@ -10390,26 +10342,10 @@ void CLIntercept::dumpProgramBinary( // CLI____ // Leave off the extension for now. { - char numberString[256] = ""; - - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( numberString, 256, "%08X_%04u_%08X", - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( numberString, 256, "%04u_%08X_%04u_%08X", - programInfo.ProgramNumber, - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } + std::string hashString = getProgramInfoHashString( programInfo ); fileName += "/CLI_"; - fileName += numberString; + fileName += hashString; } // Now make directories as appropriate. { @@ -10630,26 +10566,10 @@ void CLIntercept::dumpKernelISABinaries( // CLI______.isabin // We'll fill in the device type and kernel name later. { - char numberString[256] = ""; - - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( numberString, 256, "%08X_%04u_%08X_", - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( numberString, 256, "%04u_%08X_%04u_%08X_", - programInfo.ProgramNumber, - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } + std::string hashString = getProgramInfoHashString( programInfo ); fileNamePrefix += "/CLI_"; - fileNamePrefix += numberString; + fileNamePrefix += hashString; } // Now make directories as appropriate. { @@ -10924,27 +10844,11 @@ void CLIntercept::autoCreateSPIRV( // Make the output file name. It will have the form: // CLI____.spv { - char numberString[256] = ""; - - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( numberString, 256, "%08X_%04u_%08X", - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( numberString, 256, "%04u_%08X_%04u_%08X", - programInfo.ProgramNumber, - (unsigned int)programInfo.ProgramHash, - programInfo.CompileCount, - (unsigned int)programInfo.OptionsHash ); - } + std::string hashString = getProgramInfoHashString( programInfo ); outputFileName = dumpDirectoryName; outputFileName += "/CLI_"; - outputFileName += numberString; + outputFileName += hashString; outputFileName += ".spv"; } @@ -14769,30 +14673,11 @@ bool CLIntercept::checkCaptureReplayKernelSkips( const cl_kernel kernel ) m_Config.CaptureReplayUniqueKernels ) { const SKernelInfo& kernelInfo = m_KernelInfoMap[ kernel ]; + std::string hashString = getKernelInfoHashString( kernelInfo ); // Note: This currently uses the long kernel name. // Should it be the short kernel name instead? - std::string key = kernelInfo.KernelName; - - { - char hashString[256] = ""; - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( hashString, 256, "(%08X_%04u_%08X)", - (unsigned int)kernelInfo.ProgramHash, - kernelInfo.CompileCount, - (unsigned int)kernelInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( hashString, 256, "(%04u_%08X_%04u_%08X)", - kernelInfo.ProgramNumber, - (unsigned int)kernelInfo.ProgramHash, - kernelInfo.CompileCount, - (unsigned int)kernelInfo.OptionsHash ); - } - key += hashString; - } + std::string key = kernelInfo.KernelName + "(" + hashString + ")"; if( m_CaptureReplaySet.find( key ) == m_CaptureReplaySet.end() ) { @@ -14912,30 +14797,11 @@ bool CLIntercept::checkAubCaptureKernelSignature( m_Config.AubCaptureUniqueKernels ) { const SKernelInfo& kernelInfo = m_KernelInfoMap[ kernel ]; + std::string hashString = getKernelInfoHashString( kernelInfo ); // Note: This currently uses the long kernel name. // Should it be the short kernel name instead? - std::string key = kernelInfo.KernelName; - - { - char hashString[256] = ""; - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( hashString, 256, "(%08X_%04u_%08X)", - (unsigned int)kernelInfo.ProgramHash, - kernelInfo.CompileCount, - (unsigned int)kernelInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( hashString, 256, "(%04u_%08X_%04u_%08X)", - kernelInfo.ProgramNumber, - (unsigned int)kernelInfo.ProgramHash, - kernelInfo.CompileCount, - (unsigned int)kernelInfo.OptionsHash ); - } - key += hashString; - } + std::string key = kernelInfo.KernelName + "(" + hashString + ")"; if( gws ) { diff --git a/intercept/src/intercept.h b/intercept/src/intercept.h index a54f1160..cf19c60c 100644 --- a/intercept/src/intercept.h +++ b/intercept/src/intercept.h @@ -1128,6 +1128,9 @@ class CLIntercept typedef std::map< cl_program, SProgramInfo > CProgramInfoMap; CProgramInfoMap m_ProgramInfoMap; + std::string getProgramInfoHashString( + const SProgramInfo& kernelInfo) const; + struct SHostTimingStats { uint64_t NumberOfCalls = 0; @@ -1227,6 +1230,9 @@ class CLIntercept typedef std::map< cl_kernel, SKernelInfo > CKernelInfoMap; CKernelInfoMap m_KernelInfoMap; + std::string getKernelInfoHashString( + const SKernelInfo& kernelInfo) const; + // This defines a mapping between the "real" kernel name and a kernel // name ID. Only kernels with names larger than a control variable // will be added to this map. @@ -3671,23 +3677,7 @@ inline std::string CLIntercept::getShortKernelNameWithHash( if( config().KernelNameHashTracking ) { const SKernelInfo& kernelInfo = m_KernelInfoMap[ kernel ]; - - char hashString[256] = ""; - if( config().OmitProgramNumber ) - { - CLI_SPRINTF( hashString, 256, "$%08X_%04u_%08X", - (unsigned int)kernelInfo.ProgramHash, - kernelInfo.CompileCount, - (unsigned int)kernelInfo.OptionsHash ); - } - else - { - CLI_SPRINTF( hashString, 256, "$%04u_%08X_%04u_%08X", - kernelInfo.ProgramNumber, - (unsigned int)kernelInfo.ProgramHash, - kernelInfo.CompileCount, - (unsigned int)kernelInfo.OptionsHash ); - } + std::string hashString = getKernelInfoHashString( kernelInfo ); name += hashString; } @@ -4022,6 +4012,80 @@ inline void CLIntercept::logCL_GLTextureDetails( cl_mem image, cl_GLenum target, #endif } +/////////////////////////////////////////////////////////////////////////////// +// +inline std::string CLIntercept::getProgramInfoHashString( + const SProgramInfo& programInfo) const +{ + char hashString[256] = ""; + if( config().OmitProgramNumber && config().OmitCompileCount ) + { + CLI_SPRINTF( hashString, 256, "%08X_%08X", + (unsigned int)programInfo.ProgramHash, + (unsigned int)programInfo.OptionsHash ); + } + else if( config().OmitProgramNumber ) + { + CLI_SPRINTF( hashString, 256, "%08X_%04u_%08X", + (unsigned int)programInfo.ProgramHash, + programInfo.CompileCount, + (unsigned int)programInfo.OptionsHash ); + } + else if( config().OmitCompileCount ) + { + CLI_SPRINTF( hashString, 256, "%04u_%08X_%08X", + programInfo.ProgramNumber, + (unsigned int)programInfo.ProgramHash, + (unsigned int)programInfo.OptionsHash ); + } + else + { + CLI_SPRINTF( hashString, 256, "%04u_%08X_%04u_%08X", + programInfo.ProgramNumber, + (unsigned int)programInfo.ProgramHash, + programInfo.CompileCount, + (unsigned int)programInfo.OptionsHash ); + } + + return hashString; +} + +inline std::string CLIntercept::getKernelInfoHashString( + const SKernelInfo& kernelInfo) const +{ + char hashString[256] = ""; + if( config().OmitProgramNumber && config().OmitCompileCount ) + { + CLI_SPRINTF( hashString, 256, "%08X_%08X", + (unsigned int)kernelInfo.ProgramHash, + (unsigned int)kernelInfo.OptionsHash ); + } + else if( config().OmitProgramNumber ) + { + CLI_SPRINTF( hashString, 256, "%08X_%04u_%08X", + (unsigned int)kernelInfo.ProgramHash, + kernelInfo.CompileCount, + (unsigned int)kernelInfo.OptionsHash ); + } + else if( config().OmitCompileCount ) + { + CLI_SPRINTF( hashString, 256, "%04u_%08X_%08X", + kernelInfo.ProgramNumber, + (unsigned int)kernelInfo.ProgramHash, + (unsigned int)kernelInfo.OptionsHash ); + } + else + { + CLI_SPRINTF( hashString, 256, "%04u_%08X_%04u_%08X", + kernelInfo.ProgramNumber, + (unsigned int)kernelInfo.ProgramHash, + kernelInfo.CompileCount, + (unsigned int)kernelInfo.OptionsHash ); + } + + return hashString; +} + /////////////////////////////////////////////////////////////////////////////// // extern CLIntercept* g_pIntercept; From 195d0a3fcb81898e9283563b11acd5bc69cc67f5 Mon Sep 17 00:00:00 2001 From: Ben Ashbaugh Date: Wed, 22 Apr 2026 07:59:20 -0700 Subject: [PATCH 2/3] handle more file name candidtes without the compile count --- intercept/src/intercept.cpp | 358 +++++++++++------------------------- 1 file changed, 112 insertions(+), 246 deletions(-) diff --git a/intercept/src/intercept.cpp b/intercept/src/intercept.cpp index 3d50d54d..e6ce96f5 100644 --- a/intercept/src/intercept.cpp +++ b/intercept/src/intercept.cpp @@ -4301,63 +4301,46 @@ bool CLIntercept::injectProgramSource( bool injected = false; - std::string fileName; + std::string dir; // Get the dump directory name. { - OS().GetDumpDirectoryNameWithoutPid( sc_DumpDirectoryName, fileName ); - fileName += "/Inject"; + OS().GetDumpDirectoryNameWithoutPid( sc_DumpDirectoryName, dir ); + dir += "/Inject"; } // Make two candidate file names. They will have the form: // CLI___source.cl, or // CLI__source.cl { - char numberString1[256] = ""; - CLI_SPRINTF( numberString1, 256, "%04u_%08X", + char numberString1[64] = ""; + CLI_SPRINTF( numberString1, 64, "%04u_%08X", m_ProgramNumber, (unsigned int)hash ); - char numberString2[256] = ""; - CLI_SPRINTF( numberString2, 256, "%08X", + char numberString2[64] = ""; + CLI_SPRINTF( numberString2, 64, "%08X", (unsigned int)hash ); - std::string fileName1; - fileName1 = fileName; - fileName1 += "/CLI_"; - fileName1 += numberString1; - fileName1 += "_source.cl"; + std::vector candidates; - std::string fileName2; - fileName2 = fileName; - fileName2 += "/CLI_"; - fileName2 += numberString2; - fileName2 += "_source.cl"; + candidates.push_back(dir + "/CLI_" + numberString1 + "_source.cl"); + candidates.push_back(dir + "/CLI_" + numberString2 + "_source.cl"); std::ifstream is; - is.open( - fileName1.c_str(), - std::ios::in | std::ios::binary ); - if( is.good() ) - { - log( "Injecting source file: " + fileName1 + "\n" ); - } - else + for( const auto& fileName : candidates ) { - log( "Injection source file doesn't exist: " + fileName1 + "\n" ); - is.clear(); - is.open( - fileName2.c_str(), - std::ios::in | std::ios::binary ); + is.open(fileName, std::ios::in | std::ios::binary ); if( is.good() ) { - log( "Injecting source file: " + fileName2 + "\n" ); + log( "Injecting source file: " + fileName + "\n" ); + break; } else { - log( "Injection source file doesn't exist: " + fileName2 + "\n" ); + log( "Injection source file doesn't exist: " + fileName + "\n" ); } } @@ -4411,12 +4394,12 @@ bool CLIntercept::prependProgramSource( bool injected = false; - std::string fileName; + std::string dir; // Get the dump directory name. { - OS().GetDumpDirectoryNameWithoutPid( sc_DumpDirectoryName, fileName ); - fileName += "/Inject"; + OS().GetDumpDirectoryNameWithoutPid( sc_DumpDirectoryName, dir ); + dir += "/Inject"; } // Make three candidate file names. They will have the form: @@ -4424,68 +4407,35 @@ bool CLIntercept::prependProgramSource( // CLI__prepend.cl, or // CLI_prepend.cl { - char numberString1[256] = ""; - CLI_SPRINTF( numberString1, 256, "%04u_%08X", + char numberString1[64] = ""; + CLI_SPRINTF( numberString1, 64, "%04u_%08X", m_ProgramNumber, (unsigned int)hash ); - char numberString2[256] = ""; - CLI_SPRINTF( numberString2, 256, "%08X", + char numberString2[64] = ""; + CLI_SPRINTF( numberString2, 64, "%08X", (unsigned int)hash ); - std::string fileName1; - fileName1 = fileName; - fileName1 += "/CLI_"; - fileName1 += numberString1; - fileName1 += "_prepend.cl"; - - std::string fileName2; - fileName2 = fileName; - fileName2 += "/CLI_"; - fileName2 += numberString2; - fileName2 += "_prepend.cl"; + std::vector candidates; - std::string fileName3; - fileName3 = fileName; - fileName3 += "/CLI_prepend.cl"; + candidates.push_back(dir + "/CLI_" + numberString1 + "_prepend.cl"); + candidates.push_back(dir + "/CLI_" + numberString2 + "_prepend.cl"); + candidates.push_back(dir + "/CLI_prepend.cl"); std::ifstream is; - is.open( - fileName1.c_str(), - std::ios::in | std::ios::binary ); - if( is.good() ) - { - log( "Prepending source file: " + fileName1 + "\n" ); - } - else + for( const auto& fileName : candidates ) { - log( "Prepend source file doesn't exist: " + fileName1 + "\n" ); - is.clear(); - is.open( - fileName2.c_str(), - std::ios::in | std::ios::binary ); + is.open(fileName, std::ios::in | std::ios::binary ); if( is.good() ) { - log( "Prepending source file: " + fileName2 + "\n" ); + log( "Prepending source file: " + fileName + "\n" ); + break; } else { - log( "Prepend source file doesn't exist: " + fileName2 + "\n" ); - - is.clear(); - is.open( - fileName3.c_str(), - std::ios::in | std::ios::binary ); - if( is.good() ) - { - log( "Prepending source file: " + fileName3 + "\n" ); - } - else - { - log( "Prepend source file doesn't exist: " + fileName3 + "\n" ); - } + log( "Prepending source file doesn't exist: " + fileName + "\n" ); } } @@ -4541,63 +4491,46 @@ bool CLIntercept::injectProgramSPIRV( bool injected = false; - std::string fileName; + std::string dir; // Get the dump directory name. { - OS().GetDumpDirectoryNameWithoutPid( sc_DumpDirectoryName, fileName ); - fileName += "/Inject"; + OS().GetDumpDirectoryNameWithoutPid( sc_DumpDirectoryName, dir ); + dir += "/Inject"; } // Make two candidate file names. They will have the form: // CLI___0000.spv, or // CLI__0000.spv { - char numberString1[256] = ""; - CLI_SPRINTF( numberString1, 256, "%04u_%08X_0000", + char numberString1[64] = ""; + CLI_SPRINTF( numberString1, 64, "%04u_%08X_0000", m_ProgramNumber, (unsigned int)hash ); - char numberString2[256] = ""; - CLI_SPRINTF( numberString2, 256, "%08X_0000", + char numberString2[64] = ""; + CLI_SPRINTF( numberString2, 64, "%08X_0000", (unsigned int)hash ); - std::string fileName1; - fileName1 = fileName; - fileName1 += "/CLI_"; - fileName1 += numberString1; - fileName1 += ".spv"; + std::vector candidates; - std::string fileName2; - fileName2 = fileName; - fileName2 += "/CLI_"; - fileName2 += numberString2; - fileName2 += ".spv"; + candidates.push_back(dir + "/CLI_" + numberString1 + ".spv"); + candidates.push_back(dir + "/CLI_" + numberString2 + ".spv"); std::ifstream is; - is.open( - fileName1.c_str(), - std::ios::in | std::ios::binary ); - if( is.good() ) - { - log( "Injecting SPIR-V file: " + fileName1 + "\n" ); - } - else + for( const auto& fileName : candidates ) { - log( "Injection SPIR-V file doesn't exist: " + fileName1 + "\n" ); - is.clear(); - is.open( - fileName2.c_str(), - std::ios::in | std::ios::binary ); + is.open(fileName, std::ios::in | std::ios::binary ); if( is.good() ) { - log( "Injecting SPIR-V file: " + fileName2 + "\n" ); + log( "Injecting SPIR-V file: " + fileName + "\n" ); + break; } else { - log( "Injection SPIR-V file doesn't exist: " + fileName2 + "\n" ); + log( "Injection SPIR-V file doesn't exist: " + fileName + "\n" ); } } @@ -4644,34 +4577,41 @@ bool CLIntercept::injectProgramOptions( const SProgramInfo& programInfo = m_ProgramInfoMap[ program ]; - std::string fileName; + std::string dir; // Get the dump directory name. { - OS().GetDumpDirectoryNameWithoutPid( sc_DumpDirectoryName, fileName ); - fileName += "/Inject"; + OS().GetDumpDirectoryNameWithoutPid( sc_DumpDirectoryName, dir ); + dir += "/Inject"; } - // Make four candidate file names. They will have the form: + + // Make five candidate file names. They will have the form: // CLI_____options.txt, or // CLI____options.txt, or + // CLI___options.txt, or // CLI__options.txt, or // CLI_options.txt { - char numberString1[256] = ""; - CLI_SPRINTF( numberString1, 256, "%04u_%08X_%04u_%08X", + char numberString1[64] = ""; + CLI_SPRINTF( numberString1, 64, "%04u_%08X_%04u_%08X", programInfo.ProgramNumber, (unsigned int)programInfo.ProgramHash, programInfo.CompileCount, (unsigned int)programInfo.OptionsHash ); - char numberString2[256] = ""; - CLI_SPRINTF( numberString2, 256, "%08X_%04u_%08X", + char numberString2[64] = ""; + CLI_SPRINTF( numberString2, 64, "%08X_%04u_%08X", (unsigned int)programInfo.ProgramHash, programInfo.CompileCount, (unsigned int)programInfo.OptionsHash ); - char numberString3[256] = ""; - CLI_SPRINTF( numberString3, 256, "%08X", + char numberString3[64] = ""; + CLI_SPRINTF( numberString3, 64, "%08X_%08X", + (unsigned int)programInfo.ProgramHash, + (unsigned int)programInfo.OptionsHash ); + + char numberString4[64] = ""; + CLI_SPRINTF( numberString4, 64, "%08X", (unsigned int)programInfo.ProgramHash ); const std::string suffix = @@ -4679,78 +4619,28 @@ bool CLIntercept::injectProgramOptions( isLink ? "_link_options.txt" : "_options.txt"; - std::string fileName1; - fileName1 = fileName; - fileName1 += "/CLI_"; - fileName1 += numberString1; - fileName1 += suffix; - - std::string fileName2; - fileName2 = fileName; - fileName2 += "/CLI_"; - fileName2 += numberString2; - fileName2 += suffix; - - std::string fileName3; - fileName3 = fileName; - fileName3 += "/CLI_"; - fileName3 += numberString3; - fileName3 += suffix; + std::vector candidates; - std::string fileName4; - fileName4 = fileName; - fileName4 += suffix; + candidates.push_back(dir + "/CLI_" + numberString1 + suffix); + candidates.push_back(dir + "/CLI_" + numberString2 + suffix); + candidates.push_back(dir + "/CLI_" + numberString3 + suffix); + candidates.push_back(dir + "/CLI_" + numberString4 + suffix); + candidates.push_back(dir + "/CLI" + suffix); std::ifstream is; - is.open( - fileName1.c_str(), - std::ios::in | std::ios::binary ); - if( is.good() ) + for( const auto& fileName : candidates ) { - log( "Injecting options file: " + fileName1 + "\n" ); - } - else - { - log( "Injection options file doesn't exist: " + fileName1 + "\n" ); - is.clear(); - is.open( - fileName2.c_str(), - std::ios::in | std::ios::binary ); + is.open(fileName, std::ios::in | std::ios::binary ); if( is.good() ) { - log( "Injecting options file: " + fileName2 + "\n" ); + log( "Injecting options file: " + fileName + "\n" ); + break; } else { - log( "Injection options file doesn't exist: " + fileName2 + "\n" ); - - is.clear(); - is.open( - fileName3.c_str(), - std::ios::in | std::ios::binary ); - if( is.good() ) - { - log( "Injecting options file: " + fileName3 + "\n" ); - } - else - { - log( "Injection options file doesn't exist: " + fileName3 + "\n" ); - - is.clear(); - is.open( - fileName4.c_str(), - std::ios::in | std::ios::binary ); - if( is.good() ) - { - log( "Injecting options file: " + fileName4 + "\n" ); - } - else - { - log( "Injection options file doesn't exist: " + fileName4 + "\n" ); - } - } + log( "Injection options file doesn't exist: " + fileName + "\n" ); } } @@ -10116,13 +10006,13 @@ cl_program CLIntercept::createProgramWithInjectionBinaries( // CLI__0000 // Leave off the extension for now. { - char numberString1[256] = ""; - CLI_SPRINTF( numberString1, 256, "%04u_%08X_0000", + char numberString1[64] = ""; + CLI_SPRINTF( numberString1, 64, "%04u_%08X_0000", m_ProgramNumber, (unsigned int)hash ); - char numberString2[256] = ""; - CLI_SPRINTF( numberString2, 256, "%08X_0000", + char numberString2[64] = ""; + CLI_SPRINTF( numberString2, 64, "%08X_0000", (unsigned int)hash ); fileName1 = fileName; @@ -10690,67 +10580,50 @@ cl_program CLIntercept::createProgramWithInjectionSPIRV( // the entry point to create a program with IL. if( dispatch().clCreateProgramWithIL == NULL ) { - log( "Aborting InjectProgramSPIRV because clCreateProgramWithIL is NULL!\n" ); + log( "Skipping InjectProgramSPIRV because clCreateProgramWithIL is NULL!\n" ); } else { - std::string fileName; + std::string dir; // Get the dump directory name. { - OS().GetDumpDirectoryNameWithoutPid(sc_DumpDirectoryName, fileName); - fileName += "/Inject"; + OS().GetDumpDirectoryNameWithoutPid(sc_DumpDirectoryName, dir); + dir += "/Inject"; } - // Make three candidate file names. They will have the form: + // Make two candidate file names. They will have the form: // CLI___0000.spv, or // CLI__0000.spv { - char numberString1[256] = ""; - CLI_SPRINTF(numberString1, 256, "%04u_%08X_0000", + char numberString1[64] = ""; + CLI_SPRINTF(numberString1, 64, "%04u_%08X_0000", m_ProgramNumber, (unsigned int)hash); - char numberString2[256] = ""; - CLI_SPRINTF(numberString2, 256, "%08X_0000", + char numberString2[64] = ""; + CLI_SPRINTF(numberString2, 64, "%08X_0000", (unsigned int)hash); - std::string fileName1; - fileName1 = fileName; - fileName1 += "/CLI_"; - fileName1 += numberString1; - fileName1 += ".spv"; + std::vector candidates; - std::string fileName2; - fileName2 = fileName; - fileName2 += "/CLI_"; - fileName2 += numberString2; - fileName2 += ".spv"; + candidates.push_back(dir + "/CLI_" + numberString1 + ".spv"); + candidates.push_back(dir + "/CLI_" + numberString2 + ".spv"); std::ifstream is; - is.open( - fileName1.c_str(), - std::ios::in | std::ios::binary); - if( is.good() ) - { - log("Injecting SPIR-V file: " + fileName1 + "\n"); - } - else + for( const auto& fileName : candidates ) { - log("Injection SPIR-V file doesn't exist: " + fileName1 + "\n"); - is.clear(); - is.open( - fileName2.c_str(), - std::ios::in | std::ios::binary); + is.open(fileName, std::ios::in | std::ios::binary ); if( is.good() ) { - log("Injecting SPIR-V file: " + fileName2 + "\n"); + log( "Injecting SPIR-V file: " + fileName + "\n" ); + break; } else { - log("Injection SPIR-V file doesn't exist: " + fileName2 + "\n"); + log( "Injection SPIR-V file doesn't exist: " + fileName + "\n" ); } } @@ -10763,31 +10636,24 @@ cl_program CLIntercept::createProgramWithInjectionSPIRV( filesize = (size_t)is.tellg(); is.seekg( 0, std::ios::beg ); - char* newILBinary = new char[ filesize ]; - if( newILBinary == NULL ) - { - CLI_ASSERT( 0 ); - } - else - { - is.read(newILBinary, filesize); - - // Right now, this can still die in the ICD loader if the ICD loader - // exports this entry point but the vendor didn't implement it. It - // would be nice to enhance the ICD loader so it called into a safe - // stub function if the vendor didn't implement an entry point... - program = dispatch().clCreateProgramWithIL( - context, - newILBinary, - filesize, - errcode_ret ); - if( program ) - { - logf("Injection successful: clCreateProgramWithIL() returned %p\n", - program ); - } + std::vector newILBinary; + newILBinary.resize(filesize); - delete[] newILBinary; + is.read(newILBinary.data(), filesize); + + // Right now, this can still die in the ICD loader if the ICD loader + // exports this entry point but the vendor didn't implement it. It + // would be nice to enhance the ICD loader so it called into a safe + // stub function if the vendor didn't implement an entry point... + program = dispatch().clCreateProgramWithIL( + context, + newILBinary.data(), + filesize, + errcode_ret ); + if( program ) + { + logf("Injection successful: clCreateProgramWithIL() returned %p\n", + program ); } is.close(); From 1b55a4518864a877ff7d66cccb8df6bee5c94f71 Mon Sep 17 00:00:00 2001 From: Ben Ashbaugh Date: Tue, 28 Apr 2026 07:46:59 -0700 Subject: [PATCH 3/3] add back the missing kernel name delimiter --- intercept/src/intercept.h | 1 + 1 file changed, 1 insertion(+) diff --git a/intercept/src/intercept.h b/intercept/src/intercept.h index cf19c60c..e608d9aa 100644 --- a/intercept/src/intercept.h +++ b/intercept/src/intercept.h @@ -3679,6 +3679,7 @@ inline std::string CLIntercept::getShortKernelNameWithHash( const SKernelInfo& kernelInfo = m_KernelInfoMap[ kernel ]; std::string hashString = getKernelInfoHashString( kernelInfo ); + name += '$'; name += hashString; }