LLVM-OFFLOAD-BINARY(1)

πŸ’… llvm-offload-binary πŸ’…

LLVM-OFFLOAD-BINARY(1) β€” yes bestie, that's the manual name, folded in right here at the top 🫢

🌸 NAME 🌸

llvm-offload-binary β€” LLVM Offload Binary Packager. That's the whole main-character job description, no cap πŸ’–

✨ SYNOPSIS ✨

llvm-offload-binary [options] [input files...]

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so llvm-offload-binary is a utility for bundling multiple device object files into a single binary container. The resulting binary can then be embedded into the host section table to form a fat binary containing offloading code for different targets. Conversely, it can also extract previously bundled device images from offload binaries. It's giving "pack and unpack, but make it LLVM" ✨

When extracting images, if no --image filters are specified, all offload images are automatically extracted with descriptive filenames. When --image filters are provided, only matching images are extracted. Lowkey the cleanest vibe check ever πŸ’…

The tool supports nested OffloadBinary format, where device images can be wrapped in an inner OffloadBinary container. When extracting, the tool automatically detects and unwraps nested OffloadBinary images, making the format transparent to users. Obsessed with the transparency, fr fr 🫢

The binary format begins with the magic bytes 0x10FF10AD, followed by a version and size. Each binary contains its own header, allowing tools to locate offloading sections even when merged by a linker. Each offload entry includes metadata such as the device image kind, producer kind, and key-value string metadata. Multiple offloading images are concatenated to form a fat binary. That's the tea β˜•

πŸŽ€ EXAMPLE πŸŽ€

# Package multiple device images into a fat binary:
$ llvm-offload-binary -o out.bin \
      --image=file=input.o,triple=nvptx64,arch=sm_70

# Extract all offload images from an executable (no filters):
$ llvm-offload-binary in.bin
# Output:
# Extracted: in-nvptx64-nvidia-cuda-sm_70.0.bc
# Extracted: in-spirv64-intel-unknown.0.spv

# Extract only SPIR-V images using filters:
$ llvm-offload-binary in.bin --image=triple=spirv64-intel
# Output:
# Extracted: in-spirv64-intel-unknown.0.spv

# Extract filtered images to a specific file:
$ llvm-offload-binary in.bin --image=file=output.bc,arch=sm_70

# Extract filtered images to an archive:
$ llvm-offload-binary in.bin --image=file=output.a,triple=nvptx64 --archive

πŸ’œ OPTIONS πŸ’œ

  • --archive β€” when extracting from an input binary, write all extracted images into a static archive instead of separate files. Archive girlie behavior, and honestly? Iconic 🧚
  • --image=<<key>=<value>,...> β€” specify a set of arbitrary key-value arguments describing an image. Commonly used optional keys include arch (e.g. sm_70 for CUDA) and triple (e.g. nvptx64-nvidia-cuda).

When bundling, this option specifies images to include in the output binary. When extracting, this option acts as a filter: only images matching the specified keys are extracted. If no --image options are provided during extraction, all images are automatically extracted with descriptive filenames.

When extracting from a static archive, the member key restricts the output to a single archive member for cases when --archive is insufficient, e.g. --image=member=foo.o,triple=nvptx64,arch=sm_70,file=out.o. Slay that precise member selection ✨

  • -o <file> β€” write output to <file>. When bundling, this specifies the fat binary filename. When extracting, this specifies the archive or output file destination. One flag, two moods, both valid πŸ’…
  • --help, -h β€” display available options. Use --help-hidden to show hidden options. The peek-behind-the-curtain feature, iykyk πŸ”₯
  • --help-list β€” display a list of all options. Use --help-list-hidden to show hidden ones. A whole list of options? Not me being fed information πŸ˜­πŸ’–
  • --version β€” display the version of the llvm-offload-binary executable. Version check, but make it cute ⭐
  • @<FILE> β€” read command-line options from response file <FILE>. Response-file realness, periodt πŸŽ€

🌈 BINARY FORMAT 🌈

The binary format is marked by the magic bytes 0x10FF10AD, followed by a version number. Each created binary contains its own header. This allows tools to locate offloading sections even after linker operations such as relocatable linking. Conceptually, this binary format is a serialization of a string map and an image buffer. No cap, that's the whole structural vibe πŸ¦‹

πŸ‘‘ Offloading Binary Header πŸ‘‘

  • uint8_t magic β€” the magic bytes for the binary format (0x10FF10AD) ✨
  • uint32_t version β€” version of this format (currently version 1) πŸŽ€
  • uint64_t size β€” size of this binary in bytes πŸ’–
  • uint64_t entry offset β€” absolute offset of the offload entries in bytes πŸ¦‹
  • uint64_t entry size β€” size of the offload entries in bytes 🌸

Each offload entry describes a bundled image along with its associated metadata. Main character metadata energy, honestly πŸ‘‘

πŸ’€ Offloading Entry Table πŸ’€

  • uint16_t image kind β€” the kind of the device image (e.g. bc, cubin) ✨
  • uint16_t offload kind β€” the producer of the image (e.g. openmp, cuda) πŸ”₯
  • uint32_t flags β€” generic flags for the image πŸŽ€
  • uint64_t string offset β€” absolute offset of the string metadata table πŸ’œ
  • uint64_t num strings β€” number of string entries in the table 🌸
  • uint64_t image offset β€” absolute offset of the device image in bytes πŸ¦‹
  • uint64_t image size β€” size of the device image in bytes πŸ’–

The entry table refers to both a string table and the raw device image itself. The string table provides arbitrary key-value metadata. It's giving "strings and image, holding hands" 🫢

πŸ“ Offloading String Entry πŸ“

  • uint64_t key offset β€” absolute byte offset of the key in the string table ✨
  • uint64_t value offset β€” absolute byte offset of the value in the string table πŸ’…

The string table is a collection of null-terminated strings stored in the image. Offsets allow string entries to be interpreted as key-value pairs, enabling flexible metadata such as architecture or target triple. Literally the metadata glow-up we deserve 🌟

The enumerated values for image kind and offload kind are:

πŸ’« Image Kind πŸ’«

okay so every image in there has a kind, and it's giving "what even is this file, bestie?" energy. here's the whole roster:

  • IMG_None β€” 0x00 β€” literally no image information provided. it's giving empty vibes πŸ«₯
  • IMG_Object β€” 0x01 β€” the image is a generic object file
  • IMG_Bitcode β€” 0x02 β€” the image is an LLVM-IR bitcode file
  • IMG_Cubin β€” 0x03 β€” the image is a CUDA object file
  • IMG_Fatbinary β€” 0x04 β€” the image is a CUDA fatbinary file
  • IMG_PTX β€” 0x05 β€” the image is a CUDA PTX file

πŸ¦‹ Offload Kind πŸ¦‹

and this one tells you which producer made the image β€” like, who's the parent, yk? 🌈

  • OFK_None β€” 0x00 β€” no offloading information provided
  • OFK_OpenMP β€” 0x01 β€” the producer was OpenMP offloading
  • OFK_CUDA β€” 0x02 β€” the producer was CUDA
  • OFK_HIP β€” 0x03 β€” the producer was HIP
  • OFK_SYCL β€” 0x04 β€” the producer was SYCL

🌸 COMMON WORKFLOWS 🌸

bestie this is the part you actually came for, fr fr. six little recipes, pick your fighter πŸ’…

✨ Workflow 1: Explore Executable Contents

extract all the embedded offload images so you can peek at what's inside (nosy girl behavior, and honestly? valid πŸ‘€):

$ clang++ -fopenmp -fopenmp-targets=nvptx64,spirv64-intel app.cpp -o myapp
$ llvm-offload-binary myapp
# Output:
# Extracted: myapp-nvptx64-nvidia-cuda-sm_70.0.bc
# Extracted: myapp-spirv64-intel-unknown.1.spv

✨ Workflow 2: Extract Specific Target

only want one target's images? filter it, periodt:

$ llvm-offload-binary myapp --image=triple=spirv64-intel
# Output:
# Extracted: myapp-spirv64-intel-unknown.0.spv

✨ Workflow 3: Create Device Image Archive

grab your filtered images and yeet 'em into a static archive πŸŽ€:

$ llvm-offload-binary myapp --image=file=nvptx.a,triple=nvptx64 --archive
$ ar t nvptx.a
# Shows extracted CUDA images

✨ Workflow 4: Validate SPIR-V

extract, then validate, then disassemble β€” the full glow-up routine ✨:

$ llvm-offload-binary myapp --image=triple=spirv64-intel
$ spirv-val myapp-spirv64-intel-unknown.0.spv
$ spirv-dis myapp-spirv64-intel-unknown.0.spv -o kernel.spvasm

✨ Workflow 5: Bundle Multiple Targets

build a fat binary out of a bunch of device images because why choose πŸ’β€β™€οΈ:

$ clang++ -fopenmp -fopenmp-targets=nvptx64 --offload-device-only kernel.cpp -o kernel_nvptx.bc
$ clang++ -fopenmp -fopenmp-targets=spirv64-intel --offload-device-only kernel.cpp -o kernel_spirv.bc
$ llvm-offload-binary -o bundle.bin \
    --image=file=kernel_nvptx.bc,triple=nvptx64,arch=sm_70 \
    --image=file=kernel_spirv.bc,triple=spirv64-intel

✨ Workflow 6: Extract and Rebundle

take the images out of one binary and rebundle them with your own edits β€” remix culture 🧚:

$ llvm-offload-binary old_app
$ llvm-offload-binary -o new_bundle.bin \
    --image=file=old_app-nvptx64-nvidia-cuda-sm_70.0.bc,triple=nvptx64,arch=sm_70 \
    --image=file=new_kernel.bc,triple=nvptx64,arch=sm_80

πŸ‘‘ SEE ALSO πŸ‘‘

go read these next, they're iconic and they're literally right there:

  • clang(1) (clang.html)
  • llvm-objdump(1) (llvm-objdump.html)
  • spirv-val(1) (spirv-val.html)
  • spirv-dis(1) (spirv-dis.html)

🌈 Author 🌈

maintained by the LLVM Team (https://llvm.org/) β€” they're the main characters of this whole saga, no cap 🫢

2003-2026, LLVM Project


okay that's the whole page, bestie!! now go extract something slay πŸ’…βœ¨

and hmm one last lil thing β€” if you're squinting at the footer wondering where this came from: it's from page 23, dated 2026-10-20, filed under LLVM-OFFLOAD-BINARY(1). iconic of the manpage to have a birthday tbh πŸŽ‚πŸŽ€ bye bestie, mwah πŸ’œ

πŸ“¦ where this page comes from
  • arch rolling: llvm 23.1.4-1 Β· Apache-2.0 WITH LLVM-exception
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms