SanitizerApi: Sanitizer Patching API

# Sanitizer Patching API

## Typedefs
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackBarrier )(void *userdata, uint64_t pc, uint32_t barIndex, uint32_t threadCount, uint32_t flags)
| Function type for a barrier callback.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackBlockEnter )(void *userdata, uint64_t pc)
| Function type for a CUDA block enter callback.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackBlockExit )(void *userdata, uint64_t pc)
| Function type for a CUDA block exit callback.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackCall )(void *userdata, uint64_t pc, uint64_t targetPc, uint32_t flags)
| Function type for a function call callback.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackCudaBarrier )(void *userdata, uint64_t pc, void *barrier, uint32_t kind, uint32_t data)
| Function type for a CUDA Barrier action callback.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackDeviceSideFree )(void *userdata, uint64_t pc, void *ptr)
| Function type for a device-side free call.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackDeviceSideMalloc )(void *userdata, uint64_t pc, void *allocatedPtr, uint64_t allocatedSize)
| Function type for a device-side malloc call.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackMemoryAccess )(void *userdata, uint64_t pc, void *ptr, uint32_t accessSize, uint32_t flags, const void *newValue)
| Function type for a memory access callback.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackRet )(void *userdata, uint64_t pc)
| Function type for a function return callback.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackShfl )(void *userdata, uint64_t pc)
| Function type for a shfl callback.
typedef SanitizerPatchResult(SANITIZERAPI * | SanitizerCallbackSyncwarp )(void *userdata, uint64_t pc, uint32_t mask)
| Function type for a syncwarp callback.
## Enumerations
enum | Sanitizer_BarrierFlags { SANITIZER_BARRIER_FLAG_NONE = 0, SANITIZER_BARRIER_FLAG_UNALIGNED_ALLOWED = 0x1 }
| Flags describing a barrier. More...
enum | Sanitizer_CallFlags { SANITIZER_CALL_FLAG_NONE = 0, SANITIZER_CALL_FLAG_UNALIGNED_ALLOWED = 0x1 }
| Flags describing a function call. More...
enum | Sanitizer_CudaBarrierInstructionKind { SANITIZER_CUDA_BARRIER_INVALID = 0, SANITIZER_CUDA_BARRIER_INIT = 1, SANITIZER_CUDA_BARRIER_ARRIVE = 2, SANITIZER_CUDA_BARRIER_ARRIVE_NOCOMPLETE = 3, SANITIZER_CUDA_BARRIER_WAIT = 4, SANITIZER_CUDA_BARRIER_INVALIDATE = 5 }
| CUDA Barrier action kind. More...
enum | Sanitizer_DeviceMemoryFlags { SANITIZER_MEMORY_DEVICE_FLAG_NONE = 0, SANITIZER_MEMORY_DEVICE_FLAG_READ = 0x1, SANITIZER_MEMORY_DEVICE_FLAG_WRITE = 0x2, SANITIZER_MEMORY_DEVICE_FLAG_ATOMSYS = 0x4 }
| Flags describing a memory access. More...
enum | Sanitizer_InstructionId { SANITIZER_INSTRUCTION_INVALID = 0, SANITIZER_INSTRUCTION_BLOCK_ENTER = 1, SANITIZER_INSTRUCTION_BLOCK_EXIT = 2, SANITIZER_INSTRUCTION_GLOBAL_MEMORY_ACCESS = 3, SANITIZER_INSTRUCTION_SHARED_MEMORY_ACCESS = 4, SANITIZER_INSTRUCTION_LOCAL_MEMORY_ACCESS = 5, SANITIZER_INSTRUCTION_BARRIER = 6, SANITIZER_INSTRUCTION_SYNCWARP = 7, SANITIZER_INSTRUCTION_SHFL = 8, SANITIZER_INSTRUCTION_CALL = 9, SANITIZER_INSTRUCTION_RET = 10, SANITIZER_INSTRUCTION_DEVICE_SIDE_MALLOC = 11, SANITIZER_INSTRUCTION_DEVICE_SIDE_FREE = 12, SANITIZER_INSTRUCTION_CUDA_BARRIER = 13 }
| Instrumentation. More...
enum | SanitizerPatchResult { SANITIZER_PATCH_SUCCESS = 0, SANITIZER_PATCH_ERROR = 1 }
| Sanitizer patch result codes. More...
## Functions
SanitizerResult SANITIZERAPI | sanitizerAddPatches (const void *image, CUcontext ctx)
| Load a module containing patches that can be used by the patching API.
SanitizerResult SANITIZERAPI | sanitizerAddPatchesFromFile (const char *filename, CUcontext ctx)
| Load a module containing patches that can be used by the patching API.
SanitizerResult SANITIZERAPI | sanitizerGetCallbackPcAndSize (CUcontext ctx, const char *deviceCallbackName, uint64_t *pc, uint64_t *size)
| Get PC and size of a device callback.
SanitizerResult SANITIZERAPI | sanitizerGetFunctionPcAndSize (CUmodule module, const char *functionName, uint64_t *pc, uint64_t *size)
| Get PC and size of a CUDA function.
SanitizerResult SANITIZERAPI | sanitizerPatchInstructions (const Sanitizer_InstructionId instructionId, CUmodule module, const char *deviceCallbackName)
| Set instrumentation points and patches to be applied in a module.
SanitizerResult SANITIZERAPI | sanitizerPatchModule (CUmodule module)
| Perform the actual instrumentation of a module.
SanitizerResult SANITIZERAPI | sanitizerSetCallbackData (CUfunction kernel, const void *userdata)
| Specifies the user data pointer for callbacks.
SanitizerResult SANITIZERAPI | sanitizerSetLaunchCallbackData (Sanitizer_LaunchHandle launch, CUfunction kernel, Sanitizer_StreamHandle stream, const void *userdata)
| Specifies the user data pointer for callbacks.
SanitizerResult SANITIZERAPI | sanitizerUnpatchModule (CUmodule module)
| Remove existing instrumentation of a module.

## Detailed Description

Functions, types, and enums that implement the Sanitizer Patching API.

## Typedef Documentation

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackBarrier)(void *userdata, uint64_t pc, uint32_t barIndex, uint32_t threadCount, uint32_t flags)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction `barIndex` is the barrier index. `threadCount` is the number of expected threads (must be a multiple of the warp size). `flags` contains information about the barrier. See Sanitizer_BarrierFlags to interpret this value. 0 means that all threads are participating in the barrier.

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackBlockEnter)(void *userdata, uint64_t pc)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the entry point of the block

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackBlockExit)(void *userdata, uint64_t pc)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackCall)(void *userdata, uint64_t pc, uint64_t targetPc, uint32_t flags)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction `targetPc` is the PC where the called function is located. `flags` contains information about the function call.

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackCudaBarrier)(void *userdata, uint64_t pc, void *barrier, uint32_t kind, uint32_t data)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction `barrier` Barrier address which can be used as a unique identifier `kind` Barrier action type. See Sanitizer_CudaBarrierInstructionKind `data` Barrier data. This is specific to each action type, refer to Sanitizer_CudaBarrierInstructionKind

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackDeviceSideFree)(void *userdata, uint64_t pc, void *ptr)

Note:
  This is called prior to the actual call.

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction `ptr` is the pointer passed to device-side free.

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackDeviceSideMalloc)(void *userdata, uint64_t pc, void *allocatedPtr, uint64_t allocatedSize)

Note:
  This is called after the call has completed.

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction `allocatedPtr` is the pointer returned by device-side malloc `allocatedSize` is the size requested by the user to device-side malloc.

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackMemoryAccess)(void *userdata, uint64_t pc, void *ptr, uint32_t accessSize, uint32_t flags, const void *newValue)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction `ptr` is the address of the memory being accessed. For local or shared memory access, this is the offset within the local or shared memory window. `accessSize` is the size of the access in bytes. Valid values are 1, 2, 4, 8, and 16. `flags` contains information about the type of access. See Sanitizer_DeviceMemoryFlags to interpret this value. `newValue` is a pointer to the new value being written if the acces is a write. If the access is a read or an atomic, the pointer will be NULL.

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackRet)(void *userdata, uint64_t pc)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackShfl)(void *userdata, uint64_t pc)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction

typedef SanitizerPatchResult(SANITIZERAPI * SanitizerCallbackSyncwarp)(void *userdata, uint64_t pc, uint32_t mask)

`userdata` is a pointer to user data. See sanitizerPatchModule `pc` is the program counter of the patched instruction `mask` is the thread mask passed to __syncwarp().

## Enumeration Type Documentation

enum Sanitizer_BarrierFlags

Flags describing a barrier. These values are to be or-combined in the value of flags for a SanitizerCallbackBarrier callback.

Enumerator:

  SANITIZER_BARRIER_FLAG_NONE | Empty flag.
  SANITIZER_BARRIER_FLAG_UNALIGNED_ALLOWED | Specifies that the barrier can be called unaligned. This flag is only valid on SM 7.0 and above.

enum Sanitizer_CallFlags

Flags describing a function call. These values are to be or-combined in the value of flags for a SanitizerCallbackCall callback.

Enumerator:

  SANITIZER_CALL_FLAG_NONE | Empty flag.
  SANITIZER_CALL_FLAG_UNALIGNED_ALLOWED | Specifies that barriers within this function call can be called unaligned. This flag is only valid on SM 7.0 and above.

enum Sanitizer_CudaBarrierInstructionKind

Refer to the CUDA Barrier interface section of the CUDA toolkit documentation for a more extensive description of these actions.

Enumerator:

  SANITIZER_CUDA_BARRIER_INVALID | Invalid action ID.
  SANITIZER_CUDA_BARRIER_INIT | Barrier initialization.
  SANITIZER_CUDA_BARRIER_ARRIVE | Barrier arrive operation.
  SANITIZER_CUDA_BARRIER_ARRIVE_NOCOMPLETE | Barrier arrive operation without phase completion. Barrier data is the count argument to the arrive-on operation.
  SANITIZER_CUDA_BARRIER_WAIT | Barrier wait operation.
  SANITIZER_CUDA_BARRIER_INVALIDATE | Barrier invalidation.

enum Sanitizer_DeviceMemoryFlags

Flags describing a memory access. These values are to be or-combined in the value of flags for a SanitizerCallbackMemoryAccess callback.

Enumerator:

  SANITIZER_MEMORY_DEVICE_FLAG_NONE | Empty flag.
  SANITIZER_MEMORY_DEVICE_FLAG_READ | Specifies that the access is a read.
  SANITIZER_MEMORY_DEVICE_FLAG_WRITE | Specifies that the access is a write.
  SANITIZER_MEMORY_DEVICE_FLAG_ATOMSYS | Specifies that the access is a system-scoped atomic.

enum Sanitizer_InstructionId

Instrumentation. Every entry represent an instruction type or a function call where a callback patch can be inserted.

Enumerator:

  SANITIZER_INSTRUCTION_INVALID | Invalid instruction ID.
  SANITIZER_INSTRUCTION_BLOCK_ENTER | CUDA block enter. This is called prior to any user code. The type of the callback must be SanitizerCallbackBlockEnter.
  SANITIZER_INSTRUCTION_BLOCK_EXIT | CUDA block exit. This is called after all user code has executed. The type of the callback must be SanitizerCallbackBlockExit.
  SANITIZER_INSTRUCTION_GLOBAL_MEMORY_ACCESS | Global Memory Access. This can be a store, load or atomic operation. The type of the callback must be SanitizerCallbackMemoryAccess.
  SANITIZER_INSTRUCTION_SHARED_MEMORY_ACCESS | Shared Memory Access. This can be a store, load or atomic operation. The type of the callback must be SanitizerCallbackMemoryAccess.
  SANITIZER_INSTRUCTION_LOCAL_MEMORY_ACCESS | Local Memory Access. This can be a store or load operation. The type of the callback must be SanitizerCallbackMemoryAccess.
  SANITIZER_INSTRUCTION_BARRIER | Barrier. The type of the callback must be SanitizerCallbackBarrier.
  SANITIZER_INSTRUCTION_SYNCWARP | Syncwarp. The type of the callback must be SanitizerCallbackSyncwarp.
  SANITIZER_INSTRUCTION_SHFL | Shfl. The type of the callback must be SanitizerCallbackShfl.
  SANITIZER_INSTRUCTION_CALL | Function call. The type of the callback must be SanitizerCallbackCall.
  SANITIZER_INSTRUCTION_RET | Function return. The type of the callback must be SanitizerCallbackRet.
  SANITIZER_INSTRUCTION_DEVICE_SIDE_MALLOC | Device-side malloc. The type of the callback must be SanitizerCallbackDeviceSideMalloc.
  SANITIZER_INSTRUCTION_DEVICE_SIDE_FREE | Device-side free. The type of the callback must be SanitizerCallbackDeviceSideFree.
  SANITIZER_INSTRUCTION_CUDA_BARRIER | CUDA Barrier operation. The type of the callback must be SanitizerCallbackCudaBarrier.

enum SanitizerPatchResult

Error and result codes returned by Sanitizer patches. If a patch returns SANITIZER_PATCH_ERROR, the thread will be exited.

Enumerator:

  SANITIZER_PATCH_SUCCESS | No error.
  SANITIZER_PATCH_ERROR | An error was detected in the patch.

## Function Documentation

SanitizerResult SANITIZERAPI sanitizerAddPatches | ( | const void * | image,
|  | CUcontext | ctx |
| ) |  |  |

Note:
  Thread-safety: an API user must serialize access to sanitizerAddPatchesFromFile, sanitizerAddPatches, sanitizerPatchInstructions, and sanitizerPatchModule. For example if sanitizerAddPatches(image) and sanitizerPatchInstruction(*, *, cbName) are called concurrently and cbName is intended to be found in the loaded image, the results are undefined.

  The patches loaded are only valid for the specified CUDA context.

Parameters:

  | image | Pointer to module data to load. This API supports the same module formats as the cuModuleLoadData and cuModuleLoadFatBinary functions from the CUDA driver API.
  | ctx | CUDA context in which to load the patches. If ctx is NULL, the current context will be used.

Return values:

  | SANITIZER_SUCCESS | on success
  | SANITIZER_ERROR_NOT_INITIALIZED | if unable to initialize the sanitizer
  | SANITIZER_ERROR_INVALID_PARAMETER | if `image` does not point to a valid CUDA module.

SanitizerResult SANITIZERAPI sanitizerAddPatchesFromFile | ( | const char * | filename,
|  | CUcontext | ctx |
| ) |  |  |

Note:
  Thread-safety: an API user must serialize access to sanitizerAddPatchesFromFile, sanitizerAddPatches, sanitizerPatchInstructions, and sanitizerPatchModule. For example if sanitizerAddPatchesFromFile(filename) and sanitizerPatchInstruction(*, *, cbName) are called concurrently and cbName is intended to be found in the loaded module, the results are undefined.

  The patches loaded are only valid for the specified CUDA context.

Parameters:

  | filename | Path to the module file. This API supports the same module formats as the cuModuleLoad function from the CUDA driver API.
  | ctx | CUDA context in which to load the patches. If ctx is NULL, the current context will be used.

Return values:

  | SANITIZER_SUCCESS | on success
  | SANITIZER_ERROR_NOT_INITIALIZED | if unable to initialize the sanitizer
  | SANITIZER_ERROR_INVALID_PARAMETER | if `filename` is not a path to a valid CUDA module.

SanitizerResult SANITIZERAPI sanitizerGetCallbackPcAndSize | ( | CUcontext | ctx,
|  | const char * | deviceCallbackName,
|  | uint64_t * | pc,
|  | uint64_t * | size |
| ) |  |  |

Parameters:

  `[in]` | ctx | CUDA context in which the patches were loaded. If ctx is NULL, the current context will be used.
  `[in]` | deviceCallbackName | device function callback name
  `[out]` | pc | Callback PC returned
  `[out]` | size | Callback size returned

Return values:

  | SANITIZER_SUCCESS | on success
  | SANITIZER_ERROR_INVALID_PARAMETER | if `deviceCallbackName` function cannot be located, if pc is NULL or if size is NULL.

SanitizerResult SANITIZERAPI sanitizerGetFunctionPcAndSize | ( | CUmodule | module,
|  | const char * | functionName,
|  | uint64_t * | pc,
|  | uint64_t * | size |
| ) |  |  |

Parameters:

  `[in]` | module | CUDA module containing the function
  `[in]` | deviceCallbackName | CUDA function name
  `[out]` | pc | Function start program counter (PC) returned
  `[out]` | size | Function size in bytes returned

Return values:

  | SANITIZER_SUCCESS | on success
  | SANITIZER_ERROR_INVALID_PARAMETER | if `functionName` function cannot be located, if pc is NULL or if size is NULL.

SanitizerResult SANITIZERAPI sanitizerPatchInstructions | ( | const Sanitizer_InstructionId | instructionId,
|  | CUmodule | module,
|  | const char * | deviceCallbackName |
| ) |  |  |

Mark that all instrumentation points matching instructionId are to be patched in order to call the device function identified by deviceCallbackName. It is up to the API client to ensure that this device callback exists and match the correct callback format for this instrumentation point.

Note:
  Thread-safety: an API user must serialize access to sanitizerAddPatchesFromFile, sanitizerAddPatches, sanitizerPatchInstructions, and sanitizerPatchModule. For example if sanitizerAddPatches(fileName) and sanitizerPatchInstruction(*, *, cbName) are called concurrently and cbName is intended to be found in the loaded module, the results are undefined.

Parameters:

  | instructionId | Instrumentation point for which to insert patches
  | module | CUDA module to instrument
  | deviceCallbackName | Name of the device function callback that the inserted patch will call at the instrumented points. This function is expected to be found in code previously loaded by sanitizerAddPatchesFromFile or sanitizerAddPatches.

Return values:

  | SANITIZER_SUCCESS | on success
  | SANITIZER_ERROR_NOT_INITIALIZED | if unable to initialize the sanitizer
  | SANITIZER_ERROR_INVALID_PARAMETER | if `module` is not a CUDA module or if `deviceCallbackName` function cannot be located.

SanitizerResult SANITIZERAPI sanitizerPatchModule | ( | CUmodule | module | ) |

Perform the instrumentation of a CUDA module based on previous calls to sanitizerPatchInstructions. This function also specifies the device memory buffer to be passed in as userdata to all callback functions.

Note:
  Thread-safety: an API user must serialize access to sanitizerAddPatchesFromFile, sanitizerAddPatches, sanitizerPatchInstructions, and sanitizerPatchModule. For example if sanitizerPatchModule(mod, *) and sanitizerPatchInstruction(*, mod, *) are called concurrently, the results are undefined.

Parameters:

  | module | CUDA module to instrument

Return values:

  | SANITIZER_SUCCESS | on success
  | SANITIZER_ERROR_INVALID_PARAMETER | if `module` is not a CUDA module

SanitizerResult SANITIZERAPI sanitizerSetCallbackData | ( | CUfunction | kernel,
|  | const void * | userdata |
| ) |  |  |

Mark all subsequent launches of `kernel` to use `userdata` pointer as the device memory buffer to pass in to callback functions.

Parameters:

  | kernel | CUDA function to link to user data. Callbacks in subsequent launches on this kernel will use `userdata` as callback data.
  | userdata | Device memory buffer. This data will be passed to callback functions via the `userdata` parameter.

Return values:

  | SANITIZER_SUCCESS | on success

SanitizerResult SANITIZERAPI sanitizerSetLaunchCallbackData | ( | Sanitizer_LaunchHandle | launch,
|  | CUfunction | kernel,
|  | Sanitizer_StreamHandle | stream,
|  | const void * | userdata |
| ) |  |  |

Mark `launch` to use `userdata` pointer as the device memory buffer to pass in to callback functions. This function is only available if the driver version is 455 or newer.

Parameters:

  | launch | Kernel launch to link to user data. Callbacks in this kernel launch will use `userdata` as callback data.
  | kernel | CUDA function associated with the kernel launch.
  | stream | CUDA stream associated with the stream launch.
  | userdata | Device memory buffer. This data will be passed to callback functions via the `userdata` parameter.

Return values:

  | SANITIZER_SUCCESS | on success

SanitizerResult SANITIZERAPI sanitizerUnpatchModule | ( | CUmodule | module | ) |

Remove any instrumentation of a CUDA module performed by previous calls to sanitizerPatchModule.

Note:
  Thread-safety: an API user must serialize access to sanitizerPatchModule and sanitizerUnpatchModule on the same module. For example, if sanitizerPatchModule(mod) and sanitizerUnpatchModule(mod) are called concurrently, the results are undefined.

Parameters:

  | module | CUDA module on which to remove instrumentation

Return values:

  | SANITIZER_SUCCESS | on success