summaryrefslogtreecommitdiffstats
path: root/userspace/cuda
diff options
context:
space:
mode:
Diffstat (limited to 'userspace/cuda')
-rw-r--r--userspace/cuda/570.144/annotations/README.md3
-rw-r--r--userspace/cuda/570.144/annotations/name-candidates.tsv334
-rw-r--r--userspace/cuda/570.144/annotations/names.tsv39
-rw-r--r--userspace/cuda/570.144/annotations/subsystems.tsv49
-rw-r--r--userspace/cuda/570.144/ghidra/DecompileAt.java13
-rwxr-xr-xuserspace/cuda/570.144/scripts/ghidra_analyze.sh15
-rwxr-xr-xuserspace/cuda/570.144/scripts/ghidra_decompile_project.sh13
-rw-r--r--userspace/cuda/READ-ME-FIRST.md11
-rw-r--r--userspace/cuda/README.md5
-rw-r--r--userspace/cuda/docs/05-570.144-decompilation.md89
-rw-r--r--userspace/cuda/docs/06-tooling.md103
-rw-r--r--userspace/cuda/docs/07-version-upgrade-playbook.md31
-rw-r--r--userspace/cuda/docs/08-virtualization-approaches.md2
-rwxr-xr-xuserspace/cuda/tools/cudatool.py154
-rwxr-xr-xuserspace/cuda/tools/diff_corpus.py221
-rw-r--r--userspace/cuda/tools/ghidra/AnalyzeFunctions.java343
-rwxr-xr-xuserspace/cuda/tools/name_candidates.py224
-rwxr-xr-xuserspace/cuda/tools/subsystem_digest.py190
18 files changed, 1807 insertions, 32 deletions
diff --git a/userspace/cuda/570.144/annotations/README.md b/userspace/cuda/570.144/annotations/README.md
index 868c503..85c14af 100644
--- a/userspace/cuda/570.144/annotations/README.md
+++ b/userspace/cuda/570.144/annotations/README.md
@@ -8,8 +8,9 @@ accumulates across driver versions.
| File | Format | Purpose |
|---|---|---|
-| `names.tsv` | `file_vaddr<TAB>name<TAB>source` | symbol map to apply to a Ghidra project (or any address-keyed analysis). `source` is `export`, `wrapper`, `verified`, or `todo`. |
+| `names.tsv` | `file_vaddr<TAB>name<TAB>source` | symbol map to apply to a Ghidra project (or any address-keyed analysis). `source` is `export`, `wrapper`, `wrapper-callee`, `verified`, or `todo`. |
| `subsystems.tsv` | `file_vaddr<TAB>name<TAB>subsystem<TAB>role<TAB>evidence` | human-readable subsystem index: which function belongs to which layer and what it does, with the evidence for the claim. |
+| `name-candidates.tsv` | `file_vaddr<TAB>proposed_name<TAB>confidence<TAB>evidence<TAB>status` | machine-proposed API-implementation names for wrapper callees (`tools/name_candidates.py`), with the confidence and the candidate sets behind each proposal. `status` is `unverified` until the body is read; only `verified` entries may be promoted to `names.tsv`. |
Addresses are **file virtual addresses** (`libcuda+0x...`). Apply the map with
`tools/ghidra/ApplyNameMap.java`; see `docs/06-tooling.md`.
diff --git a/userspace/cuda/570.144/annotations/name-candidates.tsv b/userspace/cuda/570.144/annotations/name-candidates.tsv
new file mode 100644
index 0000000..559633f
--- /dev/null
+++ b/userspace/cuda/570.144/annotations/name-candidates.tsv
@@ -0,0 +1,334 @@
+# Open-IOV CUDA API-implementation candidates (our own work product; tracked).
+# Generated by tools/name_candidates.py from the elf-index exports,
+# callgraph and the version's names.tsv; see that script for the method.
+#
+# file_vaddr<TAB>proposed_name<TAB>confidence<TAB>evidence<TAB>status
+# confidence: high = exactly one filtered candidate, shared by >=2 variants
+# or a unique callee; medium = one survivor also called by another
+# wrapper, or several survivors (best-ranked proposed).
+# status: unverified (tool output). Verification = read the body in the
+# decompiled corpus and mark verified/corrected here; only verified
+# names may be copied into names.tsv.
+#
+0x001a36d0 impl_cuCtxGetApiVersion high group=cuCtxGetApiVersion variants=cuCtxGetApiVersion; before=0x1a36d0,0x2bb140,0x2bb420,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1a36d0; outside_wrappers=0 verified
+0x001a3770 impl_cuCtxGetId medium group=cuCtxGetId variants=cuCtxGetId; before=0x1a3770,0x2bb070,0x2bb140,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1a3770,0x2bb070; outside_wrappers=0 unverified
+0x001a4480 impl_cuArrayGetSparseProperties medium group=cuArrayGetSparseProperties variants=cuArrayGetSparseProperties; before=0x1a4480,0x257720,0x258750,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a4480,0x258750,0x257720; outside_wrappers=0 unverified
+0x001a46d0 impl_cuMipmappedArrayGetSparseProperties medium group=cuMipmappedArrayGetSparseProperties variants=cuMipmappedArrayGetSparseProperties; before=0x1a46d0,0x257720,0x258750,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a46d0,0x258750,0x257720; outside_wrappers=0 unverified
+0x001a4900 impl_cuArrayGetMemoryRequirements high group=cuArrayGetMemoryRequirements variants=cuArrayGetMemoryRequirements; before=0x1a4900,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a4900; outside_wrappers=0 verified
+0x001a4ac0 impl_cuMipmappedArrayGetMemoryRequirements high group=cuMipmappedArrayGetMemoryRequirements variants=cuMipmappedArrayGetMemoryRequirements; before=0x1a4ac0,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a4ac0; outside_wrappers=0 unverified
+0x001a5410 impl_cuArrayGetPlane high group=cuArrayGetPlane variants=cuArrayGetPlane; before=0x1a5410,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a5410; outside_wrappers=0 verified
+0x001a5630 impl_cuMipmappedArrayGetLevel high group=cuMipmappedArrayGetLevel variants=cuMipmappedArrayGetLevel; before=0x1a5630,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a5630; outside_wrappers=0 unverified
+0x001a5820 impl_cuDevicePrimaryCtxGetState high group=cuDevicePrimaryCtxGetState variants=cuDevicePrimaryCtxGetState; before=0x1792f0,0x179350,0x1a5820,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1a5820; outside_wrappers=0 verified
+0x001a6150 impl_cuDeviceRegisterAsyncNotification high group=cuDeviceRegisterAsyncNotification variants=cuDeviceRegisterAsyncNotification; before=0x1792f0,0x179350,0x179a80,0x1a6150,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a6150; outside_wrappers=0 verified
+0x001a62c0 impl_cuDeviceUnregisterAsyncNotification high group=cuDeviceUnregisterAsyncNotification variants=cuDeviceUnregisterAsyncNotification; before=0x179200,0x1792f0,0x179350,0x1a62c0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a62c0; outside_wrappers=0 unverified
+0x001a6430 impl_cuCtxAttach high group=cuCtxAttach variants=cuCtxAttach; before=0x1a6430,0x2bb140,0x2fde50,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a6430; outside_wrappers=0 verified
+0x001a66f0 impl_cuCtxGetCurrent high group=cuCtxGetCurrent variants=cuCtxGetCurrent; before=0x1798f0,0x1a66f0,0x2fde50,0x2fe440,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a66f0; outside_wrappers=0 verified
+0x001a6850 impl_cuCtxGetDevice high group=cuCtxGetDevice variants=cuCtxGetDevice; before=0x1a6850,0x2fde50,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a6850; outside_wrappers=0 verified
+0x001a6960 impl_cuCtxGetFlags high group=cuCtxGetFlags variants=cuCtxGetFlags; before=0x1a6960,0x2dc100,0x2fde50,0x2fe540,0x4a7e90,0xd4bd20,0xd4dc50; after=0x1a6960; outside_wrappers=0 verified
+0x001a6af0 impl_cuFlushGPUDirectRDMAWrites high group=cuFlushGPUDirectRDMAWrites variants=cuFlushGPUDirectRDMAWrites; before=0x1a6af0,0x2baed0,0x2fde50,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a6af0; outside_wrappers=0 verified
+0x001a6c50 impl_cuCtxGetExecAffinity high group=cuCtxGetExecAffinity variants=cuCtxGetExecAffinity; before=0x1a6c50,0x2baed0,0x2fde50,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a6c50; outside_wrappers=0 verified
+0x001a7320 impl_cuDeviceGetLuid high group=cuDeviceGetLuid variants=cuDeviceGetLuid; before=0x1a7320,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1a7320; outside_wrappers=0 verified
+0x001a78c0 impl_cuDeviceGetDevResource high group=cuDeviceGetDevResource variants=cuDeviceGetDevResource; before=0x1a78c0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1a78c0; outside_wrappers=0 unverified
+0x001a7aa0 impl_cuModuleGetFunctionCount high group=cuModuleGetFunctionCount variants=cuModuleGetFunctionCount; before=0x1a7aa0,0x2baed0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a7aa0; outside_wrappers=0 unverified
+0x001a7c40 impl_cuModuleEnumerateFunctions high group=cuModuleEnumerateFunctions variants=cuModuleEnumerateFunctions; before=0x1a7c40,0x2baed0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a7c40; outside_wrappers=0 unverified
+0x001a8120 impl_cuArrayDestroy medium group=cuArrayDestroy variants=cuArrayDestroy; before=0x1792f0,0x179350,0x1a8120,0x2597f0,0x2bb140,0x2d8f40,0x2e5900,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50,0xd4f3e0,0xd51980; after=0x1a8120,0x2597f0,0x2e5900; outside_wrappers=0 unverified
+0x001a82f0 impl_cuMipmappedArrayCreate high group=cuMipmappedArrayCreate variants=cuMipmappedArrayCreate; before=0x1a82f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1a82f0; outside_wrappers=0 unverified
+0x001a8520 impl_cuMipmappedArrayDestroy medium group=cuMipmappedArrayDestroy variants=cuMipmappedArrayDestroy; before=0x1792f0,0x179350,0x1a8520,0x25a070,0x2bb140,0x2d8f40,0x2e5a50,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50,0xd4f3e0,0xd51980; after=0x1a8520,0x2e5a50,0x25a070; outside_wrappers=0 unverified
+0x001aa6c0 impl_cuCtxGetCacheConfig high group=cuCtxGetCacheConfig variants=cuCtxGetCacheConfig; before=0x179cf0,0x1aa6c0,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x1aa6c0; outside_wrappers=0 unverified
+0x001aa880 impl_cuCtxGetSharedMemConfig high group=cuCtxGetSharedMemConfig variants=cuCtxGetSharedMemConfig; before=0x179cf0,0x1aa880,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x1aa880; outside_wrappers=0 unverified
+0x001aad70 impl_cuCheckpointProcessLock medium group=cuCheckpointProcessLock variants=cuCheckpointProcessLock; before=0x179200,0x1aad70,0x2623e0,0x2fe540,0x30a870,0x4a7e90,0xd19d70,0xd4dc50; after=0x1aad70,0xd19d70,0x2623e0,0x30a870; outside_wrappers=0 unverified
+0x001aae30 impl_cuCheckpointProcessCheckpoint high group=cuCheckpointProcessCheckpoint variants=cuCheckpointProcessCheckpoint; before=0x1aae30,0x2fe540,0x4a7e90,0xd4dc50; after=0x1aae30; outside_wrappers=0 unverified
+0x001aaee0 impl_cuCheckpointProcessRestore high group=cuCheckpointProcessRestore variants=cuCheckpointProcessRestore; before=0x1aaee0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1aaee0; outside_wrappers=0 unverified
+0x001aaf90 impl_cuCheckpointProcessUnlock high group=cuCheckpointProcessUnlock variants=cuCheckpointProcessUnlock; before=0x1aaf90,0x2fe540,0x4a7e90,0xd4dc50; after=0x1aaf90; outside_wrappers=0 unverified
+0x001ab040 impl_cuCoredumpGetAttribute medium group=cuCoredumpGetAttribute variants=cuCoredumpGetAttribute; before=0x179190,0x179470,0x1ab040,0x2bb420,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ab040,0x179190,0x179470; outside_wrappers=0 unverified
+0x001ab1e0 impl_cuCoredumpGetAttributeGlobal medium group=cuCoredumpGetAttributeGlobal variants=cuCoredumpGetAttributeGlobal; before=0x179190,0x179470,0x1ab1e0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ab1e0,0x179190,0x179470; outside_wrappers=0 unverified
+0x001ac3f0 impl_cuCtxDetach high group=cuCtxDetach variants=cuCtxDetach; before=0x1ac3f0,0x26d8e0,0x2bb300,0x2fde50,0x2fe0f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ac3f0; outside_wrappers=0 unverified
+0x001acc50 impl_cuCtxSetCurrent medium group=cuCtxSetCurrent variants=cuCtxSetCurrent; before=0x1acc50,0x24a4d0,0x24b930,0x24b9e0,0x2fde50,0x2fde90,0x2fe540,0x4a7e90,0xd4dc50; after=0x1acc50,0x2fde90; outside_wrappers=0 unverified
+0x001acec0 impl_cuCtxSetFlags medium group=cuCtxSetFlags variants=cuCtxSetFlags; before=0x1acec0,0x26ab80,0x2d8f40,0x2fde50,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1acec0,0x26ab80; outside_wrappers=0 unverified
+0x001ad4d0 impl_cuCtxResetPersistingL2Cache medium group=cuCtxResetPersistingL2Cache variants=cuCtxResetPersistingL2Cache; before=0x179cf0,0x1ad4d0,0x26b920,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x1ad4d0,0x26b920; outside_wrappers=0 unverified
+0x001ad670 impl_cuCtxSetCacheConfig medium group=cuCtxSetCacheConfig variants=cuCtxSetCacheConfig; before=0x1ad670,0x26ae40,0x2d8f40,0x2fe230,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x1ad670,0x26ae40; outside_wrappers=0 unverified
+0x001ad770 impl_cuCtxSetSharedMemConfig medium group=cuCtxSetSharedMemConfig variants=cuCtxSetSharedMemConfig; before=0x1ad770,0x26ae40,0x2d8f40,0x2fe230,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x1ad770,0x26ae40; outside_wrappers=0 unverified
+0x001ad870 impl_cuCtxEnablePeerAccess medium group=cuCtxEnablePeerAccess variants=cuCtxEnablePeerAccess; before=0x1792f0,0x179350,0x1ad870,0x2baed0,0x2c1500,0x2e5bf0,0x2fe230,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50; after=0x1ad870,0x2e5bf0,0x2c1500; outside_wrappers=0 unverified
+0x001ada20 impl_cuCtxDisablePeerAccess medium group=cuCtxDisablePeerAccess variants=cuCtxDisablePeerAccess; before=0x1792f0,0x179350,0x1ada20,0x259530,0x2baed0,0x2d8f40,0x2e4ff0,0x2fe230,0x2fe540,0x443950,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x1ada20,0x2e4ff0,0x259530,0x443950; outside_wrappers=0 unverified
+0x001adc60 impl_cuCtxRecordEvent high group=cuCtxRecordEvent variants=cuCtxRecordEvent; before=0x1792f0,0x179350,0x1adc60,0x2886b0,0x2895f0,0x2bb140,0x2f8e10,0x2f8fd0,0x2fe540,0x4a7e90,0xd1e3f0,0xd4d9a0,0xd4dc50; after=0x1adc60; outside_wrappers=0 unverified
+0x001ade30 impl_cuCtxWaitEvent medium group=cuCtxWaitEvent variants=cuCtxWaitEvent; before=0x1792f0,0x179350,0x1ade30,0x2bb140,0x2ed7d0,0x2fe540,0x4a7e90,0xd1e090,0xd1e230,0xd4d9a0,0xd4dc50; after=0x1ade30,0xd1e230; outside_wrappers=0 unverified
+0x001adfb0 impl_cuDeviceGetByPCIBusId high group=cuDeviceGetByPCIBusId variants=cuDeviceGetByPCIBusId; before=0x1adfb0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1adfb0; outside_wrappers=0 unverified
+0x001ae150 impl_cuDeviceGetPCIBusId medium group=cuDeviceGetPCIBusId variants=cuDeviceGetPCIBusId; before=0x179560,0x1ae150,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1ae150,0x179560; outside_wrappers=0 unverified
+0x001ae290 impl_cuDeviceGetTexture1DLinearMaxWidth medium group=cuDeviceGetTexture1DLinearMaxWidth variants=cuDeviceGetTexture1DLinearMaxWidth; before=0x1ae290,0x257890,0x2583d0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1ae290,0x257890; outside_wrappers=0 unverified
+0x001ae3d0 impl_cuDeviceComputeCapability high group=cuDeviceComputeCapability variants=cuDeviceComputeCapability; before=0x1ae3d0,0x26bc10,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1ae3d0; outside_wrappers=0 verified
+0x001ae550 impl_cuDeviceGetProperties high group=cuDeviceGetProperties variants=cuDeviceGetProperties; before=0x1ae550,0x26bc10,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1ae550; outside_wrappers=0 verified
+0x001ae780 impl_cuDeviceGetAttribute high group=cuDeviceGetAttribute variants=cuDeviceGetAttribute; before=0x1ae780,0x26bc10,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1ae780; outside_wrappers=0 verified
+0x001aec20 impl_cuDeviceCanAccessPeer medium group=cuDeviceCanAccessPeer variants=cuDeviceCanAccessPeer; before=0x1aec20,0x2c1610,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1aec20,0x2c1610; outside_wrappers=0 unverified
+0x001aed70 impl_cuDevicePrimaryCtxRetain medium group=cuDevicePrimaryCtxRetain variants=cuDevicePrimaryCtxRetain; before=0x1792f0,0x179350,0x1aed70,0x277570,0x2fe540,0x4a7e90,0xd4dc50; after=0x1aed70,0x277570; outside_wrappers=0 unverified
+0x001af400 impl_cuDeviceSetMemPool medium group=cuDeviceSetMemPool variants=cuDeviceSetMemPool; before=0x1af400,0x2c3b00,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x1af400,0x2c3b00; outside_wrappers=0 unverified
+0x001af5a0 impl_cuDeviceGetMemPool medium group=cuDeviceGetMemPool variants=cuDeviceGetMemPool; before=0x1af5a0,0x26bab0,0x2c61f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1af5a0,0x2c61f0,0x26bab0; outside_wrappers=0 unverified
+0x001af960 impl_cuDeviceGetGraphMemAttribute high group=cuDeviceGetGraphMemAttribute variants=cuDeviceGetGraphMemAttribute; before=0x1af960,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1af960; outside_wrappers=0 unverified
+0x001afae0 impl_cuDeviceSetGraphMemAttribute high group=cuDeviceSetGraphMemAttribute variants=cuDeviceSetGraphMemAttribute; before=0x1afae0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1afae0; outside_wrappers=0 unverified
+0x001afc50 impl_cuDevSmResourceSplitByCount high group=cuDevSmResourceSplitByCount variants=cuDevSmResourceSplitByCount; before=0x1afc50,0x2fe540,0x4a7e90,0xd4dc50; after=0x1afc50; outside_wrappers=0 unverified
+0x001afe80 impl_cuGraphicsEGLRegisterImage high group=cuGraphicsEGLRegisterImage variants=cuGraphicsEGLRegisterImage; before=0x1afe80,0x2fe540,0x4a7e90,0xd4dc50; after=0x1afe80; outside_wrappers=0 unverified
+0x001b0130 impl_cuEGLStreamConsumerDisconnect medium group=cuEGLStreamConsumerDisconnect variants=cuEGLStreamConsumerDisconnect; before=0x1b0130,0x2fde50,0x2fe230,0x2fe540,0x350790,0x3c52d0,0x3c5370,0x400550,0x4a7e90,0xd4dc50; after=0x1b0130,0x350790; outside_wrappers=0 unverified
+0x001b02b0 impl_cuEGLStreamProducerDisconnect medium group=cuEGLStreamProducerDisconnect variants=cuEGLStreamProducerDisconnect; before=0x1b02b0,0x2fde50,0x2fe230,0x2fe540,0x350790,0x3c52d0,0x3c5370,0x400550,0x4a7e90,0xd4dc50; after=0x1b02b0,0x350790; outside_wrappers=0 unverified
+0x001b0440 impl_cuEGLStreamConsumerAcquireFrame high group=cuEGLStreamConsumerAcquireFrame variants=cuEGLStreamConsumerAcquireFrame; before=0x1b0440,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b0440; outside_wrappers=0 unverified
+0x001b0960 impl_cuEGLStreamProducerConnect medium group=cuEGLStreamProducerConnect variants=cuEGLStreamProducerConnect; before=0x1b0960,0x26f650,0x270710,0x2fe230,0x2fe540,0x3c52d0,0x3c5370,0x3c54c0,0x4a7e90,0xd4da90,0xd4dc50; after=0x1b0960,0x270710,0x26f650,0x3c54c0; outside_wrappers=0 unverified
+0x001b0af0 impl_cuEGLStreamProducerPresentFrame high group=cuEGLStreamProducerPresentFrame variants=cuEGLStreamProducerPresentFrame; before=0x1b0af0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b0af0; outside_wrappers=0 unverified
+0x001b1370 impl_cuGraphDestroyNode high group=cuGraphDestroyNode variants=cuGraphDestroyNode; before=0x1b1370,0x2a2b90,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1b1370; outside_wrappers=0 unverified
+0x001b1f20 impl_cuGraphAddEmptyNode high group=cuGraphAddEmptyNode variants=cuGraphAddEmptyNode; before=0x1b1f20,0x2a50f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b1f20; outside_wrappers=0 unverified
+0x001b2070 impl_cuGraphAddEventRecordNode high group=cuGraphAddEventRecordNode variants=cuGraphAddEventRecordNode; before=0x1b2070,0x2a50f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b2070; outside_wrappers=0 unverified
+0x001b2190 impl_cuGraphAddEventWaitNode high group=cuGraphAddEventWaitNode variants=cuGraphAddEventWaitNode; before=0x1b2190,0x2a50f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b2190; outside_wrappers=0 unverified
+0x001b23c0 impl_cuEventQuery medium group=cuEventQuery variants=cuEventQuery; before=0x1b23c0,0x288ba0,0x2bb140,0x2fe230,0x2fe540,0x3034c0,0x4a7e90,0xd1e090,0xd4dc50; after=0x1b23c0,0x3034c0; outside_wrappers=0 unverified
+0x001b3370 impl_cuIpcGetEventHandle medium group=cuIpcGetEventHandle variants=cuIpcGetEventHandle; before=0x1b3370,0x2bb420,0x2bbaa0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b3370,0x2bbaa0; outside_wrappers=0 unverified
+0x001b37e0 impl_cuImportExternalMemory high group=cuImportExternalMemory variants=cuImportExternalMemory; before=0x1b37e0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b37e0; outside_wrappers=0 unverified
+0x001b3ab0 impl_cuExternalMemoryGetMappedBuffer medium group=cuExternalMemoryGetMappedBuffer variants=cuExternalMemoryGetMappedBuffer; before=0x1b3ab0,0x28a960,0x2d8f40,0x2fe540,0x4a7e90,0xd4d9a0,0xd4db70,0xd4dc50,0xd51980; after=0x1b3ab0,0x28a960; outside_wrappers=0 unverified
+0x001b3cd0 impl_cuExternalMemoryGetMappedMipmappedArray high group=cuExternalMemoryGetMappedMipmappedArray variants=cuExternalMemoryGetMappedMipmappedArray; before=0x1b3cd0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b3cd0; outside_wrappers=0 unverified
+0x001b3fb0 impl_cuDestroyExternalMemory medium group=cuDestroyExternalMemory variants=cuDestroyExternalMemory; before=0x1b3fb0,0x28b480,0x2d8f40,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1b3fb0,0x28b480; outside_wrappers=0 unverified
+0x001b4110 impl_cuImportExternalSemaphore high group=cuImportExternalSemaphore variants=cuImportExternalSemaphore; before=0x1b4110,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b4110; outside_wrappers=0 unverified
+0x001b50a0 impl_cuFuncSetBlockShape medium group=cuFuncSetBlockShape variants=cuFuncSetBlockShape; before=0x1b50a0,0x2938b0,0x2bb420,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1b50a0,0x2938b0; outside_wrappers=0 unverified
+0x001b5260 impl_cuFuncSetSharedSize medium group=cuFuncSetSharedSize variants=cuFuncSetSharedSize; before=0x1b5260,0x293ae0,0x2bb420,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1b5260,0x293ae0; outside_wrappers=0 unverified
+0x001b53f0 impl_cuFuncSetCacheConfig medium group=cuFuncSetCacheConfig variants=cuFuncSetCacheConfig; before=0x1b53f0,0x262ec0,0x263b80,0x263e10,0x264110,0x2baed0,0x2d8f40,0x2e0770,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1b53f0,0x262ec0,0x264110,0x263b80,0x263e10; outside_wrappers=0 unverified
+0x001b5670 impl_cuFuncSetSharedMemConfig medium group=cuFuncSetSharedMemConfig variants=cuFuncSetSharedMemConfig; before=0x1b5670,0x262ec0,0x263b80,0x263e10,0x264110,0x2baed0,0x2d8f40,0x2e0770,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1b5670,0x262ec0,0x264110,0x263b80,0x263e10; outside_wrappers=0 unverified
+0x001b58f0 impl_cuFuncGetModule high group=cuFuncGetModule variants=cuFuncGetModule; before=0x1b58f0,0x2baed0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b58f0; outside_wrappers=0 unverified
+0x001b5a20 impl_cuFuncIsLoaded high group=cuFuncIsLoaded variants=cuFuncIsLoaded; before=0x1b5a20,0x2baed0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b5a20; outside_wrappers=0 unverified
+0x001b5b70 impl_cuFuncLoad high group=cuFuncLoad variants=cuFuncLoad; before=0x1b5b70,0x2baed0,0x2e0770,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b5b70; outside_wrappers=0 unverified
+0x001b5cb0 impl_cuFuncGetAttribute medium group=cuFuncGetAttribute variants=cuFuncGetAttribute; before=0x1b5cb0,0x293ec0,0x2baed0,0x2dc100,0x2fe540,0x4a7e90,0xd4bd20,0xd4dc50; after=0x1b5cb0,0x293ec0; outside_wrappers=0 unverified
+0x001b5e80 impl_cuFuncSetAttribute medium group=cuFuncSetAttribute variants=cuFuncSetAttribute; before=0x1b5e80,0x293b70,0x2baed0,0x2d8f40,0x2e0770,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1b5e80,0x293b70; outside_wrappers=0 unverified
+0x001b6030 impl_cuModuleGetFunction high group=cuModuleGetFunction variants=cuModuleGetFunction; before=0x1b6030,0x2baed0,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980,0xd6c4a0; after=0x1b6030; outside_wrappers=0 unverified
+0x001b6210 impl_cuGraphicsGLRegisterBuffer medium group=cuGraphicsGLRegisterBuffer variants=cuGraphicsGLRegisterBuffer; before=0x179200,0x1799e0,0x1b6210,0x294fd0,0x2fe230,0x2fe540,0x3c52d0,0x3c5370,0x3c54c0,0x4a7e90,0xd4da90,0xd4dc50; after=0x1b6210,0x294fd0,0x3c54c0; outside_wrappers=0 unverified
+0x001b63e0 impl_cuGraphicsGLRegisterImage high group=cuGraphicsGLRegisterImage variants=cuGraphicsGLRegisterImage; before=0x1b63e0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b63e0; outside_wrappers=0 unverified
+0x001b66e0 impl_cuGLRegisterBufferObject high group=cuGLRegisterBufferObject variants=cuGLRegisterBufferObject; before=0x1b66e0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b66e0; outside_wrappers=0 unverified
+0x001b75f0 impl_cuGraphNodeFindInClone high group=cuGraphNodeFindInClone variants=cuGraphNodeFindInClone; before=0x1b75f0,0x2fe540,0x3aa550,0x4a7e90,0xd4d9a0,0xd4dc50,0xd663e0; after=0x1b75f0; outside_wrappers=0 unverified
+0x001b7e60 impl_cuGLUnregisterBufferObject high group=cuGLUnregisterBufferObject variants=cuGLUnregisterBufferObject; before=0x1b7e60,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b7e60; outside_wrappers=0 unverified
+0x001b8090 impl_cuGLSetBufferObjectMapFlags high group=cuGLSetBufferObjectMapFlags variants=cuGLSetBufferObjectMapFlags; before=0x1b8090,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b8090; outside_wrappers=0 unverified
+0x001b8580 impl_cuUserObjectRetain high group=cuUserObjectRetain variants=cuUserObjectRetain; before=0x179200,0x1b8580,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b8580; outside_wrappers=0 unverified
+0x001b8670 impl_cuUserObjectRelease high group=cuUserObjectRelease variants=cuUserObjectRelease; before=0x179200,0x1b8670,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b8670; outside_wrappers=0 unverified
+0x001b8760 impl_cuGraphRetainUserObject medium group=cuGraphRetainUserObject variants=cuGraphRetainUserObject; before=0x1792f0,0x179350,0x1b8760,0x2fe540,0x4a7e90,0xd4dc50,0xd6a780; after=0x1b8760,0xd6a780; outside_wrappers=0 unverified
+0x001b8900 impl_cuGraphReleaseUserObject medium group=cuGraphReleaseUserObject variants=cuGraphReleaseUserObject; before=0x1792f0,0x179350,0x1b8900,0x2fe540,0x4a7e90,0xd4dc50,0xd6a780; after=0x1b8900,0xd6a780; outside_wrappers=0 unverified
+0x001b8ba0 impl_cuGraphGetEdges medium group=cuGraphGetEdges variants=cuGraphGetEdges,cuGraphGetEdges_v2; before=0x1b8ba0,0x2a69b0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1b8ba0,0x2a69b0; outside_wrappers=0 unverified
+0x001b8fd0 impl_cuGraphExecDestroy medium group=cuGraphExecDestroy variants=cuGraphExecDestroy; before=0x1b8fd0,0x1c1c60,0x2a3530,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b8fd0,0x2a3530; outside_wrappers=0 unverified
+0x001b96b0 impl_cuGraphExecMemcpyNodeSetParams medium group=cuGraphExecMemcpyNodeSetParams variants=cuGraphExecMemcpyNodeSetParams; before=0x1b96b0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b96b0; outside_wrappers=1 unverified
+0x001b9830 impl_cuGraphExecMemsetNodeSetParams medium group=cuGraphExecMemsetNodeSetParams variants=cuGraphExecMemsetNodeSetParams; before=0x1b9830,0x2fe540,0x4a7e90,0xd4dc50; after=0x1b9830; outside_wrappers=1 unverified
+0x001ba6f0 impl_cuGraphAddHostNode high group=cuGraphAddHostNode variants=cuGraphAddHostNode; before=0x1ba6f0,0x2a63a0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ba6f0; outside_wrappers=0 unverified
+0x001baec0 impl_cuGraphAddDependencies high group=cuGraphAddDependencies variants=cuGraphAddDependencies,cuGraphAddDependencies_v2; before=0x1baec0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1baec0; outside_wrappers=0 unverified
+0x001bb0c0 impl_cuGraphRemoveDependencies high group=cuGraphRemoveDependencies variants=cuGraphRemoveDependencies,cuGraphRemoveDependencies_v2; before=0x1bb0c0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1bb0c0; outside_wrappers=0 unverified
+0x001bb960 impl_cuMemcpyBatchAsync medium group=cuMemcpyBatchAsync variants=cuMemcpyBatchAsync_ptsz,cuMemcpyBatchAsync; before=0x1bb8a0,0x1bb960,0x1bddb0,0x2baed0,0x2f16c0,0x2fde50,0x2fe540,0x4a7e90,0xd4dc50; after=0x1bb960,0x1bddb0,0x1bb8a0; outside_wrappers=0 unverified
+0x001be0e0 impl_cuMemcpy3DBatchAsync high group=cuMemcpy3DBatchAsync variants=cuMemcpy3DBatchAsync_ptsz,cuMemcpy3DBatchAsync; before=0x1be0e0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1be0e0; outside_wrappers=0 unverified
+0x001be900 impl_cuCtxDestroy high group=cuCtxDestroy variants=cuCtxDestroy_v2,cuCtxDestroy; before=0x1be900,0x26d8e0,0x2baed0,0x2fde50,0x2fe0f0,0x2fe540,0x4a7e90,0xd4da50,0xd4dc50; after=0x1be900; outside_wrappers=0 verified
+0x001bea40 impl_cuCtxPushCurrent medium group=cuCtxPushCurrent variants=cuCtxPushCurrent_v2,cuCtxPushCurrent; before=0x1bea40,0x24a4d0,0x24b930,0x2fde50,0x2fe020,0x2fe540,0x4a7e90,0xd4dc50,0xd4f3e0; after=0x1bea40,0x24b930; outside_wrappers=0 unverified
+0x001bec50 impl_cuCtxPopCurrent medium group=cuCtxPopCurrent variants=cuCtxPopCurrent_v2,cuCtxPopCurrent; before=0x1bec50,0x24a4d0,0x24b9e0,0x2fde50,0x2fe0f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1bec50,0x24b9e0; outside_wrappers=0 unverified
+0x001bee20 impl_cuDeviceGetNvSciSyncAttributes medium group=cuDeviceGetNvSciSyncAttributes variants=cuDeviceGetNvSciSyncAttributes; before=0x1bee20,0x1bf270,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1bee20,0x1bf270; outside_wrappers=0 unverified
+0x001bf3e0 impl_cuDeviceGetDefaultMemPool medium group=cuDeviceGetDefaultMemPool variants=cuDeviceGetDefaultMemPool; before=0x1798f0,0x1bf3e0,0x1bf560,0x2fe440,0x2fe540,0x4a7e90,0xd4dc50; after=0x1bf3e0,0x1bf560; outside_wrappers=0 unverified
+0x001bf660 impl_cuCtxGetDevResource high group=cuCtxGetDevResource variants=cuCtxGetDevResource; before=0x1bf660,0x2baed0,0x2bb140,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1bf660; outside_wrappers=0 unverified
+0x001bf820 impl_cuGreenCtxGetDevResource high group=cuGreenCtxGetDevResource variants=cuGreenCtxGetDevResource; before=0x1bf820,0x2baed0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1bf820; outside_wrappers=0 unverified
+0x001bf970 impl_cuDevResourceGenerateDesc high group=cuDevResourceGenerateDesc variants=cuDevResourceGenerateDesc; before=0x1bf970,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1bf970; outside_wrappers=0 unverified
+0x001c0120 impl_cuEGLStreamConsumerConnect medium group=cuEGLStreamConsumerConnect variants=cuEGLStreamConsumerConnect; before=0x1c0120,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c0120; outside_wrappers=1 unverified
+0x001c0120 impl_cuEGLStreamConsumerConnectWithFlags medium group=cuEGLStreamConsumerConnectWithFlags variants=cuEGLStreamConsumerConnectWithFlags; before=0x1c0120,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c0120; outside_wrappers=1 unverified
+0x001c0930 impl_cuStreamBatchMemOp high group=cuStreamBatchMemOp variants=cuStreamBatchMemOp_v2_ptsz,cuStreamBatchMemOp,cuStreamBatchMemOp_ptsz,cuStreamBatchMemOp_v2; before=0x1c0930,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c0930; outside_wrappers=0 unverified
+0x001c0d00 impl_cuGraphBatchMemOpNodeSetParams medium group=cuGraphBatchMemOpNodeSetParams variants=cuGraphBatchMemOpNodeSetParams; before=0x179200,0x179a80,0x179c00,0x1c0740,0x1c0d00,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c0d00; outside_wrappers=1 unverified
+0x001c0f70 impl_cuSignalExternalSemaphoresAsync high group=cuSignalExternalSemaphoresAsync variants=cuSignalExternalSemaphoresAsync_ptsz,cuSignalExternalSemaphoresAsync; before=0x1c0f70,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c0f70; outside_wrappers=0 unverified
+0x001c12c0 impl_cuWaitExternalSemaphoresAsync high group=cuWaitExternalSemaphoresAsync variants=cuWaitExternalSemaphoresAsync_ptsz,cuWaitExternalSemaphoresAsync; before=0x1c12c0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c12c0; outside_wrappers=0 unverified
+0x001c15f0 impl_cuDestroyExternalSemaphore medium group=cuDestroyExternalSemaphore variants=cuDestroyExternalSemaphore; before=0x1798f0,0x1c15f0,0x1c1730,0x2fe230,0x2fe440,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c15f0,0x1c1730; outside_wrappers=0 unverified
+0x001c1820 impl_cuGLCtxCreate high group=cuGLCtxCreate variants=cuGLCtxCreate_v2,cuGLCtxCreate; before=0x1c1820,0x2689e0,0x26d8e0,0x277680,0x2fe020,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c1820; outside_wrappers=0 unverified
+0x001c2060 impl_cuGraphAddKernelNode high group=cuGraphAddKernelNode variants=cuGraphAddKernelNode_v2,cuGraphAddKernelNode; before=0x1c2060,0x1c2b10,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c2060; outside_wrappers=0 unverified
+0x001c2570 impl_cuGraphAddMemsetNode medium group=cuGraphAddMemsetNode variants=cuGraphAddMemsetNode; before=0x1c2570,0x2a64e0,0x2baed0,0x2bb140,0x2ded70,0x2fde50,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1c2570,0x2ded70,0x2a64e0; outside_wrappers=0 unverified
+0x001c2830 impl_cuGraphMemsetNodeSetParams medium group=cuGraphMemsetNodeSetParams variants=cuGraphMemsetNodeSetParams; before=0x1c2830,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c2830; outside_wrappers=1 unverified
+0x001c3c80 impl_cuGraphKernelNodeCopyAttributes high group=cuGraphKernelNodeCopyAttributes variants=cuGraphKernelNodeCopyAttributes; before=0x1c2b10,0x1c3c80,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c3c80; outside_wrappers=0 unverified
+0x001c3e90 impl_cuGraphKernelNodeGetAttribute high group=cuGraphKernelNodeGetAttribute variants=cuGraphKernelNodeGetAttribute; before=0x1c3e90,0x2d8f40,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50,0xd51980; after=0x1c3e90; outside_wrappers=0 unverified
+0x001c4540 impl_cuGraphKernelNodeSetAttribute medium group=cuGraphKernelNodeSetAttribute variants=cuGraphKernelNodeSetAttribute; before=0x1c40f0,0x1c4540,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1c4540,0x1c40f0; outside_wrappers=0 unverified
+0x001c4a90 impl_cuGraphExecNodeSetParams medium group=cuGraphExecNodeSetParams variants=cuGraphExecNodeSetParams; before=0x1a39d0,0x1b96b0,0x1b9830,0x1b9a90,0x1b9ea0,0x1c0e20,0x1c3870,0x1c4920,0x1c4a90,0x2ac1b0,0x2b4f80,0x2fe540,0x4a7e90,0xd183b0,0xd4dc50; after=0x1c4a90,0x1b9a90,0x1b9ea0,0x1a39d0,0x2b4f80,0x1c3870,0x1b96b0,0x1c0e20,0x1b9830,0x2ac1b0,0x1c4920; outside_wrappers=0 unverified
+0x001c4d50 impl_cuGraphMemcpyNodeSetParams medium group=cuGraphMemcpyNodeSetParams variants=cuGraphMemcpyNodeSetParams; before=0x1c4d50,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1c4d50; outside_wrappers=1 unverified
+0x001c4e80 impl_cuGraphNodeSetParams medium group=cuGraphNodeSetParams variants=cuGraphNodeSetParams; before=0x1c0d00,0x1c2830,0x1c2a00,0x1c3750,0x1c4920,0x1c4d50,0x1c4e80,0x2a9f60,0x2aa190,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1c4e80,0x1c2a00,0x1c2830,0x1c0d00,0x1c4d50,0x1c3750,0x1c4920; outside_wrappers=0 unverified
+0x001c51c0 impl_cuGraphAddMemcpyNode medium group=cuGraphAddMemcpyNode variants=cuGraphAddMemcpyNode; before=0x1c51c0,0x2a60a0,0x2baed0,0x2bb140,0x2d7780,0x2fde50,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1c51c0,0x2a60a0,0x2d7780; outside_wrappers=0 unverified
+0x001c53e0 impl_cuGraphAddNode high group=cuGraphAddNode variants=cuGraphAddNode,cuGraphAddNode_v2; before=0x1c53e0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c53e0; outside_wrappers=0 unverified
+0x001c6360 impl_cuMemExportToShareableHandle high group=cuMemExportToShareableHandle variants=cuMemExportToShareableHandle; before=0x1c6360,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1c6360; outside_wrappers=0 unverified
+0x001c64f0 impl_cuLibraryGetKernel high group=cuLibraryGetKernel variants=cuLibraryGetKernel; before=0x1c64f0,0x2fe540,0x3aa550,0x4a7e90,0xd4d9a0,0xd4dc50,0xd663e0; after=0x1c64f0; outside_wrappers=0 unverified
+0x001c6610 impl_cuLibraryGetManaged high group=cuLibraryGetManaged variants=cuLibraryGetManaged; before=0x1c6610,0x2fe540,0x3aa550,0x4a7e90,0xd4d9a0,0xd4dc50,0xd663e0; after=0x1c6610; outside_wrappers=0 unverified
+0x001c69f0 impl_cuMemGetAllocationGranularity high group=cuMemGetAllocationGranularity variants=cuMemGetAllocationGranularity; before=0x1c69f0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1c69f0; outside_wrappers=0 unverified
+0x001c6ec0 impl_cuGreenCtxRecordEvent high group=cuGreenCtxRecordEvent variants=cuGreenCtxRecordEvent; before=0x1792f0,0x179350,0x1c6ec0,0x2886b0,0x2895f0,0x2baed0,0x2f8e10,0x2f8fd0,0x2fe540,0x4a7e90,0xd1e3f0,0xd4d9a0,0xd4dc50; after=0x1c6ec0; outside_wrappers=0 unverified
+0x001c7000 impl_cuGreenCtxWaitEvent medium group=cuGreenCtxWaitEvent variants=cuGreenCtxWaitEvent; before=0x1c7000,0x2baed0,0x2ed7d0,0x2fe540,0x4a7e90,0xd1e230,0xd1e3f0,0xd4d9a0,0xd4dc50; after=0x1c7000,0xd1e230; outside_wrappers=0 unverified
+0x001c7120 impl_cuGreenCtxStreamCreate medium group=cuGreenCtxStreamCreate variants=cuGreenCtxStreamCreate; before=0x1c7120,0x2baed0,0x2ef570,0x2f0fb0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50,0xd613b0; after=0x1c7120,0x2ef570,0x2f0fb0,0xd613b0; outside_wrappers=0 unverified
+0x001c73e0 impl_cuGraphicsResourceGetMappedMipmappedArray high group=cuGraphicsResourceGetMappedMipmappedArray variants=cuGraphicsResourceGetMappedMipmappedArray; before=0x1798f0,0x1c73e0,0x2baed0,0x2fe440,0x2fe540,0x3c52d0,0x3c5370,0x4a7e90,0xd4dc50; after=0x1c73e0; outside_wrappers=0 unverified
+0x001c7530 impl_cuGraphicsSubResourceGetMappedArray high group=cuGraphicsSubResourceGetMappedArray variants=cuGraphicsSubResourceGetMappedArray; before=0x1c7530,0x2baed0,0x2fe540,0x3c52d0,0x3c5370,0x4a7e90,0xd4dc50; after=0x1c7530; outside_wrappers=0 unverified
+0x001c7cf0 impl_cuMemPoolGetAccess high group=cuMemPoolGetAccess variants=cuMemPoolGetAccess; before=0x1c7cf0,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c7cf0; outside_wrappers=0 unverified
+0x001c7ed0 impl_cuGraphicsUnregisterResource high group=cuGraphicsUnregisterResource variants=cuGraphicsUnregisterResource; before=0x1c7ed0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1c7ed0; outside_wrappers=0 unverified
+0x001c80b0 impl_cuGraphicsResourceGetMappedEglFrame high group=cuGraphicsResourceGetMappedEglFrame variants=cuGraphicsResourceGetMappedEglFrame; before=0x1c80b0,0x2baed0,0x2fde50,0x2fe540,0x3c52d0,0x3c5370,0x4a7e90,0xd4dc50; after=0x1c80b0; outside_wrappers=0 unverified
+0x001c94b0 impl_cuMemPoolExportPointer high group=cuMemPoolExportPointer variants=cuMemPoolExportPointer; before=0x1792f0,0x179350,0x1c94b0,0x2fe230,0x2fe540,0x3fe100,0x4a7e90,0xd4dc50; after=0x1c94b0; outside_wrappers=0 unverified
+0x001c9700 impl_cuMemGetAllocationPropertiesFromHandle high group=cuMemGetAllocationPropertiesFromHandle variants=cuMemGetAllocationPropertiesFromHandle; before=0x1c9700,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1c9700; outside_wrappers=0 unverified
+0x001c9b90 impl_cuKernelGetParamInfo high group=cuKernelGetParamInfo variants=cuKernelGetParamInfo; before=0x1c9b90,0x2bb420,0x2bfad0,0x2fe540,0x4a7e90,0xd4dc50,0xd6c4a0; after=0x1c9b90; outside_wrappers=0 unverified
+0x001c9d80 impl_cuLibraryLoadFromFile medium group=cuLibraryLoadFromFile variants=cuLibraryLoadFromFile; before=0x179200,0x1c9d80,0x2bbd30,0x2d3f60,0x2df390,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1c9d80,0x2d3f60; outside_wrappers=0 unverified
+0x001c9f90 impl_cuLibraryGetGlobal high group=cuLibraryGetGlobal variants=cuLibraryGetGlobal; before=0x1c9f90,0x2bb420,0x2bfad0,0x2f9f00,0x2fe540,0x402500,0x4a7e90,0xd4dc50; after=0x1c9f90; outside_wrappers=0 unverified
+0x001ca790 impl_cuCtxGetLimit medium group=cuCtxGetLimit variants=cuCtxGetLimit; before=0x1ca790,0x2bb420,0x2c0400,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1ca790,0x2c0400; outside_wrappers=0 unverified
+0x001ca940 impl_cuMemHostUnregister high group=cuMemHostUnregister variants=cuMemHostUnregister; before=0x1ca940,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ca940; outside_wrappers=0 unverified
+0x001cab60 impl_cuMemAllocManaged high group=cuMemAllocManaged variants=cuMemAllocManaged; before=0x1cab60,0x2fe540,0x4a7e90,0xd4dc50; after=0x1cab60; outside_wrappers=0 unverified
+0x001cb030 impl_cuMemRangeGetAttributes medium group=cuMemRangeGetAttributes variants=cuMemRangeGetAttributes; before=0x1cb030,0x2fe540,0x4a7e90,0xd4dc50; after=0x1cb030; outside_wrappers=1 unverified
+0x001cbda0 impl_cuMemHostGetFlags high group=cuMemHostGetFlags variants=cuMemHostGetFlags; before=0x1cbda0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1cbda0; outside_wrappers=0 unverified
+0x001cc6f0 impl_cuIpcGetMemHandle medium group=cuIpcGetMemHandle variants=cuIpcGetMemHandle; before=0x1cc6f0,0x2bb420,0x2bbaa0,0x2fe540,0x3fe700,0x402500,0x4a7e90,0xd4bd90,0xd4dc50; after=0x1cc6f0,0x2bbaa0; outside_wrappers=0 unverified
+0x001ccb30 impl_cuIpcCloseMemHandle high group=cuIpcCloseMemHandle variants=cuIpcCloseMemHandle; before=0x1ccb30,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ccb30; outside_wrappers=0 unverified
+0x001ccd30 impl_cuMemGetHandleForAddressRange high group=cuMemGetHandleForAddressRange variants=cuMemGetHandleForAddressRange; before=0x1795e0,0x1ccd30,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ccd30; outside_wrappers=0 unverified
+0x001d2a60 impl_cuMemAddressReserve medium group=cuMemAddressReserve variants=cuMemAddressReserve; before=0x1792f0,0x179350,0x1795e0,0x1d2a60,0x2d8ae0,0x2fe540,0x3acc80,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1d2a60,0x3acc80,0x2d8ae0; outside_wrappers=0 unverified
+0x001d2c30 impl_cuMemAddressFree medium group=cuMemAddressFree variants=cuMemAddressFree; before=0x1792f0,0x179350,0x1795e0,0x1d2c30,0x2d8c30,0x2fe540,0x306160,0x3ac0f0,0x3ac3f0,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1d2c30,0x2d8c30,0x3ac0f0; outside_wrappers=0 unverified
+0x001d2f80 impl_cuMemPoolImportPointer high group=cuMemPoolImportPointer variants=cuMemPoolImportPointer; before=0x1d2f80,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d2f80; outside_wrappers=0 unverified
+0x001d3bf0 impl_cuMemUnmap high group=cuMemUnmap variants=cuMemUnmap; before=0x1d3bf0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d3bf0; outside_wrappers=0 unverified
+0x001d4010 impl_cuMemImportFromShareableHandle high group=cuMemImportFromShareableHandle variants=cuMemImportFromShareableHandle; before=0x1d4010,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d4010; outside_wrappers=0 unverified
+0x001d4800 impl_cuMemRetainAllocationHandle medium group=cuMemRetainAllocationHandle variants=cuMemRetainAllocationHandle; before=0x1792f0,0x179350,0x1d4800,0x257620,0x2fe540,0x3ac3f0,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1d4800,0x257620; outside_wrappers=0 unverified
+0x001d5020 impl_cuMemPoolTrimTo medium group=cuMemPoolTrimTo variants=cuMemPoolTrimTo; before=0x1792f0,0x179350,0x1d5020,0x2c51a0,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d5020,0x2c51a0; outside_wrappers=0 unverified
+0x001d5180 impl_cuMemPoolSetAttribute medium group=cuMemPoolSetAttribute variants=cuMemPoolSetAttribute; before=0x1792f0,0x179350,0x1d5180,0x2db020,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d5180,0x2db020; outside_wrappers=0 unverified
+0x001d52d0 impl_cuMemPoolGetAttribute medium group=cuMemPoolGetAttribute variants=cuMemPoolGetAttribute; before=0x1792f0,0x179350,0x1d52d0,0x2db110,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d52d0,0x2db110; outside_wrappers=0 unverified
+0x001d5430 impl_cuMemPoolSetAccess high group=cuMemPoolSetAccess variants=cuMemPoolSetAccess; before=0x1d5430,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d5430; outside_wrappers=0 unverified
+0x001d5a00 impl_cuMemPoolExportToShareableHandle medium group=cuMemPoolExportToShareableHandle variants=cuMemPoolExportToShareableHandle; before=0x1792f0,0x179350,0x1799e0,0x1d5a00,0x2c6e60,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d5a00,0x2c6e60; outside_wrappers=0 unverified
+0x001d5c60 impl_cuMemPoolImportFromShareableHandle medium group=cuMemPoolImportFromShareableHandle variants=cuMemPoolImportFromShareableHandle; before=0x1792f0,0x179350,0x179450,0x1799e0,0x1d5c60,0x28d350,0x2c3b00,0x2fe230,0x2fe540,0x30a9d0,0x3aa550,0x3ab420,0x4a7e90,0xd4dc50,0xd663e0; after=0x1d5c60,0x28d350,0x3ab420,0x30a9d0,0x2c3b00; outside_wrappers=0 unverified
+0x001d5ed0 impl_cuGraphExecUpdate high group=cuGraphExecUpdate variants=cuGraphExecUpdate_v2,cuGraphExecUpdate; before=0x1d5ed0,0x2fe540,0x4a7e90,0xd4da50,0xd4dc50; after=0x1d5ed0; outside_wrappers=0 unverified
+0x001d61c0 impl_cuGraphConditionalHandleCreate high group=cuGraphConditionalHandleCreate variants=cuGraphConditionalHandleCreate; before=0x1d61c0,0x2baed0,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d61c0; outside_wrappers=0 unverified
+0x001d6410 impl_cuGraphicsResourceSetMapFlags high group=cuGraphicsResourceSetMapFlags variants=cuGraphicsResourceSetMapFlags_v2,cuGraphicsResourceSetMapFlags; before=0x1d6410,0x2baed0,0x2fe540,0x3c52d0,0x3c5370,0x4a7e90,0xd4dc50; after=0x1d6410; outside_wrappers=0 unverified
+0x001d65a0 impl_cuGraphicsMapResources high group=cuGraphicsMapResources variants=cuGraphicsMapResources_ptsz,cuGraphicsMapResources; before=0x1d65a0,0x2baed0,0x2f16c0,0x2fe230,0x2fe540,0x3c52d0,0x3c5370,0x4a7e90,0xd4dc50; after=0x1d65a0; outside_wrappers=0 unverified
+0x001d67a0 impl_cuGraphicsUnmapResources high group=cuGraphicsUnmapResources variants=cuGraphicsUnmapResources_ptsz,cuGraphicsUnmapResources; before=0x1d67a0,0x2baed0,0x2f16c0,0x2fe230,0x2fe540,0x3c52d0,0x3c5370,0x4a7e90,0xd4dc50; after=0x1d67a0; outside_wrappers=0 unverified
+0x001d69a0 impl_cuLinkAddFile medium group=cuLinkAddFile variants=cuLinkAddFile_v2,cuLinkAddFile; before=0x179200,0x1d69a0,0x2bbd30,0x2d2990,0x2df390,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d69a0,0x2df390; outside_wrappers=0 unverified
+0x001d7d70 impl_cuLaunchCooperativeKernelMultiDevice high group=cuLaunchCooperativeKernelMultiDevice variants=cuLaunchCooperativeKernelMultiDevice; before=0x1d7d70,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d7d70; outside_wrappers=0 unverified
+0x001d9540 impl_cuKernelSetCacheConfig high group=cuKernelSetCacheConfig variants=cuKernelSetCacheConfig; before=0x1d9540,0x2bb420,0x2fe540,0x4a7e90,0xd4dc50; after=0x1d9540; outside_wrappers=0 unverified
+0x001da450 impl_cuMemFree high group=cuMemFree variants=cuMemFree_v2,cuMemFree; before=0x1da450,0x2fe540,0x4a7e90,0xd4dc50; after=0x1da450; outside_wrappers=0 verified
+0x001da880 impl_cuMemFreeHost high group=cuMemFreeHost variants=cuMemFreeHost; before=0x1da880,0x2fe540,0x4a7e90,0xd4dc50; after=0x1da880; outside_wrappers=0 verified
+0x001daad0 impl_cuMemAllocHost high group=cuMemAllocHost variants=cuMemAllocHost_v2,cuMemAllocHost; before=0x1daad0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1daad0; outside_wrappers=1 unverified
+0x001dae90 impl_cuMemPrefetchAsync high group=cuMemPrefetchAsync variants=cuMemPrefetchAsync_ptsz,cuMemPrefetchAsync_v2_ptsz,cuMemPrefetchAsync,cuMemPrefetchAsync_v2; before=0x1dae90,0x2fe540,0x4a7e90,0xd4dc50; after=0x1dae90; outside_wrappers=0 unverified
+0x001db0f0 impl_cuMemAdvise high group=cuMemAdvise variants=cuMemAdvise,cuMemAdvise_v2; before=0x1db0f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1db0f0; outside_wrappers=0 unverified
+0x001dbdd0 impl_cuPointerGetAttributes medium group=cuPointerGetAttributes variants=cuPointerGetAttributes; before=0x1db310,0x1dbdd0,0x2bb300,0x2fe540,0x3fe100,0x402500,0x4a7e90,0xd4dc50; after=0x1dbdd0,0x1db310; outside_wrappers=0 unverified
+0x001dc060 impl_cuMemHostGetDevicePointer medium group=cuMemHostGetDevicePointer variants=cuMemHostGetDevicePointer_v2,cuMemHostGetDevicePointer; before=0x1792f0,0x179350,0x1dc060,0x2bb300,0x2fe540,0x3ac3f0,0x4026d0,0x403470,0x4a7e90,0xd4dc50; after=0x1dc060,0x4026d0; outside_wrappers=0 unverified
+0x001dc310 impl_cuMemHostRegister high group=cuMemHostRegister variants=cuMemHostRegister_v2,cuMemHostRegister; before=0x1dc310,0x2fe540,0x4a7e90,0xd4dc50; after=0x1dc310; outside_wrappers=0 unverified
+0x001dc640 impl_cuIpcOpenMemHandle medium group=cuIpcOpenMemHandle variants=cuIpcOpenMemHandle_v2,cuIpcOpenMemHandle; before=0x1dc640,0x2bb420,0x2c1d40,0x2d8f40,0x2e7bf0,0x2fe540,0x400550,0x403330,0x4a7e90,0xd4dc50,0xd51980; after=0x1dc640,0x403330; outside_wrappers=0 unverified
+0x001dc7c0 impl_cuPointerSetAttribute medium group=cuPointerSetAttribute variants=cuPointerSetAttribute; before=0x1dc7c0,0x1dcc50,0x2fde50,0x2fe230,0x2fe540,0x3fe100,0x402500,0x4a7e90,0xd4dc50; after=0x1dc7c0,0x1dcc50; outside_wrappers=0 unverified
+0x001dc9b0 impl_cuPointerGetAttribute high group=cuPointerGetAttribute variants=cuPointerGetAttribute; before=0x1dc9b0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1dc9b0; outside_wrappers=0 unverified
+0x001dfbe0 impl_cuMemSetAccess medium group=cuMemSetAccess variants=cuMemSetAccess; before=0x1dfbe0,0x1e0420,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1dfbe0,0x1e0420; outside_wrappers=0 unverified
+0x001e0640 impl_cuMemGetAccess medium group=cuMemGetAccess variants=cuMemGetAccess; before=0x1e0640,0x1e0950,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1e0640,0x1e0950; outside_wrappers=0 unverified
+0x001e0b40 impl_cuMemAllocFromPoolAsync high group=cuMemAllocFromPoolAsync variants=cuMemAllocFromPoolAsync_ptsz,cuMemAllocFromPoolAsync; before=0x1e0b40,0x2f16c0,0x2fe230,0x2fe540,0x3c7f40,0x4a7e90,0xd4dc50; after=0x1e0b40; outside_wrappers=0 unverified
+0x001e0cb0 impl_cuMemCreate high group=cuMemCreate variants=cuMemCreate; before=0x1e0cb0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1e0cb0; outside_wrappers=0 unverified
+0x001e18f0 impl_cuMemMap high group=cuMemMap variants=cuMemMap; before=0x1e18f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1e18f0; outside_wrappers=0 unverified
+0x001e9ab0 impl_cuModuleLoad high group=cuModuleLoad variants=cuModuleLoad; before=0x1e9ab0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1e9ab0; outside_wrappers=0 verified
+0x001e9d80 impl_cuModuleLoadData high group=cuModuleLoadData variants=cuModuleLoadData; before=0x1e9d80,0x2fe540,0x4a7e90,0xd4dc50; after=0x1e9d80; outside_wrappers=0 verified
+0x001ea020 impl_cuModuleLoadFatBinary high group=cuModuleLoadFatBinary variants=cuModuleLoadFatBinary; before=0x1ea020,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ea020; outside_wrappers=0 unverified
+0x001ea370 impl_cuTensorMapEncodeTiled high group=cuTensorMapEncodeTiled variants=cuTensorMapEncodeTiled; before=0x1ea370,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50; after=0x1ea370; outside_wrappers=0 unverified
+0x001ea530 impl_cuTensorMapEncodeIm2col high group=cuTensorMapEncodeIm2col variants=cuTensorMapEncodeIm2col; before=0x1ea530,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50; after=0x1ea530; outside_wrappers=0 unverified
+0x001ea6f0 impl_cuTensorMapEncodeIm2colWide high group=cuTensorMapEncodeIm2colWide variants=cuTensorMapEncodeIm2colWide; before=0x1ea6f0,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50; after=0x1ea6f0; outside_wrappers=0 unverified
+0x001ea8f0 impl_cuTensorMapReplaceAddress high group=cuTensorMapReplaceAddress variants=cuTensorMapReplaceAddress; before=0x1798f0,0x1ea8f0,0x2fe440,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50; after=0x1ea8f0; outside_wrappers=0 unverified
+0x001ea9d0 impl_cuModuleLoadDataEx high group=cuModuleLoadDataEx variants=cuModuleLoadDataEx; before=0x1ea9d0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ea9d0; outside_wrappers=0 unverified
+0x001eb4d0 impl_cuSurfRefGetArray high group=cuSurfRefGetArray variants=cuSurfRefGetArray; before=0x1eb4d0,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x1eb4d0; outside_wrappers=0 unverified
+0x001eb960 impl_cuModuleGetTexRef medium group=cuModuleGetTexRef variants=cuModuleGetTexRef; before=0x179980,0x1eb960,0x2baed0,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1eb960,0x179980; outside_wrappers=0 unverified
+0x001ebb60 impl_cuModuleGetSurfRef medium group=cuModuleGetSurfRef variants=cuModuleGetSurfRef; before=0x179980,0x1ebb60,0x2baed0,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1ebb60,0x179980; outside_wrappers=0 unverified
+0x001ec6e0 impl_cuParamSetSize high group=cuParamSetSize variants=cuParamSetSize; before=0x1ec6e0,0x2bb420,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1ec6e0; outside_wrappers=0 unverified
+0x001ec8b0 impl_cuParamSetTexRef high group=cuParamSetTexRef variants=cuParamSetTexRef; before=0x1ec8b0,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50; after=0x1ec8b0; outside_wrappers=0 unverified
+0x001eca70 impl_cuOccupancyAvailableDynamicSMemPerBlock high group=cuOccupancyAvailableDynamicSMemPerBlock variants=cuOccupancyAvailableDynamicSMemPerBlock; before=0x1eca70,0x2fe540,0x4a7e90,0xd4dc50; after=0x1eca70; outside_wrappers=0 unverified
+0x001ecf80 impl_cuParamSetv high group=cuParamSetv variants=cuParamSetv; before=0x179c00,0x1ecf80,0x2bb420,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1ecf80; outside_wrappers=0 unverified
+0x001ed180 impl_cuParamSeti high group=cuParamSeti variants=cuParamSeti; before=0x1ed180,0x2bb420,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1ed180; outside_wrappers=0 unverified
+0x001ed340 impl_cuParamSetf high group=cuParamSetf variants=cuParamSetf; before=0x1ed340,0x2bb420,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1ed340; outside_wrappers=0 unverified
+0x001ed5c0 impl_cuProfilerStart medium group=cuProfilerStart variants=cuProfilerStart; before=0x1798f0,0x1ed5c0,0x2fe230,0x2fe440,0x2fe540,0x4a7e90,0xd4db70,0xd4dc50; after=0x1ed5c0; outside_wrappers=1 unverified
+0x001ed5c0 impl_cuProfilerStop medium group=cuProfilerStop variants=cuProfilerStop; before=0x1798f0,0x1ed5c0,0x2fe230,0x2fe440,0x2fe540,0x4a7e90,0xd4db70,0xd4dc50; after=0x1ed5c0; outside_wrappers=1 unverified
+0x001ed720 impl_cuSurfObjectGetResourceDesc high group=cuSurfObjectGetResourceDesc variants=cuSurfObjectGetResourceDesc; before=0x1ed720,0x2d8f40,0x2fe540,0x4a7e90,0xd4db70,0xd4dc50,0xd51980; after=0x1ed720; outside_wrappers=0 unverified
+0x001ed850 impl_cuTexObjectGetResourceDesc high group=cuTexObjectGetResourceDesc variants=cuTexObjectGetResourceDesc; before=0x1ed850,0x2d8f40,0x2fe540,0x4a7e90,0xd4db70,0xd4dc50,0xd51980; after=0x1ed850; outside_wrappers=0 unverified
+0x001eda80 impl_cuTexObjectGetTextureDesc high group=cuTexObjectGetTextureDesc variants=cuTexObjectGetTextureDesc; before=0x1eda80,0x2d8f40,0x2fe540,0x4a7e90,0xd4db70,0xd4dc50,0xd51980; after=0x1eda80; outside_wrappers=0 unverified
+0x001edc80 impl_cuTexObjectGetResourceViewDesc high group=cuTexObjectGetResourceViewDesc variants=cuTexObjectGetResourceViewDesc; before=0x1edc80,0x2d8f40,0x2fe540,0x4a7e90,0xd4db70,0xd4dc50,0xd51980; after=0x1edc80; outside_wrappers=0 unverified
+0x001f0fd0 impl_cuSurfObjectDestroy medium group=cuSurfObjectDestroy variants=cuSurfObjectDestroy; before=0x1f0fd0,0x2d8f40,0x2f9890,0x2fe230,0x2fe540,0x4a7e90,0xd4db70,0xd4dc50,0xd51980; after=0x1f0fd0,0x2f9890; outside_wrappers=0 unverified
+0x001f11d0 impl_cuSurfRefSetArray high group=cuSurfRefSetArray variants=cuSurfRefSetArray; before=0x1f11d0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1f11d0; outside_wrappers=0 unverified
+0x001f1540 impl_cuSurfObjectCreate high group=cuSurfObjectCreate variants=cuSurfObjectCreate; before=0x1f1540,0x2fe540,0x4a7e90,0xd4dc50; after=0x1f1540; outside_wrappers=0 unverified
+0x001f2970 impl_cuTexObjectCreate high group=cuTexObjectCreate variants=cuTexObjectCreate; before=0x1f2970,0x2fe540,0x4a7e90,0xd4dc50; after=0x1f2970; outside_wrappers=0 unverified
+0x001f35d0 impl_cuTexObjectDestroy medium group=cuTexObjectDestroy variants=cuTexObjectDestroy; before=0x1f35d0,0x2d8f40,0x2fbad0,0x2fe230,0x2fe540,0x4a6e10,0x4a7e90,0xd4db70,0xd4dc50,0xd51980; after=0x1f35d0,0x4a6e10,0x2fbad0; outside_wrappers=0 unverified
+0x001f3830 impl_cuTexRefDestroy medium group=cuTexRefDestroy variants=cuTexRefDestroy; before=0x1798f0,0x1f3830,0x2d8f40,0x2fbad0,0x2fe440,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f3830,0x2fbad0; outside_wrappers=0 unverified
+0x001f3990 impl_cuTexRefSetArray high group=cuTexRefSetArray variants=cuTexRefSetArray; before=0x1f3990,0x2fe540,0x4a7e90,0xd4dc50; after=0x1f3990; outside_wrappers=0 unverified
+0x001f3ca0 impl_cuTexRefSetMipmappedArray high group=cuTexRefSetMipmappedArray variants=cuTexRefSetMipmappedArray; before=0x1f3ca0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1f3ca0; outside_wrappers=0 unverified
+0x001f4000 impl_cuTexRefSetFormat high group=cuTexRefSetFormat variants=cuTexRefSetFormat; before=0x1f4000,0x2583d0,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f4000; outside_wrappers=0 unverified
+0x001f4200 impl_cuTexRefSetAddressMode high group=cuTexRefSetAddressMode variants=cuTexRefSetAddressMode; before=0x1f4200,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f4200; outside_wrappers=0 unverified
+0x001f4370 impl_cuTexRefSetFilterMode high group=cuTexRefSetFilterMode variants=cuTexRefSetFilterMode; before=0x1f4370,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f4370; outside_wrappers=0 unverified
+0x001f44b0 impl_cuTexRefSetBorderColor high group=cuTexRefSetBorderColor variants=cuTexRefSetBorderColor; before=0x1f44b0,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f44b0; outside_wrappers=0 unverified
+0x001f4620 impl_cuTexRefSetFlags high group=cuTexRefSetFlags variants=cuTexRefSetFlags; before=0x1f4620,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f4620; outside_wrappers=0 unverified
+0x001f4770 impl_cuTexRefSetMipmapFilterMode high group=cuTexRefSetMipmapFilterMode variants=cuTexRefSetMipmapFilterMode; before=0x1f4770,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f4770; outside_wrappers=0 unverified
+0x001f48b0 impl_cuTexRefSetMipmapLevelBias high group=cuTexRefSetMipmapLevelBias variants=cuTexRefSetMipmapLevelBias; before=0x1f48b0,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f48b0; outside_wrappers=0 unverified
+0x001f49f0 impl_cuTexRefSetMipmapLevelClamp high group=cuTexRefSetMipmapLevelClamp variants=cuTexRefSetMipmapLevelClamp; before=0x1f49f0,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f49f0; outside_wrappers=0 unverified
+0x001f4b60 impl_cuTexRefSetMaxAnisotropy high group=cuTexRefSetMaxAnisotropy variants=cuTexRefSetMaxAnisotropy; before=0x1f4b60,0x2d8f40,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50,0xd51980; after=0x1f4b60; outside_wrappers=0 unverified
+0x001f4f60 impl_cuTexRefGetAddressMode high group=cuTexRefGetAddressMode variants=cuTexRefGetAddressMode; before=0x1798f0,0x1f4f60,0x2fe440,0x2fe540,0x4a7e90,0xd11b90,0xd4dc50; after=0x1f4f60; outside_wrappers=0 unverified
+0x001f5c20 impl_cuGraphicsVDPAURegisterVideoSurface high group=cuGraphicsVDPAURegisterVideoSurface variants=cuGraphicsVDPAURegisterVideoSurface; before=0x179200,0x1799e0,0x1f5c20,0x2d8f40,0x2fe230,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x1f5c20; outside_wrappers=0 unverified
+0x001f5e10 impl_cuGraphicsVDPAURegisterOutputSurface high group=cuGraphicsVDPAURegisterOutputSurface variants=cuGraphicsVDPAURegisterOutputSurface; before=0x179200,0x1799e0,0x1f5e10,0x2d8f40,0x2fe230,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x1f5e10; outside_wrappers=0 unverified
+0x001f8c90 impl_cuMemPoolDestroy medium group=cuMemPoolDestroy variants=cuMemPoolDestroy; before=0x1798f0,0x1d5910,0x1f8c90,0x2fe230,0x2fe440,0x2fe540,0x4a7e90,0xd4dc50; after=0x1f8c90,0x1d5910; outside_wrappers=0 unverified
+0x001f9780 impl_cuMulticastUnbind high group=cuMulticastUnbind variants=cuMulticastUnbind; before=0x1f94c0,0x1f9780,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1f9780; outside_wrappers=0 unverified
+0x001f9950 impl_cuMulticastAddDevice high group=cuMulticastAddDevice variants=cuMulticastAddDevice; before=0x1f94c0,0x1f9950,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1f9950; outside_wrappers=0 unverified
+0x001f9a90 impl_cuMulticastGetGranularity high group=cuMulticastGetGranularity variants=cuMulticastGetGranularity; before=0x1f94c0,0x1f9a90,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1f9a90; outside_wrappers=0 unverified
+0x001f9f70 impl_cuOccupancyMaxActiveBlocksPerMultiprocessor medium group=cuOccupancyMaxActiveBlocksPerMultiprocessor variants=cuOccupancyMaxActiveBlocksPerMultiprocessor; before=0x1f9e20,0x1f9f70,0x2bb420,0x2dc100,0x2e4340,0x2fe540,0x4a7e90,0xd4bd20,0xd4dc50; after=0x1f9f70,0x2e4340; outside_wrappers=1 unverified
+0x001f9f70 impl_cuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags medium group=cuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags variants=cuOccupancyMaxActiveBlocksPerMultiprocessorWithFlags; before=0x1f9e20,0x1f9f70,0x2bb420,0x2dc100,0x2e4340,0x2fe540,0x4a7e90,0xd4bd20,0xd4dc50; after=0x1f9f70,0x2e4340; outside_wrappers=1 unverified
+0x001fa330 impl_cuOccupancyMaxPotentialBlockSize medium group=cuOccupancyMaxPotentialBlockSize variants=cuOccupancyMaxPotentialBlockSize; before=0x1f9e20,0x1fa330,0x2baed0,0x2d8f40,0x2e4570,0x2fde50,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1fa330,0x2e4570; outside_wrappers=1 unverified
+0x001fa330 impl_cuOccupancyMaxPotentialBlockSizeWithFlags medium group=cuOccupancyMaxPotentialBlockSizeWithFlags variants=cuOccupancyMaxPotentialBlockSizeWithFlags; before=0x1f9e20,0x1fa330,0x2baed0,0x2d8f40,0x2e4570,0x2fde50,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x1fa330,0x2e4570; outside_wrappers=1 unverified
+0x001fa6d0 impl_cuOccupancyMaxPotentialClusterSize high group=cuOccupancyMaxPotentialClusterSize variants=cuOccupancyMaxPotentialClusterSize; before=0x1fa6d0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1fa6d0; outside_wrappers=0 unverified
+0x001faa00 impl_cuOccupancyMaxActiveClusters high group=cuOccupancyMaxActiveClusters variants=cuOccupancyMaxActiveClusters; before=0x1faa00,0x2fe540,0x4a7e90,0xd4dc50; after=0x1faa00; outside_wrappers=0 unverified
+0x001facd0 impl_cuStreamCreate medium group=cuStreamCreate variants=cuStreamCreate; before=0x1facd0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1facd0; outside_wrappers=1 unverified
+0x001facd0 impl_cuStreamCreateWithPriority medium group=cuStreamCreateWithPriority variants=cuStreamCreateWithPriority; before=0x1facd0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1facd0; outside_wrappers=1 unverified
+0x001fb3d0 impl_cuStreamWaitEvent high group=cuStreamWaitEvent variants=cuStreamWaitEvent_ptsz,cuStreamWaitEvent; before=0x1792f0,0x179350,0x1fb3d0,0x2a2b90,0x2a50f0,0x2baed0,0x2ed7d0,0x2fe540,0x3abad0,0x4a7e90,0xd1d500,0xd1e090,0xd4dc50; after=0x1fb3d0; outside_wrappers=0 unverified
+0x001fb7f0 impl_cuStreamGetCaptureInfo high group=cuStreamGetCaptureInfo variants=cuStreamGetCaptureInfo_v2_ptsz,cuStreamGetCaptureInfo_v3_ptsz,cuStreamGetCaptureInfo,cuStreamGetCaptureInfo_ptsz,cuStreamGetCaptureInfo_v2,cuStreamGetCaptureInfo_v3; before=0x1fb7f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1fb7f0; outside_wrappers=0 unverified
+0x001fbe30 impl_cuStreamBeginCaptureToGraph high group=cuStreamBeginCaptureToGraph variants=cuStreamBeginCaptureToGraph_ptsz,cuStreamBeginCaptureToGraph; before=0x1fba70,0x1fbe30,0x2d8f40,0x2eff60,0x2f16c0,0x2fe540,0x4a7e90,0xd1e090,0xd4dc50,0xd51980; after=0x1fbe30; outside_wrappers=0 unverified
+0x001fd190 impl_cuStreamCopyAttributes high group=cuStreamCopyAttributes variants=cuStreamCopyAttributes_ptsz,cuStreamCopyAttributes; before=0x1fd190,0x2fe540,0x4a7e90,0xd1d500,0xd4dc50; after=0x1fd190; outside_wrappers=0 unverified
+0x001fd2e0 impl_cuStreamGetAttribute high group=cuStreamGetAttribute variants=cuStreamGetAttribute_ptsz,cuStreamGetAttribute; before=0x1fd2e0,0x2d8f40,0x2fe540,0x4a7e90,0xd1d500,0xd4dc50,0xd51980; after=0x1fd2e0; outside_wrappers=0 unverified
+0x001fd460 impl_cuVDPAUCtxCreate high group=cuVDPAUCtxCreate variants=cuVDPAUCtxCreate_v2,cuVDPAUCtxCreate; before=0x1fd460,0x2689e0,0x26d8e0,0x277680,0x2fe020,0x2fe540,0x4a7e90,0xd4dc50; after=0x1fd460; outside_wrappers=0 unverified
+0x001ff270 impl_cuMulticastBindMem medium group=cuMulticastBindMem variants=cuMulticastBindMem; before=0x1f94c0,0x1ff270,0x2fde40,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x1ff270,0x2fde40; outside_wrappers=0 unverified
+0x001ff3e0 impl_cuMulticastBindAddr high group=cuMulticastBindAddr variants=cuMulticastBindAddr; before=0x1ff3e0,0x2fe540,0x4a7e90,0xd4dc50; after=0x1ff3e0; outside_wrappers=0 unverified
+0x0024a6d0 impl_cuCoredumpSetAttributeGlobal high group=cuCoredumpSetAttributeGlobal variants=cuCoredumpSetAttributeGlobal; before=0x24a4d0,0x24a6d0,0x2fe540,0x4a7e90,0xd4dc50; after=0x24a6d0; outside_wrappers=0 unverified
+0x00259480 impl_cuTexRefSetAddress2D high group=cuTexRefSetAddress2D variants=cuTexRefSetAddress2D_v3,cuTexRefSetAddress2D_v2,cuTexRefSetAddress2D; before=0x259480,0x2baed0,0x2d8f40,0x2fbe80,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x259480; outside_wrappers=0 unverified
+0x00261f70 impl_cuCheckpointProcessGetRestoreThreadId high group=cuCheckpointProcessGetRestoreThreadId variants=cuCheckpointProcessGetRestoreThreadId; before=0x261f70,0x2fe540,0x4a7e90,0xd4dc50; after=0x261f70; outside_wrappers=0 unverified
+0x00262690 impl_cuCheckpointProcessGetState medium group=cuCheckpointProcessGetState variants=cuCheckpointProcessGetState; before=0x179200,0x2623e0,0x262690,0x2fe540,0x30a870,0x4a7e90,0xd4dc50; after=0x262690,0x2623e0,0x30a870; outside_wrappers=0 unverified
+0x00266fc0 impl_cuCoredumpSetAttribute high group=cuCoredumpSetAttribute variants=cuCoredumpSetAttribute; before=0x266fc0,0x2fe540,0x4a7e90,0xd4dc50; after=0x266fc0; outside_wrappers=0 unverified
+0x0026a9b0 impl_cuCtxSynchronize medium group=cuCtxSynchronize variants=cuCtxSynchronize; before=0x1ad290,0x26a9b0,0x2baed0,0x2fde50,0x2fe540,0x4a7e90,0xd1e3f0,0xd4dc50; after=0x26a9b0,0x1ad290; outside_wrappers=0 unverified
+0x0026ec30 impl_cuEGLStreamProducerReturnFrame medium group=cuEGLStreamProducerReturnFrame variants=cuEGLStreamProducerReturnFrame; before=0x1b0db0,0x26ec30,0x2fde50,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50,0xd6e3d0; after=0x26ec30,0x1b0db0,0xd6e3d0; outside_wrappers=0 unverified
+0x0026fa30 impl_cuEGLStreamConsumerReleaseFrame medium group=cuEGLStreamConsumerReleaseFrame variants=cuEGLStreamConsumerReleaseFrame; before=0x1b07f0,0x26e7c0,0x26fa30,0x2fde50,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x26fa30,0x26e7c0,0x1b07f0; outside_wrappers=0 unverified
+0x00287bb0 impl_cuGetErrorName medium group=cuGetErrorName variants=cuGetErrorName; before=0x287bb0,0x2fe540,0x4a7e90,0xd4dc50; after=0x287bb0; outside_wrappers=1 unverified
+0x00287bb0 impl_cuGetErrorString medium group=cuGetErrorString variants=cuGetErrorString; before=0x287bb0,0x2fe540,0x4a7e90,0xd4dc50; after=0x287bb0; outside_wrappers=1 unverified
+0x00287cb0 impl_cuEventElapsedTime medium group=cuEventElapsedTime variants=cuEventElapsedTime,cuEventElapsedTime_v2; before=0x287cb0,0x288ba0,0x2bb140,0x2fe540,0x487640,0x4a7e90,0xd4dc50; after=0x287cb0,0x487640,0x288ba0; outside_wrappers=0 unverified
+0x00287ed0 impl_cuEventCreate medium group=cuEventCreate variants=cuEventCreate; before=0x1b0fb0,0x287ed0,0x2bb420,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x287ed0,0x1b0fb0; outside_wrappers=0 unverified
+0x00288cd0 impl_cuEventSynchronize medium group=cuEventSynchronize variants=cuEventSynchronize; before=0x1b2600,0x288cd0,0x2bb140,0x2fe230,0x2fe540,0x3034c0,0x4a7e90,0xd1e090,0xd4dc50; after=0x288cd0,0x1b2600,0x3034c0; outside_wrappers=0 unverified
+0x002891d0 impl_cuEventDestroy high group=cuEventDestroy variants=cuEventDestroy_v2,cuEventDestroy; before=0x2891d0,0x2baed0,0x2bb140,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x2891d0; outside_wrappers=0 verified
+0x00294db0 impl_cuGLGetDevices medium group=cuGLGetDevices variants=cuGLGetDevices_v2,cuGLGetDevices; before=0x294db0,0x29d320,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x294db0,0x29d320; outside_wrappers=0 unverified
+0x00294fd0 impl_cuGLInit medium group=cuGLInit variants=cuGLInit; before=0x294fd0,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50; after=0x294fd0; outside_wrappers=1 unverified
+0x0029d480 impl_cuGraphCreate high group=cuGraphCreate variants=cuGraphCreate; before=0x29d480,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x29d480; outside_wrappers=0 unverified
+0x002a1b10 impl_cuGraphAddMemAllocNode medium group=cuGraphAddMemAllocNode variants=cuGraphAddMemAllocNode; before=0x1baa70,0x2a1930,0x2a1b10,0x2a5430,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2a1b10,0x2a5430,0x1baa70,0x2a1930; outside_wrappers=0 unverified
+0x002a3530 impl_cuGraphDestroy medium group=cuGraphDestroy variants=cuGraphDestroy; before=0x2a3530,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2a3530; outside_wrappers=1 unverified
+0x002a5a20 impl_cuGraphAddMemFreeNode medium group=cuGraphAddMemFreeNode variants=cuGraphAddMemFreeNode; before=0x1c1db0,0x2a5a20,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2a5a20,0x1c1db0; outside_wrappers=0 unverified
+0x002a66e0 impl_cuGraphAddBatchMemOpNode medium group=cuGraphAddBatchMemOpNode variants=cuGraphAddBatchMemOpNode; before=0x1c0740,0x1c0bc0,0x2a66e0,0x2bb140,0x2fe540,0x4a7e90,0xd4dc50; after=0x2a66e0,0x1c0bc0; outside_wrappers=0 unverified
+0x002a6bf0 impl_cuGraphDebugDotPrint high group=cuGraphDebugDotPrint variants=cuGraphDebugDotPrint; before=0x2a6bf0,0x2fe540,0x4a7e90,0xd4dc50; after=0x2a6bf0; outside_wrappers=0 verified
+0x002aa0a0 impl_cuGraphAddExternalSemaphoresSignalNode medium group=cuGraphAddExternalSemaphoresSignalNode variants=cuGraphAddExternalSemaphoresSignalNode; before=0x1b9cc0,0x2aa0a0,0x2fe540,0x4a7e90,0xd4dc50; after=0x2aa0a0,0x1b9cc0; outside_wrappers=0 unverified
+0x002aa2d0 impl_cuGraphAddExternalSemaphoresWaitNode medium group=cuGraphAddExternalSemaphoresWaitNode variants=cuGraphAddExternalSemaphoresWaitNode; before=0x1ba0d0,0x2aa2d0,0x2fe540,0x4a7e90,0xd4dc50; after=0x2aa2d0,0x1ba0d0; outside_wrappers=0 unverified
+0x002aabc0 impl_cuGraphClone medium group=cuGraphClone variants=cuGraphClone; before=0x1ba8d0,0x2aabc0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2aabc0,0x1ba8d0; outside_wrappers=0 unverified
+0x002ac120 impl_cuGraphExecBatchMemOpNodeSetParams medium group=cuGraphExecBatchMemOpNodeSetParams variants=cuGraphExecBatchMemOpNodeSetParams; before=0x179200,0x179a80,0x179c00,0x1c0740,0x1c0e20,0x2ac120,0x2baed0,0x2fe540,0x4a7e90,0xd183b0,0xd4dc50; after=0x2ac120,0x1c0e20; outside_wrappers=0 unverified
+0x002aca10 impl_cuGraphKernelNodeSetParams high group=cuGraphKernelNodeSetParams variants=cuGraphKernelNodeSetParams_v2,cuGraphKernelNodeSetParams; before=0x1c2b10,0x2aca10,0x2fe540,0x4a7e90,0xd4dc50; after=0x2aca10; outside_wrappers=0 unverified
+0x002afcf0 impl_cuGraphNodeSetEnabled high group=cuGraphNodeSetEnabled variants=cuGraphNodeSetEnabled; before=0x2afcf0,0x2fe540,0x4a7e90,0xd183b0,0xd4dc50; after=0x2afcf0; outside_wrappers=0 unverified
+0x002b01c0 impl_cuGraphExecKernelNodeSetParams medium group=cuGraphExecKernelNodeSetParams variants=cuGraphExecKernelNodeSetParams_v2,cuGraphExecKernelNodeSetParams; before=0x1c2b10,0x2b01c0,0x2fe540,0x4a7e90,0xd183b0,0xd4dc50,0xd6a9f0; after=0x2b01c0,0xd6a9f0; outside_wrappers=0 unverified
+0x002b4f80 impl_cuGraphExecChildGraphNodeSetParams medium group=cuGraphExecChildGraphNodeSetParams variants=cuGraphExecChildGraphNodeSetParams; before=0x2ac1b0,0x2b4f80,0x2fe540,0x4a7e90,0xd183b0,0xd4dc50; after=0x2b4f80,0x2ac1b0; outside_wrappers=1 unverified
+0x002b9ff0 impl_cuGreenCtxDestroy medium group=cuGreenCtxDestroy variants=cuGreenCtxDestroy; before=0x1792f0,0x179350,0x1c6be0,0x26d680,0x2b9ff0,0x2bb140,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2b9ff0,0x1c6be0; outside_wrappers=0 unverified
+0x002ba3e0 impl_cuGreenCtxCreate medium group=cuGreenCtxCreate variants=cuGreenCtxCreate; before=0x1792f0,0x179350,0x1c6830,0x26d8a0,0x277570,0x2ba3e0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2ba3e0,0x1c6830,0x277570,0x26d8a0; outside_wrappers=0 unverified
+0x002bdf80 impl_cuLinkDestroy high group=cuLinkDestroy variants=cuLinkDestroy; before=0x2bdf80,0x2fe540,0x4a7e90,0xd4dc50; after=0x2bdf80; outside_wrappers=0 unverified
+0x002bf2f0 impl_cuKernelGetAttribute high group=cuKernelGetAttribute variants=cuKernelGetAttribute; before=0x2bb420,0x2bf2f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x2bf2f0; outside_wrappers=0 unverified
+0x002bfd50 impl_cuKernelSetAttribute medium group=cuKernelSetAttribute variants=cuKernelSetAttribute; before=0x179730,0x1ca190,0x2bb420,0x2bfd50,0x2d8f40,0x2fe540,0x4a7e90,0xd4dc50,0xd51f50; after=0x2bfd50,0x1ca190,0xd51f50,0x179730; outside_wrappers=0 unverified
+0x002c05e0 impl_cuCtxSetLimit medium group=cuCtxSetLimit variants=cuCtxSetLimit; before=0x1ca690,0x2c05e0,0x2d8f40,0x2fe230,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x2c05e0,0x1ca690; outside_wrappers=0 unverified
+0x002c1040 impl_cuDeviceGetP2PAttribute medium group=cuDeviceGetP2PAttribute variants=cuDeviceGetP2PAttribute; before=0x1af7e0,0x2c1040,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2c1040,0x1af7e0; outside_wrappers=0 unverified
+0x002c2890 impl_cuLibraryUnload medium group=cuLibraryUnload variants=cuLibraryUnload; before=0x1c9e80,0x2c2890,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x2c2890,0x1c9e80; outside_wrappers=0 unverified
+0x002c4050 impl_cuMemPoolCreate medium group=cuMemPoolCreate variants=cuMemPoolCreate; before=0x1d5780,0x2c4050,0x2c6030,0x2cee80,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50; after=0x2c4050,0x1d5780,0x2cee80,0x2c6030; outside_wrappers=0 unverified
+0x002c71c0 impl_cuDeviceGraphMemTrim high group=cuDeviceGraphMemTrim variants=cuDeviceGraphMemTrim; before=0x2c71c0,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2c71c0; outside_wrappers=0 unverified
+0x002cb940 impl_cuInit medium group=cuInit variants=cuInit; before=0x2ba8f0,0x2cb940,0x2fe540,0x4a7e90,0xd4dc50; after=0x2cb940,0x2ba8f0; outside_wrappers=0 unverified
+0x002ce4e0 impl_cuLinkCreate high group=cuLinkCreate variants=cuLinkCreate_v2,cuLinkCreate; before=0x2bb420,0x2bbd30,0x2ce4e0,0x2fe540,0x4a7e90,0xd4dc50; after=0x2ce4e0; outside_wrappers=0 verified
+0x002d09f0 impl_cuLinkComplete high group=cuLinkComplete variants=cuLinkComplete; before=0x2d09f0,0x2fe540,0x4a7e90,0xd4dc50; after=0x2d09f0; outside_wrappers=0 unverified
+0x002d3f60 impl_cuLibraryLoadData medium group=cuLibraryLoadData variants=cuLibraryLoadData; before=0x2bbd30,0x2d3f60,0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x2d3f60; outside_wrappers=1 unverified
+0x002d81b0 impl_cuMemBatchDecompressAsync medium group=cuMemBatchDecompressAsync variants=cuMemBatchDecompressAsync_ptsz,cuMemBatchDecompressAsync; before=0x26bc10,0x2d8060,0x2d81b0,0x2f8e10,0x2f8fd0,0x2fe540,0x4a7e90,0xd1d500,0xd4dc50,0xd73560; after=0x2d81b0,0xd73560,0x2d8060; outside_wrappers=0 unverified
+0x002e84d0 impl_cuModuleUnload medium group=cuModuleUnload variants=cuModuleUnload; before=0x1eb2e0,0x2baed0,0x2d8f40,0x2e84d0,0x2fe230,0x2fe540,0x301460,0x4a7e90,0xd4dc50,0xd4f3e0,0xd51980; after=0x2e84d0,0x1eb2e0,0x301460; outside_wrappers=0 unverified
+0x002eb720 impl_cuMemMapArrayAsync medium group=cuMemMapArrayAsync variants=cuMemMapArrayAsync_ptsz,cuMemMapArrayAsync; before=0x1dfae0,0x2d8f40,0x2eb720,0x2fe540,0x4a7e90,0xd1d500,0xd4dc50,0xd51980; after=0x2eb720,0x1dfae0; outside_wrappers=0 unverified
+0x002ec4a0 impl_cuStreamAttachMemAsync medium group=cuStreamAttachMemAsync variants=cuStreamAttachMemAsync_ptsz,cuStreamAttachMemAsync; before=0x1fce40,0x2d8f40,0x2ec4a0,0x2f16c0,0x2fe230,0x2fe540,0x4a7e90,0xd4dc50,0xd51980; after=0x2ec4a0,0x1fce40; outside_wrappers=0 unverified
+0x002f0110 impl_cuStreamEndCapture medium group=cuStreamEndCapture variants=cuStreamEndCapture_ptsz,cuStreamEndCapture; before=0x1fb6b0,0x2f0110,0x2f16c0,0x2fe540,0x4a7e90,0xd1e090,0xd4dc50; after=0x2f0110,0x1fb6b0; outside_wrappers=0 unverified
+0x002f0630 impl_cuStreamDestroy medium group=cuStreamDestroy variants=cuStreamDestroy_v2,cuStreamDestroy; before=0x1792f0,0x179350,0x1fb130,0x2d8f40,0x2f0630,0x2fe540,0x4a7e90,0xd1d500,0xd4dc50,0xd51980; after=0x2f0630,0x1fb130; outside_wrappers=0 unverified
+0x002f0fe0 impl_cuGLUnmapBufferObject medium group=cuGLUnmapBufferObject variants=cuGLUnmapBufferObject; before=0x1c1a20,0x2baed0,0x2f0fe0,0x2fde50,0x2fe230,0x2fe540,0x3aa550,0x3c52d0,0x3c5370,0x4a7e90,0xd4dc50,0xd663e0; after=0x2f0fe0,0x1c1a20; outside_wrappers=1 unverified
+0x002f0fe0 impl_cuGLUnmapBufferObjectAsync medium group=cuGLUnmapBufferObjectAsync variants=cuGLUnmapBufferObjectAsync; before=0x1c1a20,0x2baed0,0x2f0fe0,0x2fde50,0x2fe230,0x2fe540,0x3aa550,0x3c52d0,0x3c5370,0x4a7e90,0xd4dc50,0xd663e0; after=0x2f0fe0,0x1c1a20; outside_wrappers=1 unverified
+0x002f1880 impl_cuStreamSetAttribute high group=cuStreamSetAttribute variants=cuStreamSetAttribute_ptsz,cuStreamSetAttribute; before=0x2d8f40,0x2f1880,0x2fe540,0x4a7e90,0xd1d500,0xd4dc50,0xd51980; after=0x2f1880; outside_wrappers=0 unverified
+0x002f9f00 impl_cuModuleGetGlobal high group=cuModuleGetGlobal variants=cuModuleGetGlobal_v2,cuModuleGetGlobal; before=0x2baed0,0x2d8f40,0x2f9f00,0x2fe540,0x402500,0x4a7e90,0xd4dc50,0xd51980; after=0x2f9f00; outside_wrappers=1 verified
+0x002fb8e0 impl_cuTexRefCreate medium group=cuTexRefCreate variants=cuTexRefCreate; before=0x1f2870,0x2d8f40,0x2fb8e0,0x2fe540,0x4a7e90,0xd4da90,0xd4dc50,0xd51980; after=0x2fb8e0,0x1f2870; outside_wrappers=0 unverified
+0x002fffa0 impl_cuMemRangeGetAttribute medium group=cuMemRangeGetAttribute variants=cuMemRangeGetAttribute; before=0x1cb030,0x2fe540,0x2fffa0,0x306160,0x3fe700,0x4a7e90,0xd4bd90,0xd4db70,0xd4dc50; after=0x2fffa0,0x1cb030; outside_wrappers=0 unverified
+0x00304420 impl_cuStreamQuery medium group=cuStreamQuery variants=cuStreamQuery_ptsz,cuStreamQuery; before=0x1fcfe0,0x2ea920,0x2f16c0,0x2fe230,0x2fe540,0x304420,0x4a7e90,0xd4dc50; after=0x304420,0x1fcfe0,0x2ea920; outside_wrappers=0 unverified
+0x003aa910 impl_cuLibraryEnumerateKernels medium group=cuLibraryEnumerateKernels variants=cuLibraryEnumerateKernels; before=0x2fe540,0x3aa910,0x3aad50,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x3aa910,0x3aad50; outside_wrappers=1 unverified
+0x003aa910 impl_cuLibraryGetKernelCount medium group=cuLibraryGetKernelCount variants=cuLibraryGetKernelCount; before=0x2fe540,0x3aa910,0x3aad50,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x3aa910,0x3aad50; outside_wrappers=1 unverified
+0x003c9250 impl_cuMemFreeAsync high group=cuMemFreeAsync variants=cuMemFreeAsync_ptsz,cuMemFreeAsync; before=0x1798f0,0x2fe440,0x2fe540,0x3c9250,0x4a7e90,0xd4dc50; after=0x3c9250; outside_wrappers=0 verified
+0x003fb7b0 impl_cuMemRelease medium group=cuMemRelease variants=cuMemRelease; before=0x1792f0,0x179350,0x1d2dc0,0x2fe540,0x3fb7b0,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x3fb7b0,0x1d2dc0; outside_wrappers=0 unverified
+0x003fcfa0 impl_cuMulticastCreate medium group=cuMulticastCreate variants=cuMulticastCreate; before=0x1792f0,0x179350,0x1f94c0,0x1f9580,0x26bc10,0x2fe540,0x3fcfa0,0x4a7e90,0xd4d9a0,0xd4dc50; after=0x3fcfa0,0x1f9580; outside_wrappers=0 unverified
+0x00400ec0 impl_cuMemAlloc high group=cuMemAlloc variants=cuMemAlloc_v2,cuMemAlloc; before=0x1d9cb0,0x2bb300,0x2c1d40,0x2d8f40,0x2e7bf0,0x2fe230,0x2fe540,0x400550,0x400ec0,0x4a7e90,0xd4dc50,0xd51980; after=0x400ec0; outside_wrappers=0 verified
+0x00402a30 impl_cuMemGetAddressRange high group=cuMemGetAddressRange variants=cuMemGetAddressRange_v2,cuMemGetAddressRange; before=0x1792f0,0x179350,0x2bb300,0x2fe540,0x3ac3f0,0x402a30,0x403470,0x4a7e90,0xd4bd90,0xd4dc50; after=0x402a30; outside_wrappers=0 verified
+0x00d11d90 impl_cuStreamBeginCapture high group=cuStreamBeginCapture variants=cuStreamBeginCapture_v2_ptsz,cuStreamBeginCapture,cuStreamBeginCapture_ptsz,cuStreamBeginCapture_v2; before=0x2d8f40,0x2eff60,0x2f16c0,0x2fe540,0x4a7e90,0xd11d90,0xd4dc50,0xd51980; after=0xd11d90; outside_wrappers=0 verified
+0x00d11e90 impl_cuStreamSynchronize medium group=cuStreamSynchronize variants=cuStreamSynchronize_ptsz,cuStreamSynchronize; before=0x1fb280,0x2f16c0,0x2fe230,0x2fe540,0x4a7e90,0xd11e90,0xd4dc50; after=0xd11e90,0x1fb280; outside_wrappers=0 unverified
+0x00d121d0 impl_cuGetProcAddress high group=cuGetProcAddress variants=cuGetProcAddress_v2,cuGetProcAddress; before=0x2fe540,0x4a7e90,0xd121d0,0xd4dc50; after=0xd121d0; outside_wrappers=0 unverified
+0x00d180a0 impl_cuGraphAddChildGraphNode medium group=cuGraphAddChildGraphNode variants=cuGraphAddChildGraphNode; before=0x1ba7c0,0x2fe540,0x4a7e90,0xd180a0,0xd4d9a0,0xd4dc50; after=0xd180a0,0x1ba7c0; outside_wrappers=0 unverified
+0x00d20520 impl_cuIpcOpenEventHandle medium group=cuIpcOpenEventHandle variants=cuIpcOpenEventHandle; before=0x179200,0x1799e0,0x1b3530,0x2bb420,0x2d8f40,0x2da1f0,0x2fe540,0x483550,0x4a7e90,0xd20520,0xd4dc50,0xd4e540,0xd51980; after=0xd20520,0x1b3530,0xd4e540,0x483550,0x2da1f0; outside_wrappers=0 unverified
+0x00d668f0 impl_cuLibraryGetUnifiedFunction high group=cuLibraryGetUnifiedFunction variants=cuLibraryGetUnifiedFunction; before=0x2fe540,0x4a7e90,0xd4d9a0,0xd4dc50,0xd668f0; after=0xd668f0; outside_wrappers=0 verified
diff --git a/userspace/cuda/570.144/annotations/names.tsv b/userspace/cuda/570.144/annotations/names.tsv
index 403bef3..e668055 100644
--- a/userspace/cuda/570.144/annotations/names.tsv
+++ b/userspace/cuda/570.144/annotations/names.tsv
@@ -1302,3 +1302,42 @@
0x4676f0 cudaEngineContextCreateHook verified
0x481360 rmEngineContextAlloc verified
0x453cc0 cudaEngineContextCleanup verified
+# --- engine-record path verified in the 2026-09 type-recovery pass (see docs/05 section 3.7) ---
+0x450ff0 cudaDeviceBuildEngineRecords verified
+0x462770 cudaRmGetEngines verified
+0x44a170 cudaDeviceSupportsClass verified
+0x458040 cudaDeviceAbiTableInit verified
+0x44ac20 cudaDeviceInitCaps verified
+#
+# --- wrapper callees verified in the 2026-09 name-candidate pass ---
+# Method: tools/name_candidates.py; per-entry evidence and confidence in
+# name-candidates.tsv; roles/evidence also recorded in subsystems.tsv.
+0x1a36d0 impl_cuCtxGetApiVersion wrapper-callee
+0x1a4900 impl_cuArrayGetMemoryRequirements wrapper-callee
+0x1a5410 impl_cuArrayGetPlane wrapper-callee
+0x1a5820 impl_cuDevicePrimaryCtxGetState wrapper-callee
+0x1a6150 impl_cuDeviceRegisterAsyncNotification wrapper-callee
+0x1a6430 impl_cuCtxAttach wrapper-callee
+0x1a66f0 impl_cuCtxGetCurrent wrapper-callee
+0x1a6850 impl_cuCtxGetDevice wrapper-callee
+0x1a6960 impl_cuCtxGetFlags wrapper-callee
+0x1a6af0 impl_cuFlushGPUDirectRDMAWrites wrapper-callee
+0x1a6c50 impl_cuCtxGetExecAffinity wrapper-callee
+0x1a7320 impl_cuDeviceGetLuid wrapper-callee
+0x1ae3d0 impl_cuDeviceComputeCapability wrapper-callee
+0x1ae550 impl_cuDeviceGetProperties wrapper-callee
+0x1ae780 impl_cuDeviceGetAttribute wrapper-callee
+0x1be900 impl_cuCtxDestroy wrapper-callee
+0x1da450 impl_cuMemFree wrapper-callee
+0x1da880 impl_cuMemFreeHost wrapper-callee
+0x1e9ab0 impl_cuModuleLoad wrapper-callee
+0x1e9d80 impl_cuModuleLoadData wrapper-callee
+0x2891d0 impl_cuEventDestroy wrapper-callee
+0x2a6bf0 impl_cuGraphDebugDotPrint wrapper-callee
+0x2ce4e0 impl_cuLinkCreate wrapper-callee
+0x2f9f00 impl_cuModuleGetGlobal wrapper-callee
+0x3c9250 impl_cuMemFreeAsync wrapper-callee
+0x400ec0 impl_cuMemAlloc wrapper-callee
+0x402a30 impl_cuMemGetAddressRange wrapper-callee
+0xd11d90 impl_cuStreamBeginCapture wrapper-callee
+0xd668f0 impl_cuLibraryGetUnifiedFunction wrapper-callee
diff --git a/userspace/cuda/570.144/annotations/subsystems.tsv b/userspace/cuda/570.144/annotations/subsystems.tsv
index 5a512bd..4d0c423 100644
--- a/userspace/cuda/570.144/annotations/subsystems.tsv
+++ b/userspace/cuda/570.144/annotations/subsystems.tsv
@@ -25,13 +25,52 @@
# --- engine/context bring-up (the cuCtxCreate path: crash solved, engine topology blocking; see docs/05) ---
0x3a9c20 cudaHandlePoolAlloc engine bitmap handle allocator: lock, scan 64-bit words for first zero bit, return base + index*64 + bit decompiled
0x3a2f50 cudaHandlePoolFree engine clears the handle bit under the pool mutex decompiled
-0x453ef0 cudaEngineContextRegisterHelper engine-engines per-engine registration: alloc handle, call create hook, call bind hook, publish engine id + descriptor into context arrays; called twice for engine index 0 (GR + secondary async CE) decompiled+trace
-0x45a670 cudaDeviceInitEngineContexts engine-engines walks 0x14-byte engine records (base+0x2fec for GR; +0x300c+(idx-1)*0x14; +0x350c; +0x351c+(idx-0x16)*0x14), checks engine existence via [table+0x4e00], calls the helper; sees only GR + CE0..4 because the GET_ENGINES_V2/classDB filter drops the async CE (see docs/05 section 3.6) decompiled+trace
-0x4676f0 cudaEngineContextCreateHook engine-engines hook at [table+0x40]+0x530; selects instance/class from the engine descriptor and calls rmEngineContextAlloc; its saved rbp was zeroed by the alloc reply's 16-byte class-params copy-back (crash solved, see docs/05 section 3.5) decompiled+trace
-0x481360 rmEngineContextAlloc rm builds NV_ESC_RM_ALLOC requests per class (0x80 device, 0x5/0x79 per-class table, 0x2080 subdevice array of 32, default generic) and returns small status codes; with a zeroed secondary engine record the class is rewritten to NV01_ROOT_CLIENT (0x41), status 0x19, and the context rolls back (rc=999) decompiled+trace
+0x453ef0 cudaEngineContextRegisterHelper engine-engines per-engine registration: idx = record+0 kind (1 normalizes to 0), alloc handle, call create hook with the record, call bind hook, publish engine id at ctx+0x50+idx*4 and the record pointer at ctx[0x9488]+0x88+idx*8; called twice for engine index 0 (GR + secondary async CE) decompiled+trace
+0x45a670 cudaDeviceInitEngineContexts engine-engines per-context engine-init hook installed at ctx+0x94b0; selects the 0x14-byte engine record for ctx+0x38 (GR at +0x2fec; copy at +0x300c+(idx-1)*0x14, +0x300c+(idx-2)*0x14 for idx 0xc..0x15; SEC2 at +0x350c; decomp copy at +0x351c+(idx-0x16)*0x14), checks existence via [table+0x4e00](table, record+0xc), calls the helper; for index 0 also registers the secondary record at *(table+0x4af0)+0x75c decompiled+trace
+0x4676f0 cudaEngineContextCreateHook engine-engines create hook at [table+0x40]+0x530; reads record kind +0, instance +8, class +0xc; copies instance into RM alloc-param dword 1 only for kinds 2/3/5; passes record+0xc as the alloc class to rmEngineContextAlloc; its saved rbp was zeroed by the alloc reply's 16-byte class-params copy-back (crash solved, see docs/05 section 3.5); the typed pass recovered its 4 parameters and the field logic (run/analysis/typed/fn_0x4676f0.c) decompiled+trace
+0x481360 rmEngineContextAlloc rm builds NV_ESC_RM_ALLOC requests per class (0x80 device, 0x5/0x79 per-class table, 0x2080 subdevice array of 32, default generic with the record as params) and returns small status codes; class comes from the engine record, so a zeroed secondary record means class 0 is rewritten to NV01_ROOT_CLIENT (0x41), status 0x19, and the context rolls back (rc=999) decompiled+trace
0x453cc0 cudaEngineContextCleanup engine-engines failure-path cleanup of an engine context; runs on the rolled-back context (rc=999) decompiled
+# --- engine record construction (the record identity and the COPY14 blocker; see docs/05 section 3.7) ---
+0x450ff0 cudaDeviceBuildEngineRecords engine-engines builds the 0x14-byte per-engine records from the GET_ENGINES_V2 list at device+0x2aa8 (count +0x2fe8): kind 1 GR -> +0x2fec (class device+0xd38), kind 3 copy -> +0x300c+n*0x14 (class +0xd44, caps bit0 = CE_GRCE also seeds the secondary record at *(device+0x4af0)+0x75c), kind 4 SEC2 -> +0x350c (class +0xd4c), kind 5 decomp copy -> +0x351c+n*0x14 (class +0xd50); fields +0 kind, +4 NV2080 engine type, +8 instance, +0xc class, +0x10 caps decompiled+trace
+0x462770 cudaRmGetEngines engine-engines RM control AL wrapper for NV2080_CTRL_CMD_GPU_GET_ENGINES_V2: reads the engine list and classifies each raw NV2080 engine type into {kind, type, instance} records at 0x10-byte stride (GR 1..8 -> kind 1; copy 9..0x12 and 0x34..0x3d -> kind 3; decomp copy 0x40..0x53 -> kind 5; SEC2 0x26 -> kind 4; others skipped); called from 0x44ac20 via AL slot 0x1d8 decompiled
+0x44a170 cudaDeviceSupportsClass engine-engines device class-list membership callback installed at device+0x4e00 by the ABI table setup (0x458040 and 0x4494d0): returns true when class is in the class list at device+0xd90 (count +0xd98); the walker calls it with (device, record+0xc) before registering an engine decompiled+trace
+0x458040 cudaDeviceAbiTableInit engine-engines builds the RM device state and installs the device ABI function table at device+0x4d18.. (engine builder +0x4d88, class callback +0x4e00 = 0x44a170, ctx table setup +0x4ef0, init caps +0x4d38); class list copied from the config block into device+0xd90/+0xd98 decompiled
+0x44ac20 cudaDeviceInitCaps engine-engines device init-caps path: calls the AL getEngines slot 0x1d8 (0x462770) to fill device+0x2aa8/+0x2fe8, then the ABI static-info hooks; the engine list it produces is what the record builder consumes decompiled
# --- CURRENT BLOCKER (2026-09-23): engine list / classDB consistency (async CE COPY14) ---
-0x45a670 cudaDeviceInitEngineContexts engine-engines CURRENT BLOCKER: classDB-filtered engine list has 6 engines in the guest (GR + CE0..4) vs 7 on the host oracle (adds async CE COPY14: engDesc 0x793ceb0e, instance 14, client type 0x38, class 0xc9b5); without a classDB entry the walker reads a zeroed secondary record and the RM alloc is rejected (class 0x41, st 0x19). Record layout above; see docs/05 section 3.6 decompiled+trace
+0x45a670 cudaDeviceInitEngineContexts engine-engines CURRENT BLOCKER: the GET_ENGINES_V2 list has 6 engines in the guest (GR + CE0..4) vs 7 on the host oracle (adds async CE COPY14: engDesc 0x793ceb0e, NV2080 type 0x38, instance 14, paired class 0xc9b5); the classDB filter drops COPY14, so no copy record carries CE_GRCE (caps bit0, live guest 0xbc/0xfc) and the secondary record at *(table+0x4af0)+0x75c stays zero (host t=2 cls=0xc5b5); the zero class is rewritten to 0x41 (st 0x19) and the context rolls back. Record field map and builder chain in docs/05 section 3.7 decompiled+trace
# --- open questions ---
0x4a7e90 FUN_004a7e90 unknown called by every generated wrapper; likely tool/trace dispatch or thread-data helper todo
0x2cb940 FUN_002cb940 unknown large function (10 KB) reachable from the cuInit wrapper; candidate init implementation todo
+# --- wrapper callees verified in the 2026-09 name-candidate pass ---
+# Names proposed by tools/name_candidates.py (see name-candidates.tsv), each
+# verified by reading its body in the 570.144 corpus; source `wrapper-callee`
+# in names.tsv. Evidence: decompiled.
+0x1a36d0 impl_cuCtxGetApiVersion api current-context API version getter: resolves the thread context and returns its API-version field decompiled (wrapper-callee)
+0x1a4900 impl_cuArrayGetMemoryRequirements mem array memory-requirements getter: refreshes the backing-store state under the context mutex and returns the allocation size decompiled (wrapper-callee)
+0x1a5410 impl_cuArrayGetPlane mem array plane getter: validates the plane index and returns the plane handle decompiled (wrapper-callee)
+0x1a5820 impl_cuDevicePrimaryCtxGetState api primary-context state getter: reads flags/active state under the device mutex decompiled (wrapper-callee)
+0x1a6150 impl_cuDeviceRegisterAsyncNotification api device async-notification registration: allocates and links a notification record under the device mutex decompiled (wrapper-callee)
+0x1a6430 impl_cuCtxAttach api context attach: increments the context attach refcount under the context lock decompiled (wrapper-callee)
+0x1a66f0 impl_cuCtxGetCurrent api current-context getter: returns the calling thread's context from TLS decompiled (wrapper-callee)
+0x1a6850 impl_cuCtxGetDevice api context device getter: resolves the current context and returns its device ordinal decompiled (wrapper-callee)
+0x1a6960 impl_cuCtxGetFlags api context flags getter: composes flags from context fields under the context lock decompiled (wrapper-callee)
+0x1a6af0 impl_cuFlushGPUDirectRDMAWrites api GPUDirect RDMA write flush: validates args and dispatches through the device op table decompiled (wrapper-callee)
+0x1a6c50 impl_cuCtxGetExecAffinity api context exec-affinity getter: returns the affinity value under the context lock decompiled (wrapper-callee)
+0x1a7320 impl_cuDeviceGetLuid api device LUID getter: bounds-checks the ordinal and calls the device op at table+0x5180 decompiled (wrapper-callee)
+0x1ae3d0 impl_cuDeviceComputeCapability api compute-capability getter: reads device attributes 0x4b/0x4c decompiled (wrapper-callee)
+0x1ae550 impl_cuDeviceGetProperties api device properties getter: fills CUDA device properties from the device record decompiled (wrapper-callee)
+0x1ae780 impl_cuDeviceGetAttribute api device attribute getter: validates the ordinal and reads one attribute (fast path for attribute 0x20080403) decompiled (wrapper-callee)
+0x1be900 impl_cuCtxDestroy api context destroy: validates the handle, takes the context lock and tears the context down decompiled (wrapper-callee)
+0x1da450 impl_cuMemFree mem device memory free: resolves the allocation under the context lock and frees it decompiled (wrapper-callee)
+0x1da880 impl_cuMemFreeHost mem host memory free: frees pinned host memory (or routes to the device free path) decompiled (wrapper-callee)
+0x1e9ab0 impl_cuModuleLoad module module load from file: reads the file and parses it into the context decompiled (wrapper-callee)
+0x1e9d80 impl_cuModuleLoadData module module load from memory image: same path as file load with an in-memory image decompiled (wrapper-callee)
+0x2891d0 impl_cuEventDestroy sync event destroy: unlinks and frees an event under the context mutex decompiled (wrapper-callee)
+0x2a6bf0 impl_cuGraphDebugDotPrint launch graph DOT dump: writes the graph as a DOT debug file decompiled (wrapper-callee)
+0x2ce4e0 impl_cuLinkCreate jit linker create: allocates and initializes the linker state decompiled (wrapper-callee)
+0x2f9f00 impl_cuModuleGetGlobal module module global getter: resolves a named global through the module symbol table decompiled (wrapper-callee)
+0x3c9250 impl_cuMemFreeAsync mem async device memory free: resolves the allocation and frees it on a stream decompiled (wrapper-callee)
+0x400ec0 impl_cuMemAlloc mem device memory alloc: validates/derives the allocation descriptor and allocates decompiled (wrapper-callee)
+0x402a30 impl_cuMemGetAddressRange mem allocation lookup: resolves the allocation containing an address under the context mutex decompiled (wrapper-callee)
+0xd11d90 impl_cuStreamBeginCapture stream stream begin capture: validates the mode and starts capture under the stream lock decompiled (wrapper-callee)
+0xd668f0 impl_cuLibraryGetUnifiedFunction module library function getter: resolves a named function through the library symbol table decompiled (wrapper-callee)
diff --git a/userspace/cuda/570.144/ghidra/DecompileAt.java b/userspace/cuda/570.144/ghidra/DecompileAt.java
index 5092ee9..f1572c7 100644
--- a/userspace/cuda/570.144/ghidra/DecompileAt.java
+++ b/userspace/cuda/570.144/ghidra/DecompileAt.java
@@ -1,5 +1,18 @@
// SPDX-License-Identifier: BSD-3-Clause
//
+// ###########################################################################
+// # WARNING: DEPRECATED - DO NOT USE FOR NEW ANALYSIS (kept for history). #
+// # #
+// # It treats its argument as a Ghidra program address, but the analysis #
+// # convention here is FILE virtual addresses (libcuda+0x...) and Ghidra #
+// # loads these binaries at image base 0x100000. Called with a file vaddr #
+// # it decompiles the function 0x100000 bytes too low (the bug behind the #
+// # old `helper_453ef0.c` / `fn_0x481360.c` artifacts). #
+// # #
+// # Replacement: tools/ghidra/DecompileAt.java (adds the image base) used #
+// # through tools/ghidra_decompile_at.sh. #
+// ###########################################################################
+//
// DecompileAt.java - Ghidra post-script: decompile the function containing a
// given address (no auto-analysis required).
//
diff --git a/userspace/cuda/570.144/scripts/ghidra_analyze.sh b/userspace/cuda/570.144/scripts/ghidra_analyze.sh
index b844300..eb8422b 100755
--- a/userspace/cuda/570.144/scripts/ghidra_analyze.sh
+++ b/userspace/cuda/570.144/scripts/ghidra_analyze.sh
@@ -1,6 +1,21 @@
#!/bin/bash
# SPDX-License-Identifier: BSD-3-Clause
#
+# ###########################################################################
+# # WARNING: DEPRECATED - DO NOT USE FOR NEW ANALYSIS (kept for history). #
+# # #
+# # Two bugs make its output unusable: #
+# # 1. It passes FILE virtual addresses to Ghidra, which loads these #
+# # binaries at image base 0x100000. Every address is 0x100000 too low, #
+# # so the decompiled "functions" are the wrong ones. #
+# # 2. `-analysisTimeoutPerFile 0` does not mean "no timeout" in this #
+# # Ghidra build: it aborts auto-analysis immediately, producing an #
+# # analysed-looking project with no analysis at all. #
+# # #
+# # Replacement: tools/ghidra_full_analysis.sh (plus #
+# # tools/ghidra/ConfigureAnalysis.java). #
+# ###########################################################################
+#
# ghidra_analyze.sh - import a library into a Ghidra project and run the full
# auto-analysis once. The project is kept, so later decompilations are cheap:
#
diff --git a/userspace/cuda/570.144/scripts/ghidra_decompile_project.sh b/userspace/cuda/570.144/scripts/ghidra_decompile_project.sh
index 66d7c90..b44b2b2 100755
--- a/userspace/cuda/570.144/scripts/ghidra_decompile_project.sh
+++ b/userspace/cuda/570.144/scripts/ghidra_decompile_project.sh
@@ -1,6 +1,19 @@
#!/bin/bash
# SPDX-License-Identifier: BSD-3-Clause
#
+# ###########################################################################
+# # WARNING: DEPRECATED - DO NOT USE FOR NEW ANALYSIS (kept for history). #
+# # #
+# # It passes a FILE virtual address straight to 570.144/ghidra/ #
+# # DecompileAt.java, but Ghidra loads these binaries at image base #
+# # 0x100000: the script resolves (and decompiles) the function 0x100000 #
+# # bytes too low. It also depends on a project produced by the broken #
+# # ghidra_analyze.sh above. #
+# # #
+# # Replacement: tools/ghidra_decompile_at.sh, which translates the file #
+# # vaddr with tools/ghidra/DecompileAt.java (file-vaddr aware). #
+# ###########################################################################
+#
# ghidra_decompile_project.sh - decompile a function from an already-analyzed
# Ghidra project (run scripts/ghidra_analyze.sh once first). No re-import and
# no analysis, so this takes seconds.
diff --git a/userspace/cuda/READ-ME-FIRST.md b/userspace/cuda/READ-ME-FIRST.md
index 180907f..2abb797 100644
--- a/userspace/cuda/READ-ME-FIRST.md
+++ b/userspace/cuda/READ-ME-FIRST.md
@@ -112,17 +112,22 @@ userspace/cuda/
├── README.md index + honest status
├── docs/01..07 public analysis (tracked)
├── tools/ reusable tooling (tracked)
-├── LOCAL-SOURCES.md local source map (gitignored)
+│ ├── cudatool.py ELF exports/FDEs/wrappers/delta/fdematch
+│ ├── callwalk.py callee/caller/path walker
+│ ├── name_candidates.py API-implementation name candidates
+│ ├── subsystem_digest.py per-subsystem call-tree digest
+│ ├── diff_corpus.py corpus diff across driver versions
+│ └── ghidra_*.sh, ghidra/ Ghidra analysis/decompile/name-map scripts
└── 570.144/
├── README.md, docs/, scripts/ version-specific helpers + old write-up
├── annotations/ name map + subsystem index (tracked)
- ├── LOCAL-ANALYSIS.md local version notes (gitignored)
└── run/
├── libcuda.so.570.144 the guest binary (md5 ed5b2fc0…)
├── ghidra-full/ analyzed project (29,494 functions)
├── analysis/elf-index/ functions/exports/callgraph/strings TSVs
├── analysis/decompiled/ raw corpus (29,254 functions, 0 failures)
- └── analysis/decompiled-annotated/ corpus + names + call context
+ ├── analysis/decompiled-annotated/ corpus + names + call context
+ └── analysis/subsystem-digest.txt, fdematch-*.txt generated reports
```
## 5. Rules while you work in this area
diff --git a/userspace/cuda/README.md b/userspace/cuda/README.md
index 38ff6f5..9c3163d 100644
--- a/userspace/cuda/README.md
+++ b/userspace/cuda/README.md
@@ -70,8 +70,11 @@ userspace/cuda/
├── READ-ME-FIRST.md reading guide for agents/debuggers
├── docs/ public analysis documents
├── tools/ reusable, version-agnostic tooling
-│ ├── cudatool.py ELF/export/FDE/wrapper/version-delta toolkit
+│ ├── cudatool.py ELF/export/FDE/wrapper/delta/fdematch toolkit
│ ├── callwalk.py callgraph callee/caller/path walker
+│ ├── name_candidates.py propose impl names for wrapper callees
+│ ├── subsystem_digest.py per-subsystem call-tree digest
+│ ├── diff_corpus.py diff two decompiled corpus indexes
│ ├── annotate_corpus.py annotate + rename the decompiled corpus
│ ├── ghidra_full_analysis.sh
│ ├── ghidra_export_index.sh
diff --git a/userspace/cuda/docs/05-570.144-decompilation.md b/userspace/cuda/docs/05-570.144-decompilation.md
index 84b377e..4e23866 100644
--- a/userspace/cuda/docs/05-570.144-decompilation.md
+++ b/userspace/cuda/docs/05-570.144-decompilation.md
@@ -162,9 +162,18 @@ engine index >= 0x16 -> table + 0x351c + (index-0x16)*0x14
before the helper, the walker calls the callback at `table+0x4e00`
with `(table, desc->[0xc])` — a
-"does this engine/class exist" check — and only proceeds when it returns
-true. The helper then uses `desc->[0]` (engine kind), `desc->[8]` (instance)
-and `desc->[0xc]` (class) for the registration.
+"does this engine/class exist" check (a class-list membership test; the
+callback pointer is installed by the device ABI table setup at
+`libcuda+0x458040`/`libcuda+0x4494d0`, target `libcuda+0x44a170`) — and only
+proceeds when it returns true. The helper then uses `desc->[0]` (engine kind),
+`desc->[8]` (instance) and `desc->[0xc]` (class) for the registration.
+
+The records are built by `libcuda+0x450ff0` from the engine list that the
+`GET_ENGINES_V2` wrapper `libcuda+0x462770` returns (`{kind, engine type,
+instance}` triples at 0x10-byte stride). The record layout and the full field
+map are in §3.7. Note the walker's index ranges cover copy slots `1..0xa` and
+`0xc..0x15`, with `0xb` used for the SEC2 slot and `>=0x16` for decompression
+copy slots; the engine list is a different, dense array.
### 3.4 The engine create/register function
@@ -232,8 +241,8 @@ path on the host's real driver):
* libcuda asks the driver for the GPU's engines (`GET_ENGINES_V2`). The host
oracle's filtered list has **7** engines: GR, CE0..CE4 and `COPY14`, the
async copy engine. The guest list has only **6** — the same minus `COPY14`.
-* `COPY14`'s engine descriptor is `0x793ceb0e`, instance 14, client engine
- type `0x38`, paired with engine class `0xc9b5`. The GSP-RM firmware's
+* `COPY14`'s engine descriptor is `0x793ceb0e`, instance 14, engine type
+ `0x38`, paired with engine class `0xc9b5`. The GSP-RM firmware's
`{class, engDesc}` pair table pairs OBJCE instances `0..7` with class
`0xcab5` and instances `0x0b..0x13` (including `0x0e` = 14) with class
`0xc9b5`.
@@ -256,24 +265,56 @@ static info and add a 13th device-info entry with descriptor `0x793ceb0e`,
instance 14, RM engine type `0x17`, FIFO tag 6, runlist 5) did not change the
guest list, so the missing input is elsewhere: what builds the driver's
classDB entry for descriptor `0x793ceb0e` (class list/static-info class data
-versus the device-info-table fields) is the open question. The record layout
-the walker reads is in §3.3; the per-engine fields it consumes are
-`+0` (kind), `+8` (instance) and `+0xc` (class).
-
-### 3.7 What the emulation should check first
-
-* **Engine-list/classDB consistency — the active blocker (§3.6).** The engine
- records at the offsets in §3.3 must be present and self-consistent for every
- engine index the walker visits, the "does this engine exist" callback
- (`[table+0x4e00]`) must agree with them, and the whole set must agree with
- the class-filtered engine list the driver builds from the GSP static info
- (`GET_ENGINES_V2` + classDB). A missing entry is silent: the walker then
- reads a zeroed record.
+versus the device-info-table fields) is the open question.
+
+### 3.7 The engine descriptor record, and how it explains the blocker
+
+The device state holds a list of 0x10-byte engine entries plus a parallel set
+of 0x14-byte **per-engine descriptor records**; the walker (§3.3) reads the
+records, the helper and create hook consume them. The record was recovered
+from the record builder (`libcuda+0x450ff0`), the `GET_ENGINES_V2` wrapper
+(`libcuda+0x462770`), the create hook disassembly (`libcuda+0x4676f0`) and the
+live guest dump (`run/gdb32b.out`):
+
+| Offset | Field | Meaning | Evidence |
+|---|---|---|---|
+| `+0x00` | engine kind | `1` = graphics (GR), `3` = copy (CE), `4` = SEC2, `5` = decompression copy. The helper normalizes `1` to `0` for the per-context slot index. | builder branches on it; `GET_ENGINES_V2` wrapper classifies each engine type into it; live: GR `t=1`, CE `t=3` |
+| `+0x04` | engine type | raw `NV2080_ENGINE_TYPE` from the engine list (`1` = GR, `9..13` = COPY0..4, `0x38` = COPY14) | builder copies the first 8 bytes of the list entry into `+0/+4`; not read by the walker/helper |
+| `+0x08` | instance | engine instance (`COPY0..4` → `0..4`, `COPY14` → `14`) | helper + create hook read it; create hook copies it into the RM alloc parameters only for kinds 2/3/5; live dump |
+| `+0x0c` | class | RM allocation class for this engine: GR → the device's compute class (live `0xc5c0`), copy → the DMA copy class (live `0xc5b5`), SEC2/decomp copy → their classes | builder stores the per-kind class; the create hook passes `+0xc` straight to `libcuda+0x481360` as the `NV_ESC_RM_ALLOC` class; host capture shows `class=0xc5b5` |
+| `+0x10` | engine caps | for copy records: the CE capability bitmask; **bit 0 (`CE_GRCE`) marks the async/GRCE copy engine**. A copy record with bit 0 set is also copied to the *secondary record* slot and does not take a normal CE slot. | builder tests `+0x10 & 1` and copies to the secondary; live caps `0xbc`/`0xfc` (bit 0 clear) |
+
+Secondary record: the GR context registers a second engine from a dedicated
+0x14-byte slot (same layout) that is filled from the GRCE-capable copy record
+and then normalized to kind `2` and the async copy class. GR's own record is
+larger (a 0x20-byte slot with an unrecovered tail at `+0x10..+0x1f`).
+
+**How this explains the blocker.** The builder derives the records from the
+engine list the driver returns for `GET_ENGINES_V2`; the guest list has 6
+entries (GR + CE0..4) because the class-database filter drops `COPY14`. With
+no `COPY14` entry there is no copy record with the `CE_GRCE` capability bit
+set, so the secondary record slot is never filled and the walker sees class
+`0`. libcuda then allocates the engine object with class `0`, the escape path
+rewrites that to `NV01_ROOT_CLIENT` (`0x41`), the allocation fails with status
+`0x19`, the context rolls back and `cuCtxCreate` returns 999. In other words:
+the guest is not merely missing one entry in a list — it is missing the
+*async copy engine record that seeds the secondary record*.
+
+**What the emulation should check first (revised)**:
+
+* **`COPY14` in `GET_ENGINES_V2`** — the engine's classDB entry must exist so
+ that `gpuUpdateEngineTable`'s class-list filter keeps OBJCE instance 14.
+ The class/advertised-engine-table consistency is the root cause; the
+ secondary-record zeroing is its symptom.
+* **CE capabilities.** The copy records' caps word must carry the `CE_GRCE`
+ bit for the async CE. If `COPY14` is restored but its emulated CE caps still
+ return bit 0 clear, the secondary record stays empty and the class-0
+ allocation returns.
* **Consumed-control reply fidelity.** The controls answered generically (the
host log lists `0x20803039`, `0x20802a12`, `0x20808162`, `0x2080182b`,
`0x20800a70`, `0x20800a93`, …) should be checked for consumed fields, because
the walker's engine table is built from data the driver collected earlier
- (device caps, engine list, class list).
+ (device caps, engine list, class list, CE caps).
* The `NV_ESC_RM_ALLOC` parameter block built by `libcuda+0x481360` for class
`0xc5c0` (`TURING_COMPUTE_A`) must be answered with a coherent object: echo
the request's params back (§3.5) and return a coherent handle; the driver
@@ -307,7 +348,15 @@ citations in docs and gdb sessions use the same numbers.
holds our name map (exports are exact, internals grow over time).
* The decompiler does not recover struct types; field offsets are named
`[obj+0xNN]` and must be interpreted with the descriptions in `docs/01`
- and `docs/03`.
+ and `docs/03`. A targeted Decompiler Parameter ID pass
+ (`tools/ghidra/AnalyzeFunctions.java`, see `docs/06` §2d) re-ran over 80
+ key functions (crash/engine path, resolved wrapper implementations, largest
+ `.text`) and committed their signatures into a project copy
+ (`run/ghidra-typed/`); the re-decompiled bodies are in
+ `run/analysis/typed/` and the before/after report in
+ `run/analysis/typed/paramid_report.tsv`. 16 of 80 bodies changed materially
+ (parameter/type recovery), the rest now carry committed signatures that
+ improve downstream decompilation.
* Indirect calls dominate the API dispatch; the callgraph contains direct
edges only (77,742). Cross-referencing indirect targets requires reading the
wrapper/stub relocations (as in §2) or live traces.
diff --git a/userspace/cuda/docs/06-tooling.md b/userspace/cuda/docs/06-tooling.md
index 85d1c8c..72fc8ac 100644
--- a/userspace/cuda/docs/06-tooling.md
+++ b/userspace/cuda/docs/06-tooling.md
@@ -8,6 +8,9 @@ tools are stdlib-only or Ghidra scripts; nothing needs network access.
userspace/cuda/tools/
├── cudatool.py ELF/interface toolkit (python3, no deps)
├── callwalk.py callee/caller trees and shortest call path
+├── name_candidates.py propose impl names for wrapper callees
+├── subsystem_digest.py per-subsystem call-tree digest
+├── diff_corpus.py diff two decompiled corpus indexes
├── annotate_corpus.py annotated + name-substituted corpus
├── ghidra_full_analysis.sh import + full auto-analysis into a project
├── ghidra_export_index.sh functions/exports/callgraph/strings index
@@ -19,6 +22,7 @@ userspace/cuda/tools/
├── ExportFunctionIndex.java index exporter
├── BatchDecompile.java chunk decompiler
├── DecompileAt.java single function (file-vaddr aware)
+ ├── AnalyzeFunctions.java targeted Decompiler Parameter ID pass
├── ApplyNameMap.java apply/transfer a name map
└── PrintProgramInfo.java address convention + stats
```
@@ -34,12 +38,33 @@ tools/cudatool.py crash <lib> <map_base> <ip> # dmesg -> file vaddr
tools/cudatool.py strings <lib> [--grep RE]
tools/cudatool.py note <lib> # .note.cuda.fwd_compatibility JSON
tools/cudatool.py delta <libA> <libB> # see §4
+tools/cudatool.py fdematch <libA> <libB> [--names names.tsv] [--window 0x100]
```
Useful for: checking what changed between two driver package versions before
spending time on decompilation; converting a guest dmesg crash to a file vaddr
without gdb; getting a function list in a second.
+### 1b. Cross-version function matching — `fdematch`
+
+```
+tools/cudatool.py fdematch <libA> <libB> [--names <names.tsv>] [--window 0x100]
+```
+
+`fdematch` matches function ranges from the two `.eh_frame_hdr` tables. A
+single global address shift is not enough across patch versions, so it uses
+the common exports as **local anchors**: for each A function it looks for a B
+function with the same FDE size within `--window` bytes of
+`old_addr + delta(nearest common export)`. The report gives exact / window /
+unique match counts and the overall match rate, and with `--names` it breaks
+the name map down by its `source` column (exports, wrappers, verified,
+wrapper-callee), which is exactly what you need to know before transferring
+names to a new version. Example result for 570.144 → 570.211.01: 85.5% of
+functions match (58.3% uniquely), **all 659 exports transfer exactly, but
+only ~1% of the generated wrapper addresses do** — the wrapper region is
+regenerated and must be re-resolved with `cudatool.py wrappers`, never by
+address arithmetic.
+
### Address conventions
* `cudatool.py` prints **file virtual addresses** — the `libcuda+0x...` used
@@ -102,6 +127,67 @@ tools/callwalk.py <indexdir>/callgraph.tsv chain 0x31b7f0 0x2cb940
Addresses are file vaddrs; `names.tsv` next to the callgraph is used for
labels.
+## 2d. Targeted type recovery
+
+The full analysis disables the Decompiler Parameter ID analyzer (§2), so
+function signatures stay at the default `FUN_<addr>(...)`. `AnalyzeFunctions.java`
+re-runs that analyzer over a caller-supplied function list instead of the whole
+program: it takes an addresses file (one `0x<file_vaddr>` per line, comments
+allowed), translates through the image base like `DecompileAt.java`, resolves
+each address to its function and runs the analyzer on the resulting address
+set (batched, with a per-function decompiler timeout). Run it against a
+project copy, not the canonical one, because it commits parameters into the
+project:
+
+```
+cp -a <proj_dir> <proj_dir>-typed
+analyzeHeadless <proj_dir>-typed <proj_name> -process <program> -noanalysis \
+ -scriptPath tools/ghidra \
+ -postScript AnalyzeFunctions.java <addresses.txt> \
+ --timeout 120 --batch 20 --out <report.tsv>
+```
+
+Then re-decompile the affected functions with `ghidra_decompile_at.sh` from the
+typed project; the report's `params_before/after` and `GAIN` columns show
+which functions gained structure. `--list` resolves the list without running
+the analyzer (dry run).
+
+## 2d. Subsystem call-tree digest — `subsystem_digest.py`
+
+```
+tools/subsystem_digest.py <subsystems.tsv> <callgraph.tsv> [--out FILE]
+ [--depth 2] [--max-per-node 8] [--subsystem NAME]
+```
+
+For every subsystem in `annotations/subsystems.tsv` it prints the annotated
+members, the subsystem **entry functions** (members not called by another
+member of the same subsystem) and a depth-limited call tree from each entry
+whose direct callees are grouped by subsystem. It closes with a
+cross-subsystem edge count matrix. This is the quickest way to see a
+subsystem's shape and where its boundary with the rest of the driver is,
+without opening Ghidra. Example output for 570.144 is saved under
+`570.144/run/analysis/subsystem-digest.txt` (gitignored).
+
+## 2e. API-implementation candidates — `name_candidates.py`
+
+```
+tools/name_candidates.py <exports.tsv> <callgraph.tsv> <names.tsv> <out.tsv>
+ [--max-outside 2]
+```
+
+Exports are generated stubs → generated wrappers → the hand-written
+implementation of that API. `name_candidates.py` groups the wrappers by base
+name (stripping `_v<N>`, `_ptsz`, `_ptds`), takes the intersection of their
+direct callees and filters out helpers that are also called by wrappers
+outside the group (the trace/init/lock helpers). A single surviving candidate
+is `high` confidence when the group has several variants or the callee is
+unique; otherwise the best-ranked candidate is `medium`. Output rows carry
+the full candidate set and the outside-wrapper count as evidence, plus a
+`status` column that starts as `unverified`. Verification means reading the
+body in the corpus and marking `verified`/`corrected`; only verified entries
+may be copied into `names.tsv` (source `wrapper-callee`). The 570.144 run is
+tracked in `570.144/annotations/name-candidates.tsv`.
+
## 3. Looking things up
```
@@ -131,6 +217,23 @@ first thing to run on a new driver release; it tells you immediately whether
the update is a patch (nothing moved), a feature release (new exports) or a
reshuffle (many moves).
+### 4b. Corpus deltas — `diff_corpus.py`
+
+```
+tools/diff_corpus.py <indexA.tsv> <indexB.tsv> [--label-a A] [--label-b B]
+ [--out FILE] [--max-list 40] [--json]
+```
+
+Diffs two `decompiled_index.tsv` corpora (the merged output of
+`ghidra_batch_decompile.sh` + `ghidra_index_merge.sh`) and reports
+added/removed/moved/resized functions and a summary. Named functions match by
+name; the address shift is estimated from them and anonymous `FUN_*`
+functions match at `old_addr + shift` (a size difference there is a resize).
+This makes a driver upgrade measurable at the function level: run it after
+decompiling the new version to see how much of the previous corpus still
+corresponds. It needs a decompiled index for the other version; if only the
+binary exists, use `cudatool.py fdematch` (no decompilation required).
+
## 5. Name transfer — `ApplyNameMap.java`
```
diff --git a/userspace/cuda/docs/07-version-upgrade-playbook.md b/userspace/cuda/docs/07-version-upgrade-playbook.md
index 337f5eb..23569bd 100644
--- a/userspace/cuda/docs/07-version-upgrade-playbook.md
+++ b/userspace/cuda/docs/07-version-upgrade-playbook.md
@@ -49,6 +49,33 @@ with `PrintProgramInfo.java` before citing addresses.
## 3. Transfer names and knowledge
+Measure the transfer first, before copying anything:
+
+```
+tools/cudatool.py fdematch <previous>/run/libcuda.so.<old> <libcuda.so.<new>> \
+ --names <previous>/annotations/names.tsv
+```
+
+`fdematch` matches function ranges from both `.eh_frame_hdr` tables using the
+common exports as local address anchors (same FDE size within a small window
+of `old_addr + nearest-export delta`), and breaks the previous name map down
+by its `source` column. Measured for **570.144 → 570.211.01**
+(`570.144/run/analysis/fdematch-570.144-570.211.txt`, gitignored):
+
+| Map part | Transferable | How |
+|---|---|---|
+| 659 exports | **100%**, exact | same name, same size, address = old + local delta |
+| verified internals | 5/7 (71%) | anchored same-size window |
+| wrapper-callee internals | 21/29 (72%) | anchored same-size window |
+| generated `wrapper_*` | **1.1%** | **do not transfer by address** |
+| all A functions | 85.5% matched (58.3% unique) | anchored same-size window |
+
+The wrapper result is the important one: the generated wrapper region is
+re-laid-out between patch versions, so wrapper addresses must be re-resolved
+on the new binary with `tools/cudatool.py wrappers` (and then
+`annotate_corpus.py` re-run), never by adding a delta to the old map. Export
+and hand-written internal names do carry over.
+
```
cp <previous>/annotations/names.tsv <new>/annotations/names.tsv
# translate addresses: the map is file-vaddr keyed, so for unchanged
@@ -61,7 +88,9 @@ analyzeHeadless <proj> cuda-full -process <program> -noanalysis \
Also transfer the *subsystem index* (`annotations/subsystems.tsv`: address,
our name, subsystem, evidence) and re-validate the entries that the delta
-marked as moved.
+marked as moved. For corpus-level measurement (added/removed/resized
+functions, not just name transfer) use `tools/diff_corpus.py` on the old and
+new `decompiled_index.tsv` once the new version has been decompiled.
## 4. Validate against the guest
diff --git a/userspace/cuda/docs/08-virtualization-approaches.md b/userspace/cuda/docs/08-virtualization-approaches.md
index 3523ad1..00ca13f 100644
--- a/userspace/cuda/docs/08-virtualization-approaches.md
+++ b/userspace/cuda/docs/08-virtualization-approaches.md
@@ -2,7 +2,7 @@
One-page decision summary for how a guest's CUDA work gets executed in
Open-IOV. Companion to `docs/04-virtualization-and-emulation.md` (design
-principles) and to the project implementation docs (`docs/refactored-architecture.md`,
+principles) and to the project implementation docs (`docs/03-architecture/06-host-module-and-hybrid-model.md`,
`docs/04-implementation/02-practical-challenges-and-adversarial-interop.md`).
## 1. The options
diff --git a/userspace/cuda/tools/cudatool.py b/userspace/cuda/tools/cudatool.py
index 2e4c1c6..3417d2b 100755
--- a/userspace/cuda/tools/cudatool.py
+++ b/userspace/cuda/tools/cudatool.py
@@ -21,6 +21,7 @@
# strings <lib> [--grep RE] defined strings with file offsets
# delta <libA> <libB> interface-level diff between two versions
# wrappers <lib> export stub -> generated wrapper target
+# fdematch <libA> <libB> function-range match report across versions
# note <lib> CUDA forward-compatibility note (JSON)
#
# Address convention: every address printed by this tool is a FILE VIRTUAL
@@ -476,6 +477,151 @@ def cmd_wrappers(args):
print(f"0x{w['stub']:08x} -> 0x{w['wrapper']:08x} {w['name']}")
+def cmd_fdematch(args):
+ """Match function ranges between two libraries by unwind-table (FDE)
+ start/size, using the common exports as local address anchors.
+
+ A single global address shift is not enough across patch versions: the
+ library is partly re-laid-out (function insertions/removals drift the
+ addresses locally, and the generated wrapper region is regenerated). The
+ matcher therefore uses the nearest common export by address as the local
+ anchor and looks for a B function of the same FDE size within a small
+ window around old_start + anchor_delta. This measures how transferable a
+ name map is between two driver versions, and the --names breakdown shows
+ which parts of the map (exports, generated wrappers, internals) survive."""
+ import bisect
+ from collections import Counter, defaultdict
+
+ a, b = ELF(args.libA), ELF(args.libB)
+ fa = {s: (e - s if e is not None else None)
+ for s, e in a.function_ranges()}
+ fb = {s: (e - s if e is not None else None)
+ for s, e in b.function_ranges()}
+
+ ea = {s["name"]: s["value"] for s in a.exports()}
+ eb = {s["name"]: s["value"] for s in b.exports()}
+ common = sorted(set(ea) & set(eb))
+ anchors = sorted((ea[n], eb[n] - ea[n]) for n in common)
+ anchor_addrs = [x for x, _ in anchors]
+ deltas = [d for _, d in anchors]
+ d_counter = Counter(d // 0x1000 * 0x1000 for d in deltas)
+
+ def anchor_delta(v):
+ i = bisect.bisect_left(anchor_addrs, v)
+ cand = []
+ if i < len(anchors):
+ cand.append(anchors[i])
+ if i > 0:
+ cand.append(anchors[i - 1])
+ if not cand:
+ return 0
+ return min(cand, key=lambda t: abs(t[0] - v))[1]
+
+ size_b = defaultdict(list)
+ for s, sz in fb.items():
+ size_b[sz].append(s)
+ for k in size_b:
+ size_b[k].sort()
+
+ def window_matches(v, size, w):
+ if size is None or size not in size_b:
+ return []
+ target = v + anchor_delta(v)
+ starts = size_b[size]
+ lo = bisect.bisect_left(starts, target - w)
+ hi = bisect.bisect_right(starts, target + w)
+ return starts[lo:hi]
+
+ exact = window = unique = unmatched = 0
+ for v, size in fa.items():
+ m = window_matches(v, size, args.window)
+ if not m:
+ unmatched += 1
+ elif v + anchor_delta(v) in m:
+ exact += 1
+ if len(m) == 1:
+ unique += 1
+ else:
+ window += 1
+ if len(m) == 1:
+ unique += 1
+ matched = exact + window
+ total = len(fa)
+ rate = matched / total if total else 0.0
+
+ transfer = None
+ if args.names:
+ transfer = defaultdict(lambda: dict(entries=0, exact=0, window=0,
+ missing=0, not_in_a=0))
+ with open(args.names) as f:
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ p = line.split("\t")
+ if len(p) < 2:
+ continue
+ try:
+ v = int(p[0], 16)
+ except ValueError:
+ continue
+ src = p[2] if len(p) > 2 else "?"
+ t = transfer[src]
+ t["entries"] += 1
+ if v not in fa:
+ t["not_in_a"] += 1
+ continue
+ m = window_matches(v, fa[v], args.window)
+ if not m:
+ t["missing"] += 1
+ elif v + anchor_delta(v) in m:
+ t["exact"] += 1
+ else:
+ t["window"] += 1
+
+ if args.json:
+ print(json.dumps(dict(
+ lib_a=args.libA, lib_b=args.libB,
+ functions_a=total, functions_b=len(fb),
+ anchors=len(anchors),
+ delta_median=hex(deltas[len(deltas) // 2]) if deltas else "0x0",
+ delta_clusters=[[hex(k), v] for k, v in d_counter.most_common(6)],
+ window=hex(args.window),
+ exact=exact, window_matches=window, unique=unique,
+ unmatched=unmatched, match_rate=round(rate, 4),
+ name_map=transfer), indent=1))
+ return
+
+ print(f"fdematch A: {args.libA}")
+ print(f" B: {args.libB}")
+ print(f"functions : A={total} B={len(fb)} "
+ f"(ranges from .eh_frame_hdr)")
+ print(f"anchors : {len(anchors)} common exports")
+ if deltas:
+ print(f"delta clusters : " + ", ".join(
+ f"{'+' if k >= 0 else '-'}0x{abs(k):x} ({v})"
+ for k, v in d_counter.most_common(5)))
+ print(f"matching window : +/-0x{args.window:x} around "
+ f"nearest-anchor-shifted address, same FDE size")
+ print(f"exact match : {exact} ({exact/total*100:.1f}%)"
+ if total else "exact match : 0")
+ print(f"window match : {window} ({window/total*100:.1f}%)"
+ if total else "window match : 0")
+ print(f"unique match : {unique} ({unique/total*100:.1f}%)"
+ if total else "unique match : 0")
+ print(f"unmatched A : {unmatched}")
+ print(f"match rate : {rate*100:.1f}% of A's {total} functions")
+ if transfer:
+ print(f"name map : {args.names} (per source column)")
+ for src in sorted(transfer):
+ t = transfer[src]
+ got = t["exact"] + t["window"]
+ pct = got / t["entries"] * 100 if t["entries"] else 0.0
+ print(f" {src:<14} : {got}/{t['entries']} ({pct:.1f}%) "
+ f"exact={t['exact']} window={t['window']} "
+ f"missing={t['missing']} not-in-A={t['not_in_a']}")
+
+
def cmd_note(args):
elf = ELF(args.lib)
print(json.dumps(elf.cuda_note(), indent=2))
@@ -502,6 +648,14 @@ def main():
p = sub.add_parser("note"); p.add_argument("lib"); p.set_defaults(fn=cmd_note)
p = sub.add_parser("wrappers"); p.add_argument("lib")
p.add_argument("--json", action="store_true"); p.set_defaults(fn=cmd_wrappers)
+ p = sub.add_parser("fdematch"); p.add_argument("libA"); p.add_argument("libB")
+ p.add_argument("--names", default=None,
+ help="names.tsv to report transferability for")
+ p.add_argument("--window", type=lambda x: int(x, 0), default=0x100,
+ help="same-size match window around the anchored address "
+ "(default 0x100)")
+ p.add_argument("--json", action="store_true")
+ p.set_defaults(fn=cmd_fdematch)
args = ap.parse_args()
try:
diff --git a/userspace/cuda/tools/diff_corpus.py b/userspace/cuda/tools/diff_corpus.py
new file mode 100755
index 0000000..7224ac7
--- /dev/null
+++ b/userspace/cuda/tools/diff_corpus.py
@@ -0,0 +1,221 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# diff_corpus.py - diff two decompiled corpus indexes across driver versions.
+#
+# Inputs are `decompiled_index.tsv` files (the merged output of the batch
+# decompiler): a header line and one row per function:
+# addr<TAB>file_addr<TAB>size<TAB>name<TAB>file<TAB>line<TAB>status
+# `addr` is the Ghidra program address, `file_addr` the file virtual address
+# (libcuda+0x...) used everywhere in the analysis.
+#
+# Matching (function identity across versions):
+# 1. Named functions (anything whose name does not start with FUN_) match by
+# name; the same name in both indexes is the same function.
+# 2. The address shift between the two builds is estimated as the median of
+# (file_addrB - file_addrA) over name-matched functions.
+# 3. Anonymous FUN_* functions match when B has a function at
+# file_addrA + shift; a size difference there is reported as a resize.
+# Functions that do not land on a B function are `removed`; B functions
+# that no A function maps to are `added`.
+#
+# This is deliberately address/size based (the corpus has no structural hash),
+# so it measures exactly what matters for name-map transfer: did the function
+# move, grow, disappear or appear.
+#
+# Usage:
+# diff_corpus.py <indexA.tsv> <indexB.tsv> [--label-a A] [--label-b B]
+# [--out FILE] [--max-list N] [--json]
+#
+# Exit status is 0 for a normal report (differences do not fail the tool).
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import argparse
+import json
+import statistics
+import sys
+from collections import Counter, defaultdict
+
+
+def load_index(path):
+ funcs = {}
+ with open(path) as f:
+ f.readline() # header
+ for line in f:
+ p = line.rstrip("\n").split("\t")
+ if len(p) < 4:
+ continue
+ try:
+ funcs[int(p[1], 16)] = dict(addr=int(p[0], 16), size=int(p[2]),
+ name=p[3])
+ except ValueError:
+ continue
+ return funcs
+
+
+def is_named(name):
+ return bool(name) and not name.startswith("FUN_")
+
+
+def label(f, names):
+ if f is None:
+ return "<none>"
+ return f"{names.get(f['name'], f['name'])} (libcuda+0x{f['file']:x}, {f['size']}B)"
+
+
+def main():
+ ap = argparse.ArgumentParser(
+ description=__doc__,
+ formatter_class=argparse.RawDescriptionHelpFormatter)
+ ap.add_argument("index_a")
+ ap.add_argument("index_b")
+ ap.add_argument("--label-a", default=None)
+ ap.add_argument("--label-b", default=None)
+ ap.add_argument("--out", default=None, help="write the report here "
+ "(default: stdout)")
+ ap.add_argument("--max-list", type=int, default=40,
+ help="max entries listed per category (default 40)")
+ ap.add_argument("--json", action="store_true", help="emit JSON")
+ args = ap.parse_args()
+
+ a = load_index(args.index_a)
+ b = load_index(args.index_b)
+ la = args.label_a or args.index_a
+ lb = args.label_b or args.index_b
+
+ named_a = defaultdict(list)
+ named_b = defaultdict(list)
+ for fa, f in a.items():
+ if is_named(f["name"]):
+ named_a[f["name"]].append(fa)
+ for fb, f in b.items():
+ if is_named(f["name"]):
+ named_b[f["name"]].append(fb)
+
+ matched_named = [] # (name, fa, fb)
+ for name in sorted(set(named_a) & set(named_b)):
+ # duplicate symbol names (multiple thunks) match in address order
+ for fa, fb in zip(sorted(named_a[name]), sorted(named_b[name])):
+ matched_named.append((name, fa, fb))
+
+ deltas = [fb - fa for _, fa, fb in matched_named]
+ shift = int(statistics.median(deltas)) if deltas else 0
+ dominant = (sum(1 for d in deltas if abs(d - shift) <= 0x40) /
+ len(deltas)) if deltas else 0.0
+
+ used_a = set(fa for _, fa, _ in matched_named)
+ used_b = set(fb for _, _, fb in matched_named)
+ moved = [(n, fa, fb) for n, fa, fb in matched_named if fa != fb]
+ resized = [(n, fa, fb) for n, fa, fb in matched_named
+ if a[fa]["size"] != b[fb]["size"]]
+
+ shifted = []
+ for fa, f in sorted(a.items()):
+ if fa in used_a or is_named(f["name"]):
+ continue
+ fb = fa + shift
+ if fb in b and fb not in used_b:
+ shifted.append((fa, fb))
+ used_a.add(fa)
+ used_b.add(fb)
+ shifted_resized = [(fa, fb) for fa, fb in shifted
+ if a[fa]["size"] != b[fb]["size"]]
+ shifted_ok = [(fa, fb) for fa, fb in shifted
+ if a[fa]["size"] == b[fb]["size"]]
+
+ removed = sorted(fa for fa in a if fa not in used_a)
+ added = sorted(fb for fb in b if fb not in used_b)
+
+ anon_a = sum(1 for f in a.values() if not is_named(f["name"]))
+ anon_b = sum(1 for f in b.values() if not is_named(f["name"]))
+ named_count_a = sum(len(v) for v in named_a.values())
+ named_count_b = sum(len(v) for v in named_b.values())
+ matched_total = len(matched_named) + len(shifted)
+
+ result = dict(
+ label_a=la, label_b=lb,
+ total_a=len(a), total_b=len(b),
+ named_a=named_count_a, named_b=named_count_b,
+ anon_a=anon_a, anon_b=anon_b,
+ shift=shift, shift_dominant=round(dominant, 4),
+ matched_named=len(matched_named), matched_shifted=len(shifted_ok),
+ matched_shifted_resized=len(shifted_resized),
+ moved=len(moved), resized_named=len(resized),
+ added=len(added), removed=len(removed),
+ match_rate_a=round(matched_total / len(a), 4) if a else 0.0,
+ match_rate_b=round(matched_total / len(b), 4) if b else 0.0,
+ named_transfer_rate=round(len(matched_named) / named_count_a, 4)
+ if named_count_a else 0.0,
+ )
+
+ def hexlist(addrs):
+ return [f"libcuda+0x{x:x} {a[x]['name']} ({a[x]['size']}B)"
+ if x in a else f"libcuda+0x{x:x} {b[x]['name']} ({b[x]['size']}B)"
+ for x in addrs[:args.max_list]]
+
+ if args.json:
+ out = dict(result)
+ out["added_list"] = [f"libcuda+0x{x:x} {b[x]['name']} ({b[x]['size']}B)"
+ for x in added[:args.max_list]]
+ out["removed_list"] = [f"libcuda+0x{x:x} {a[x]['name']} ({a[x]['size']}B)"
+ for x in removed[:args.max_list]]
+ text = json.dumps(out, indent=1)
+ else:
+ lines = []
+ lines.append(f"corpus diff: {la} -> {lb}")
+ lines.append("=" * 72)
+ lines.append(f"functions : A={len(a)} B={len(b)} "
+ f"(named A={len(named_a)} B={len(named_b)}; "
+ f"anonymous A={anon_a} B={anon_b})")
+ lines.append(f"address shift : 0x{shift:x} "
+ f"(dominant for {dominant*100:.1f}% of name matches)")
+ lines.append(f"matched : {matched_total} "
+ f"({len(matched_named)} by name, "
+ f"{len(shifted_ok)} anonymous at shifted address)")
+ lines.append(f"match rate : A {result['match_rate_a']*100:.1f}% "
+ f"B {result['match_rate_b']*100:.1f}% "
+ f"(name map transfer {result['named_transfer_rate']*100:.1f}%)")
+ lines.append(f"moved : {len(moved)} named functions changed "
+ f"address")
+ lines.append(f"resized : {len(resized)} named + "
+ f"{len(shifted_resized)} anonymous matched functions "
+ f"changed size")
+ lines.append(f"added : {len(added)}")
+ lines.append(f"removed : {len(removed)}")
+ lines.append("")
+ if moved:
+ lines.append(f"-- moved named (first {args.max_list}) --")
+ for n, fa, fb in moved[:args.max_list]:
+ lines.append(f" {n}: libcuda+0x{fa:x} -> libcuda+0x{fb:x} "
+ f"({fb-fa:+#x})")
+ if resized:
+ lines.append(f"-- resized named (first {args.max_list}) --")
+ for n, fa, fb in resized[:args.max_list]:
+ lines.append(f" {n}: libcuda+0x{fa:x} {a[fa]['size']}B -> "
+ f"{b[fb]['size']}B")
+ if shifted_resized:
+ lines.append(f"-- resized anonymous (first {args.max_list}) --")
+ for fa, fb in shifted_resized[:args.max_list]:
+ lines.append(f" libcuda+0x{fa:x} {a[fa]['size']}B -> "
+ f"libcuda+0x{fb:x} {b[fb]['size']}B")
+ if added:
+ lines.append(f"-- added (first {args.max_list}) --")
+ lines.extend(" " + x for x in
+ hexlist(added))
+ if removed:
+ lines.append(f"-- removed (first {args.max_list}) --")
+ lines.extend(" " + x for x in
+ hexlist(removed))
+ text = "\n".join(lines)
+
+ if args.out:
+ with open(args.out, "w") as f:
+ f.write(text + "\n")
+ else:
+ print(text)
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/userspace/cuda/tools/ghidra/AnalyzeFunctions.java b/userspace/cuda/tools/ghidra/AnalyzeFunctions.java
new file mode 100644
index 0000000..e0ae6cb
--- /dev/null
+++ b/userspace/cuda/tools/ghidra/AnalyzeFunctions.java
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: BSD-3-Clause
+//
+// AnalyzeFunctions.java - Ghidra post-script: run the "Decompiler Parameter ID"
+// analyzer over a caller-supplied list of functions, using the analyzer's
+// AddressSetView entry point instead of a whole-program analysis pass.
+//
+// This is the targeted type-recovery pass for the CUDA userspace driver: the
+// full auto-analysis deliberately disables the parameter-ID analyzer because it
+// decompiles every function and is very expensive on a 29k-function stripped
+// binary. Re-running it over a curated address set (crash path, engine-record
+// path, handle pool, RM alloc, resolved wrapper implementations, the largest
+// .text functions) recovers parameter counts/types and local variables where
+// the decompiler can infer them, without touching the rest of the program.
+//
+// Usage:
+// analyzeHeadless <proj_dir> <proj_name> -process <program> -noanalysis \
+// -scriptPath tools/ghidra \
+// -postScript AnalyzeFunctions.java <addresses_file> \
+// [--timeout <secs>] [--out <tsv>] [--list] [--batch <n>]
+//
+// <addresses_file> one entry per line: "0x<file_vaddr> [# comment]".
+// Addresses are FILE virtual addresses (libcuda+0x...).
+// Blank lines and lines starting with '#' are ignored.
+// --timeout <secs> per-function decompiler timeout for the analyzer
+// (default 60, matching the analyzer's own default).
+// --out <tsv> write the before/after report to this file as well.
+// --list only resolve the addresses to functions and print them;
+// do not run the analyzer (dry run).
+// --batch <n> run the analyzer in batches of n functions (default 0 =
+// one batch). Useful to checkpoint very large sets.
+//
+// The script translates file vaddr -> program address via the program's image
+// base (0x100000 for this binary), exactly like DecompileAt.java. If an address
+// is not inside a known function it is disassembled and turned into one.
+//
+// The analyzer class was renamed between Ghidra versions
+// (DecompilerParameterIdAnalyzer -> DecompilerFunctionAnalyzer); the script
+// looks up both and invokes the AddressSetView-based entry point
+// added(AddressSetView, TaskMonitor) when present, falling back to
+// added(Program, AddressSetView, TaskMonitor, MessageLog).
+
+import ghidra.app.script.GhidraScript;
+import ghidra.app.services.Analyzer;
+import ghidra.app.util.importer.MessageLog;
+import ghidra.framework.options.Options;
+import ghidra.program.model.address.Address;
+import ghidra.program.model.address.AddressSet;
+import ghidra.program.model.address.AddressSetView;
+import ghidra.program.model.listing.Function;
+import ghidra.program.model.listing.FunctionIterator;
+import ghidra.program.model.listing.Listing;
+import ghidra.program.model.listing.Variable;
+import ghidra.util.classfinder.ClassSearcher;
+import ghidra.util.task.TaskMonitor;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+public class AnalyzeFunctions extends GhidraScript {
+
+ private static final String[] ANALYZER_CLASSES = {
+ "ghidra.app.plugin.core.analysis.DecompilerFunctionAnalyzer",
+ "ghidra.app.plugin.core.analysis.DecompilerParameterIdAnalyzer",
+ };
+
+ private static final String OPTION_TIMEOUT = "Analysis Decompiler Timeout (sec)";
+
+ private static class Target {
+ long fileAddr;
+ Address entry;
+ String name;
+ int paramsBefore;
+ int localsBefore;
+ int paramsAfter = -1;
+ int localsAfter = -1;
+ }
+
+ @Override
+ public void run() throws Exception {
+ String[] args = getScriptArgs();
+ if (args.length < 1) {
+ println("usage: AnalyzeFunctions.java <addresses_file> [--timeout secs] " +
+ "[--out tsv] [--list] [--batch n]");
+ return;
+ }
+
+ String addrFile = args[0];
+ int timeoutSecs = 60;
+ String outFile = null;
+ boolean listOnly = false;
+ int batchSize = 0;
+ for (int i = 1; i < args.length; i++) {
+ switch (args[i]) {
+ case "--timeout":
+ timeoutSecs = Integer.parseInt(args[++i]);
+ break;
+ case "--out":
+ outFile = args[++i];
+ break;
+ case "--list":
+ listOnly = true;
+ break;
+ case "--batch":
+ batchSize = Integer.parseInt(args[++i]);
+ break;
+ default:
+ println("unknown argument: " + args[i]);
+ return;
+ }
+ }
+
+ long imageBase = currentProgram.getImageBase().getOffset();
+ List<Long> fileAddrs = readAddresses(addrFile);
+ println("AnalyzeFunctions: " + fileAddrs.size() + " address(es), image base 0x"
+ + Long.toHexString(imageBase));
+
+ List<Target> targets = resolveTargets(fileAddrs, imageBase);
+ println("AnalyzeFunctions: resolved " + targets.size() + " function(s)");
+
+ if (listOnly) {
+ for (Target t : targets) {
+ println(String.format(" libcuda+0x%06x %s program=0x%x params=%d locals=%d",
+ t.fileAddr, t.name, t.entry.getOffset(), t.paramsBefore,
+ t.localsBefore));
+ }
+ return;
+ }
+
+ Analyzer analyzer = newAnalyzer();
+ if (analyzer == null) {
+ println("ERROR: no Decompiler Parameter ID analyzer class found");
+ return;
+ }
+ println("AnalyzeFunctions: analyzer = " + analyzer.getClass().getName()
+ + ", timeout = " + timeoutSecs + "s");
+
+ Options opts = currentProgram.getOptions("Analyzers");
+ analyzer.registerOptions(opts, currentProgram);
+ if (opts.contains(OPTION_TIMEOUT)) {
+ opts.setInt(OPTION_TIMEOUT, timeoutSecs);
+ }
+ analyzer.optionsChanged(opts, currentProgram);
+
+ int txId = currentProgram.startTransaction("AnalyzeFunctions parameter ID");
+ boolean commit = false;
+ try {
+ runAnalyzer(analyzer, targets, batchSize);
+ commit = true;
+ }
+ finally {
+ currentProgram.endTransaction(txId, commit);
+ }
+
+ snapshotAfter(targets, imageBase);
+ report(targets, outFile);
+ }
+
+ private List<Long> readAddresses(String path) throws Exception {
+ List<Long> out = new ArrayList<>();
+ try (BufferedReader r = new BufferedReader(new FileReader(path))) {
+ String line;
+ while ((line = r.readLine()) != null) {
+ line = line.trim();
+ if (line.isEmpty() || line.startsWith("#")) {
+ continue;
+ }
+ String tok = line.split("\\s+")[0];
+ if (tok.startsWith("0x") || tok.startsWith("0X")) {
+ tok = tok.substring(2);
+ }
+ try {
+ out.add(Long.parseUnsignedLong(tok, 16));
+ }
+ catch (NumberFormatException e) {
+ println("WARN: bad address line: " + line);
+ }
+ }
+ }
+ return out;
+ }
+
+ private List<Target> resolveTargets(List<Long> fileAddrs, long imageBase) {
+ List<Target> targets = new ArrayList<>();
+ Listing listing = currentProgram.getListing();
+ for (long fileAddr : fileAddrs) {
+ Address addr = toAddr(fileAddr + imageBase);
+ Function f = getFunctionContaining(addr);
+ if (f == null) {
+ FunctionIterator it = listing.getFunctions(addr, false);
+ if (it.hasNext()) {
+ f = it.next();
+ }
+ }
+ if (f == null) {
+ disassemble(addr);
+ f = createFunction(addr, null);
+ }
+ if (f == null) {
+ println("WARN: no function at libcuda+0x" + Long.toHexString(fileAddr));
+ continue;
+ }
+ Target t = new Target();
+ t.fileAddr = fileAddr;
+ t.entry = f.getEntryPoint();
+ t.name = f.getName();
+ t.paramsBefore = f.getParameterCount();
+ t.localsBefore = f.getLocalVariables().length;
+ targets.add(t);
+ }
+ return targets;
+ }
+
+ private Analyzer newAnalyzer() throws Exception {
+ // Preferred path: the plugin service discovers analyzers via ClassSearcher,
+ // which also works when the analyzer lives in a module that is not visible
+ // to the script's class loader (Class.forName then fails).
+ try {
+ ClassSearcher.search(monitor);
+ for (Class<? extends Analyzer> c : ClassSearcher.getClasses(Analyzer.class)) {
+ Object o = c.getDeclaredConstructor().newInstance();
+ Analyzer a = (Analyzer) o;
+ if ("Decompiler Parameter ID".equals(a.getName())) {
+ return a;
+ }
+ }
+ }
+ catch (Exception e) {
+ println("WARN: ClassSearcher lookup failed: " + e);
+ }
+ // Fallback: direct reflection over the known class names.
+ for (String cn : ANALYZER_CLASSES) {
+ try {
+ Class<?> c = Class.forName(cn);
+ Object o = c.getDeclaredConstructor().newInstance();
+ if (o instanceof Analyzer) {
+ return (Analyzer) o;
+ }
+ }
+ catch (ClassNotFoundException e) {
+ // try next candidate
+ }
+ }
+ return null;
+ }
+
+ private void runAnalyzer(Analyzer analyzer, List<Target> targets, int batchSize)
+ throws Exception {
+ Method addedSet = findMethod(analyzer.getClass(), "added",
+ AddressSetView.class, TaskMonitor.class);
+ Method addedProgram = findMethod(analyzer.getClass(), "added",
+ ghidra.program.model.listing.Program.class, AddressSetView.class,
+ TaskMonitor.class, MessageLog.class);
+ if (addedSet == null && addedProgram == null) {
+ throw new NoSuchMethodException("no supported added(...) entry point on "
+ + analyzer.getClass().getName());
+ }
+
+ int n = (batchSize > 0) ? batchSize : targets.size();
+ for (int start = 0; start < targets.size(); start += n) {
+ int end = Math.min(start + n, targets.size());
+ AddressSet set = new AddressSet();
+ for (int i = start; i < end; i++) {
+ set.addRange(targets.get(i).entry, targets.get(i).entry);
+ }
+ println(String.format("AnalyzeFunctions: batch %d..%d (%d functions)",
+ start, end - 1, end - start));
+ try {
+ if (addedSet != null) {
+ addedSet.invoke(analyzer, set, monitor);
+ }
+ else {
+ addedProgram.invoke(analyzer, currentProgram, set, monitor,
+ new MessageLog());
+ }
+ }
+ catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ println("WARN: analyzer threw for batch " + start + ".." + (end - 1)
+ + ": " + (cause == null ? e : cause));
+ }
+ }
+ }
+
+ private Method findMethod(Class<?> c, String name, Class<?>... params) {
+ for (Class<?> k = c; k != null; k = k.getSuperclass()) {
+ try {
+ Method m = k.getDeclaredMethod(name, params);
+ m.setAccessible(true);
+ return m;
+ }
+ catch (NoSuchMethodException e) {
+ // keep walking up the hierarchy
+ }
+ }
+ return null;
+ }
+
+ private void snapshotAfter(List<Target> targets, long imageBase) {
+ for (Target t : targets) {
+ Function f = getFunctionAt(t.entry);
+ if (f == null) {
+ continue;
+ }
+ t.paramsAfter = f.getParameterCount();
+ Variable[] locals = f.getLocalVariables();
+ t.localsAfter = locals.length;
+ if (t.name.startsWith("FUN_") && !f.getName().equals(t.name)) {
+ t.name = f.getName();
+ }
+ }
+ }
+
+ private void report(List<Target> targets, String outFile) throws Exception {
+ StringBuilder sb = new StringBuilder();
+ sb.append("# libcuda 570.144 targeted Decompiler Parameter ID pass\n");
+ sb.append("# file_vaddr\tname\tparams_before\tparams_after\tlocals_before\tlocals_after\n");
+ int improved = 0;
+ for (Target t : targets) {
+ boolean gain = t.paramsAfter > t.paramsBefore || t.localsAfter > t.localsBefore;
+ if (gain) {
+ improved++;
+ }
+ sb.append(String.format("0x%06x\t%s\t%d\t%d\t%d\t%d%s\n",
+ t.fileAddr, t.name, t.paramsBefore, t.paramsAfter,
+ t.localsBefore, t.localsAfter, gain ? "\tGAIN" : ""));
+ }
+ sb.append(String.format("# %d/%d functions gained parameters or locals\n",
+ improved, targets.size()));
+ String text = sb.toString();
+ println(text);
+ if (outFile != null) {
+ try (PrintWriter w = new PrintWriter(new FileWriter(outFile))) {
+ w.print(text);
+ }
+ }
+ }
+}
diff --git a/userspace/cuda/tools/name_candidates.py b/userspace/cuda/tools/name_candidates.py
new file mode 100755
index 0000000..7a36a7c
--- /dev/null
+++ b/userspace/cuda/tools/name_candidates.py
@@ -0,0 +1,224 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# name_candidates.py - propose API-implementation names for the hand-written
+# functions called by the generated CUDA API wrappers.
+#
+# Background: every exported cu* entry is a generated stub that jumps through
+# an interposition slot to a generated wrapper (tracing/tool dispatch); the
+# wrapper then calls the hand-written implementation of that API. Export
+# families have several variants of one API (cuMemAlloc_v2, cuMemAlloc_ptsz,
+# cuMemAlloc_ptds, ...), all of which must reach the same implementation.
+#
+# Method (robust, structure-only):
+# 1. Group exported wrappers by BASE NAME: strip the variant suffixes
+# `_v<N>`, `_ptsz`, `_ptds` (in any order/combination) from the export
+# name; all exports in a group are variants of one API.
+# 2. The implementation of a base name is a DIRECT CALLEE shared by ALL of
+# its variants' wrappers, i.e. the intersection of the wrappers' direct
+# callee sets.
+# 3. Filter out global helpers: a candidate is dropped when it is called by
+# >= --max-outside wrappers OUTSIDE its group (trace/init/lock helpers
+# are called by dozens to hundreds of unrelated wrappers). Wrappers are
+# never candidates for themselves.
+# 4. Confidence:
+# high - exactly one candidate survives, and either the group has
+# >= 2 variants (the survivor is shared by all of them) or the
+# survivor is a unique callee (called by exactly one wrapper
+# in the whole library);
+# medium - exactly one survivor but it is also called by another
+# wrapper (possible shared implementation), or several
+# survivors remain (the best-ranked one is proposed).
+# Ranking among several survivors: fewest outside wrappers first, then
+# largest direct-callee count (implementations do work; helpers do not),
+# then lowest address, for a deterministic result.
+#
+# Inputs:
+# <exports.tsv> elf-index exports table: addr file_addr size name
+# <callgraph.tsv> elf-index callgraph: caller callee caller_file callee_file
+# <names.tsv> name map: file_vaddr<TAB>name (wrapper_<export> entries
+# provide the wrapper address of each export)
+# <out.tsv> output (comments + one row per proposal)
+#
+# Output rows (TSV):
+# file_vaddr proposed_name confidence evidence status
+# `proposed_name` is `impl_<base>`; `evidence` carries the wrapper group,
+# candidate callees before/after filtering and the outside-wrapper count;
+# `status` is always `unverified` (the tool proposes, it does not prove).
+# All addresses are FILE virtual addresses (libcuda+0x...).
+#
+# Usage:
+# name_candidates.py <exports.tsv> <callgraph.tsv> <names.tsv> <out.tsv>
+# [--max-outside N] [--quiet]
+
+import argparse
+import re
+import sys
+from collections import defaultdict
+
+
+SUFFIX_RE = re.compile(r"(_ptsz|_ptds)$|_v\d+$")
+
+
+def base_name(name):
+ """Strip CUDA variant suffixes (_v<N>, _ptsz, _ptds) from an export name."""
+ prev = None
+ while prev != name:
+ prev = name
+ name = SUFFIX_RE.sub("", name)
+ return name
+
+
+def load_exports(path):
+ rows = []
+ with open(path) as f:
+ f.readline()
+ for line in f:
+ p = line.rstrip("\n").split("\t")
+ if len(p) < 4:
+ continue
+ try:
+ rows.append(dict(addr=int(p[0], 16), file=int(p[1], 16),
+ size=int(p[2]), name=p[3]))
+ except ValueError:
+ continue
+ return rows
+
+
+def load_names(path):
+ names = {}
+ with open(path) as f:
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ p = line.split("\t")
+ if len(p) >= 2:
+ try:
+ names[int(p[0], 16)] = p[1]
+ except ValueError:
+ pass
+ return names
+
+
+def load_callgraph(path):
+ callees = defaultdict(set)
+ callers = defaultdict(set)
+ with open(path) as f:
+ f.readline()
+ for line in f:
+ p = line.rstrip("\n").split("\t")
+ if len(p) < 4:
+ continue
+ try:
+ cf, kf = int(p[2], 16), int(p[3], 16)
+ except ValueError:
+ continue
+ callees[cf].add(kf)
+ callers[kf].add(cf)
+ return callees, callers
+
+
+def hx(a):
+ return f"0x{a:x}"
+
+
+def main():
+ ap = argparse.ArgumentParser(
+ description=__doc__,
+ formatter_class=argparse.RawDescriptionHelpFormatter)
+ ap.add_argument("exports")
+ ap.add_argument("callgraph")
+ ap.add_argument("names")
+ ap.add_argument("out")
+ ap.add_argument("--max-outside", type=int, default=2,
+ help="drop a candidate called by >= N wrappers outside "
+ "its base-name group (default 2)")
+ ap.add_argument("--quiet", action="store_true")
+ args = ap.parse_args()
+
+ exports = load_exports(args.exports)
+ names = load_names(args.names)
+ callees, callers = load_callgraph(args.callgraph)
+
+ wrapper_by_export = {}
+ for a, n in names.items():
+ if n.startswith("wrapper_"):
+ wrapper_by_export[n[len("wrapper_"):]] = a
+ wrapper_set = set(wrapper_by_export.values())
+
+ groups = defaultdict(list)
+ for e in exports:
+ w = wrapper_by_export.get(e["name"])
+ if w is not None:
+ groups[base_name(e["name"])].append((e["name"], w))
+
+ rows = []
+ n_high = n_med = 0
+ for group in sorted(groups):
+ variants = groups[group]
+ if not variants:
+ continue
+ variant_wrappers = {w for _, w in variants}
+ inter = None
+ for _, w in variants:
+ cs = set(callees.get(w, ()))
+ inter = cs if inter is None else (inter & cs)
+ if not inter:
+ continue
+ before = sorted(inter)
+ survivors = []
+ for c in before:
+ if c in wrapper_set:
+ continue
+ outside = [w for w in callers.get(c, ())
+ if w in wrapper_set and w not in variant_wrappers]
+ if len(outside) >= args.max_outside:
+ continue
+ survivors.append((len(outside), c))
+ if not survivors:
+ continue
+ # rank: fewest outside wrappers, then most direct callees, then address
+ survivors.sort(key=lambda t: (t[0], -len(callees.get(t[1], ())), t[1]))
+ best_outside, best = survivors[0]
+ after = [c for _, c in survivors]
+ if len(survivors) == 1 and (len(variants) >= 2 or
+ len(callers.get(best, ()) & wrapper_set) == 1):
+ confidence = "high"
+ n_high += 1
+ else:
+ confidence = "medium"
+ n_med += 1
+ evidence = (
+ f"group={group} variants=" + ",".join(n for n, _ in variants) +
+ "; before=" + ",".join(hx(c) for c in before) +
+ "; after=" + ",".join(hx(c) for c in after) +
+ f"; outside_wrappers={best_outside}")
+ rows.append((best, f"impl_{group}", confidence, evidence))
+
+ rows.sort()
+ with open(args.out, "w") as f:
+ f.write("# Open-IOV CUDA API-implementation candidates (our own work product; tracked).\n")
+ f.write("# Generated by tools/name_candidates.py from the elf-index exports,\n")
+ f.write("# callgraph and the version's names.tsv; see that script for the method.\n")
+ f.write("#\n")
+ f.write("# file_vaddr<TAB>proposed_name<TAB>confidence<TAB>evidence<TAB>status\n")
+ f.write("# confidence: high = exactly one filtered candidate, shared by >=2 variants\n")
+ f.write("# or a unique callee; medium = one survivor also called by another\n")
+ f.write("# wrapper, or several survivors (best-ranked proposed).\n")
+ f.write("# status: unverified (tool output). Verification = read the body in the\n")
+ f.write("# decompiled corpus and mark verified/corrected here; only verified\n")
+ f.write("# names may be copied into names.tsv.\n")
+ f.write("#\n")
+ for a, name, conf, ev in rows:
+ f.write(f"0x{a:08x}\t{name}\t{conf}\t{ev}\tunverified\n")
+
+ if not args.quiet:
+ print(f"[name_candidates] groups={len(groups)} proposals={len(rows)} "
+ f"(high={n_high} medium={n_med}) -> {args.out}",
+ file=sys.stderr)
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/userspace/cuda/tools/subsystem_digest.py b/userspace/cuda/tools/subsystem_digest.py
new file mode 100755
index 0000000..68f0d09
--- /dev/null
+++ b/userspace/cuda/tools/subsystem_digest.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# subsystem_digest.py - per-subsystem call-tree digest from the tracked
+# subsystem annotations plus the callgraph index.
+#
+# For every subsystem in subsystems.tsv it prints:
+# * members (address, name, role) - the annotated functions;
+# * entry functions - members that are not called by another member of the
+# same subsystem (the roots of the subsystem's call tree);
+# * a depth-limited call tree from each entry, with the direct callees of a
+# node grouped by their subsystem;
+# * a cross-subsystem edge summary (how many calls each subsystem makes into
+# every other one) - the fastest way to see the layering.
+#
+# The digest is a navigation aid: it shows where to start reading the
+# decompiled corpus for a subsystem and which other subsystems it touches,
+# without opening Ghidra. Addresses are FILE virtual addresses (libcuda+0x...).
+#
+# Usage:
+# subsystem_digest.py <subsystems.tsv> <callgraph.tsv> [--out FILE]
+# [--depth N] [--max-per-node N] [--subsystem NAME]
+#
+# <subsystems.tsv> format (comments allowed):
+# file_vaddr<TAB>name<TAB>subsystem<TAB>role<TAB>evidence
+# <callgraph.tsv> format (header):
+# caller<TAB>callee<TAB>caller_file<TAB>callee_file
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import argparse
+import sys
+from collections import defaultdict
+
+
+def load_subsystems(path):
+ members = {}
+ with open(path) as f:
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ p = line.split("\t")
+ if len(p) < 4:
+ continue
+ try:
+ addr = int(p[0], 16)
+ except ValueError:
+ continue
+ members[addr] = dict(name=p[1], subsystem=p[2],
+ role=p[3],
+ evidence=p[4] if len(p) > 4 else "")
+ return members
+
+
+def load_callgraph(path):
+ callees = defaultdict(set)
+ callers = defaultdict(set)
+ with open(path) as f:
+ f.readline()
+ for line in f:
+ p = line.rstrip("\n").split("\t")
+ if len(p) < 4:
+ continue
+ try:
+ cf, kf = int(p[2], 16), int(p[3], 16)
+ except ValueError:
+ continue
+ callees[cf].add(kf)
+ callers[kf].add(cf)
+ return callees, callers
+
+
+def main():
+ ap = argparse.ArgumentParser(
+ description=__doc__,
+ formatter_class=argparse.RawDescriptionHelpFormatter)
+ ap.add_argument("subsystems")
+ ap.add_argument("callgraph")
+ ap.add_argument("--out", default=None,
+ help="write the digest here (default: stdout)")
+ ap.add_argument("--depth", type=int, default=2,
+ help="call-tree depth below each entry (default 2)")
+ ap.add_argument("--max-per-node", type=int, default=8,
+ help="max callees shown per node (default 8)")
+ ap.add_argument("--subsystem", default=None,
+ help="only digest this subsystem")
+ args = ap.parse_args()
+
+ members = load_subsystems(args.subsystems)
+ callees, callers = load_callgraph(args.callgraph)
+
+ by_sub = defaultdict(dict)
+ for addr, m in members.items():
+ by_sub[m["subsystem"]][addr] = m
+
+ def name_of(a):
+ m = members.get(a)
+ if m:
+ return f"{m['name']} (libcuda+0x{a:x})"
+ return f"libcuda+0x{a:x}"
+
+ def sub_of(a):
+ m = members.get(a)
+ return m["subsystem"] if m else "unknown"
+
+ out = []
+ out.append("# Subsystem call-tree digest (generated by tools/subsystem_digest.py)")
+ out.append(f"# subsystems.tsv: {args.subsystems}")
+ out.append(f"# callgraph.tsv : {args.callgraph}")
+ out.append("# Addresses are FILE virtual addresses (libcuda+0x...).")
+ out.append("# entry = annotated member with no caller inside its own subsystem.")
+ out.append("")
+
+ # cross-subsystem edge counts
+ cross = defaultdict(int)
+ for addr, m in members.items():
+ for c in callees.get(addr, ()):
+ cross[(m["subsystem"], sub_of(c))] += 1
+
+ selected = sorted(by_sub)
+ if args.subsystem:
+ selected = [s for s in selected if s == args.subsystem]
+ if not selected:
+ print(f"error: subsystem {args.subsystem!r} not in {args.subsystems}",
+ file=sys.stderr)
+ return 1
+
+ for sub in selected:
+ ms = by_sub[sub]
+ out.append("=" * 72)
+ out.append(f"## {sub} ({len(ms)} annotated members)")
+ out.append("=" * 72)
+ out.append("members:")
+ for a in sorted(ms):
+ m = ms[a]
+ out.append(f" libcuda+0x{a:x}\t{m['name']}\t{m['role']}")
+ entries = sorted(a for a in ms
+ if not (callers.get(a, set()) & set(ms)))
+ if not entries:
+ entries = sorted(ms)
+ out.append("entries: (no entry: every member is called from inside "
+ "the subsystem; showing all)")
+ else:
+ out.append("entries:")
+ for a in entries:
+ out.append(f" {name_of(a)}: {ms[a]['role']}")
+ out.append("call tree:")
+
+ def walk(a, depth, indent, seen):
+ kids = sorted(callees.get(a, ()))
+ if not kids or depth <= 0:
+ return
+ groups = defaultdict(list)
+ for k in kids:
+ groups[sub_of(k)].append(k)
+ for g in sorted(groups):
+ shown = groups[g][:args.max_per_node]
+ more = f" (+{len(groups[g]) - args.max_per_node} more)" \
+ if len(groups[g]) > args.max_per_node else ""
+ out.append(f"{indent}-> {g}: " +
+ "; ".join(name_of(k) for k in shown) + more)
+ for k in kids:
+ if k in seen:
+ continue
+ seen.add(k)
+ walk(k, depth - 1, indent + " ", seen)
+
+ for a in entries:
+ out.append(f" {name_of(a)}")
+ walk(a, args.depth, " ", {a})
+ out.append("")
+
+ out.append("=" * 72)
+ out.append("## cross-subsystem calls (edges from -> to)")
+ out.append("=" * 72)
+ for (src, dst) in sorted(cross):
+ out.append(f" {src:<16} -> {dst:<16} {cross[(src, dst)]}")
+
+ text = "\n".join(out)
+ if args.out:
+ with open(args.out, "w") as f:
+ f.write(text + "\n")
+ else:
+ print(text)
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())