mirror of
https://github.com/morluto/rea.git
synced 2026-10-22 05:42:31 -05:00
167 lines
8.0 KiB
Markdown
167 lines
8.0 KiB
Markdown
# Static CUDA and HIP code objects
|
|
|
|
`inspect_gpu_code_objects` answers which GPU targets and kernel declarations a
|
|
local artifact carries. It reads ELF/PE sections, standalone CUDA fatbins,
|
|
CUBIN/PTX and Clang HIP bundles, including CCOB v1/v2/v3. It neither executes the
|
|
artifact nor invokes CUDA/ROCm tools. GPU execution, SASS disassembly and host
|
|
launch correlation remain outside coverage.
|
|
|
|
Start with a target inventory:
|
|
|
|
```json
|
|
{ "path": "/artifacts/library.so", "view": { "collection": "targets" } }
|
|
```
|
|
|
|
Target rows aggregate inventoried payloads and distinguish an unrequested kernel
|
|
analysis from a complete or partial one. `objects` pages expose exact object
|
|
IDs, compression declarations and encoded/header locations. Fields, exact
|
|
filters, batch IDs and stable pagination select the facts delivered to the
|
|
caller. IDs are positional within the recorded artifact SHA-256. Selecting `object_ids`
|
|
in a new inspection requires `expected_sha256` from that inventory; a changed
|
|
file is rejected before parsing selected payloads.
|
|
|
|
`target` is the inventory declaration used for selection; `payload_target` is
|
|
the independently observed inner declaration when available. Object pages keep
|
|
both values, their kind, `target_consistency` and inspection coverage even with
|
|
selected fields.
|
|
Conflicting base architectures retain both values, mark object/report/target
|
|
coverage partial and annotate the affected kernels. CUBIN flags establish a base
|
|
architecture: `base-only` explicitly leaves feature-profile agreement unknown,
|
|
including `a` variants. A standalone declaration is `single-source`, and
|
|
unexamined payloads remain `unexamined`. An exact AMDGPU target is normalized at
|
|
its note owner for comparison with a Clang bundle declaration; raw values remain
|
|
intact. Unresolved feature comparisons stay `unknown`.
|
|
|
|
`cuda_target_header` retains the OS ABI, normalized raw `e_flags` and exact
|
|
header location. CUDA OS ABI `0x33` and the observed `0x41` flags layout use
|
|
different architecture fields; they are decoded at one ABI-aware owner.
|
|
Unrecognized layouts keep the header and an unknown target instead of
|
|
inventing an SM label. Header provenance is validated against its CUBIN object.
|
|
|
|
Target filters select inventory declarations. An unselected payload's inner
|
|
target remains unexamined; an empty filtered result does not establish that
|
|
no enclosed code declares that target. Discovering every inner declaration
|
|
requires decoding those payloads.
|
|
|
|
HIP IDs with one or two separators before the architecture retain the declared
|
|
target. If a recognized AMDGPU bundle ID does not expose a target, the same
|
|
bounded note-discovery owner used for standalone AMDGPU files establishes it
|
|
before filtering. Those directory/note reads share the inspection work budget;
|
|
successive queries can select the target returned by inventory.
|
|
|
|
Decode selected targets and return a kernel page in the same call:
|
|
|
|
```json
|
|
{
|
|
"path": "/artifacts/library.so",
|
|
"analysis": "kernels",
|
|
"targets": ["sm_100"],
|
|
"view": {
|
|
"collection": "kernels",
|
|
"names": ["kernel_name"],
|
|
"fields": [
|
|
"name",
|
|
"parameter_count",
|
|
"parameter_bytes",
|
|
"parameters",
|
|
"registers",
|
|
"shared_bytes"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Only selected payloads are decoded. Other inventory entries remain present with
|
|
`not-selected` states, and overall payload coverage remains partial. An empty
|
|
kernel page proves no matching retained fact; it does not establish that an
|
|
unexamined payload contains no kernel. Missing fields remain null.
|
|
|
|
Kernel representations have different meanings:
|
|
|
|
- PTX reports parameter declarations and virtual registers. Shared bytes cover
|
|
supported static declarations inside that entry; they do not establish module
|
|
shared memory, dynamic allocation or physical device resources.
|
|
Scalar register declarations count each bare or percent-prefixed name and
|
|
each parameterized range. Unsupported declaration forms or overflowing totals
|
|
retain an unknown count and partial decoding coverage. Unsupported parameter
|
|
layouts and unknown shared-memory declarations likewise retain their known
|
|
facts, explicit limitations and partial coverage through retained pages.
|
|
- CUBIN identifies CUDA entry symbols and reads numeric `nv.info` records and
|
|
native section declarations. Global register declarations also cover compiler
|
|
versions that leave the older text-section register field empty.
|
|
- AMDGPU reads v3+ MessagePack notes. Argument counts include hidden ABI arguments
|
|
when present; SGPR/VGPR counts and fixed group/private segment sizes retain
|
|
their declared meanings. Legacy YAML metadata remains unsupported.
|
|
|
|
Each selected PTX payload becomes a retained UTF-8 text artifact with a SHA-256,
|
|
byte length and source coordinates. It is omitted from compact replies. Read it
|
|
with `inspect_analysis_view` and the parent Evidence ID returned by the compact
|
|
receipt:
|
|
|
|
```json
|
|
{
|
|
"source": { "kind": "retained-evidence", "evidence_id": "ev_..." },
|
|
"view": {
|
|
"kind": "gpu-code-objects",
|
|
"collection": "ptx",
|
|
"object_id": "...",
|
|
"offset": 0,
|
|
"limit": 4096
|
|
}
|
|
}
|
|
```
|
|
|
|
Text offsets use UTF-16 code units and must fall on Unicode scalar boundaries.
|
|
Complete Evidence retains the selected text; `export_evidence_bundle` provides
|
|
its portable source record. Historical pages never reopen the input file.
|
|
|
|
A location with `container_id: null` uses original file offsets. Other locations
|
|
use that inventoried object's decoded byte coordinates. Follow its parent,
|
|
encoded location and digest to trace decompressed metadata back to a native
|
|
section and the original file. Decoded offsets are never presented as physical
|
|
file offsets.
|
|
|
|
The CLI uses the same service and contracts:
|
|
|
|
```sh
|
|
rea inspect-gpu-code-objects /artifacts/library.so --analysis kernels \
|
|
--targets '["sm_100"]' --detail summary \
|
|
--view '{"collection":"kernels","names":["kernel_name"]}' \
|
|
--evidence_output /analysis/library-gpu.evidence.json --json
|
|
```
|
|
|
|
A full-file SHA-256 always streams every byte. Inventory then reads bounded
|
|
native directories and bundle headers; CCOB requires decompression to discover
|
|
its inner directory. Kernel analysis reads selected payloads. `bytes_read`
|
|
includes hashing and subsequent descriptor reads, so this is not a header-only
|
|
hashing workflow.
|
|
|
|
CUDA raw LZ4 blocks and Zstd, and CCOB zlib/Zstd are supported. Unknown versions
|
|
or codecs retain declarations with explicit limitations. Lengths are checked
|
|
before decoding, and CCOB's truncated MD5 is verified against decoded bytes.
|
|
Resource limits are one active inspection, 128 MiB per input/output buffer,
|
|
512 MiB of payload input, decoded output and AMD note-read work per inspection,
|
|
and 16 MiB retained facts including selected PTX. Payload work is reserved before
|
|
reading or allocating; a capacity refusal does not reread an aliased payload.
|
|
Native tables and decoded section names each have a 16 MiB structural budget;
|
|
AMDGPU ELF note discovery admits at most 8 MiB of source note bytes, with
|
|
bounded depth and container/string allocations. Standalone AMD targets are read
|
|
from those notes before target selection; selected kernel analysis reuses the
|
|
same parsed declarations. Pages have a
|
|
1 MiB response budget. Resource refusals and interrupted observations preserve
|
|
known facts and explicit uncertainty.
|
|
|
|
CUDA ELF parsing additionally shares a 262,144 record/symbol visit limit,
|
|
128 MiB of cumulative metadata section reads, and a 16 MiB serialized-size
|
|
accounting budget for temporary index facts. These limits are checked before
|
|
index growth; they are not claims about JavaScript heap size. Equivalent scoped
|
|
metadata byte ranges and repeated equal register declarations are coalesced;
|
|
conflicting values remain unknown. Parameter sections are parsed once per ELF.
|
|
|
|
Missing CUBIN symbol tables or unresolved section names produce `partial`
|
|
object, report and target coverage even when some kernel facts survive. AMD note
|
|
failures preserve earlier successfully parsed declarations and the original
|
|
failure reason. Standalone PTX recognition tries a small header first, then
|
|
continues within the existing 16 MiB text budget when leading comments or
|
|
whitespace obscure its directives; admitted full-file probe bytes are reused.
|