Home / Alt manpages / llvm-dis-20(1)

  • llvm-dis-20(1)
  • User command
  • linux

Turn LLVM Bitcode into Readable IR with llvm-dis-20

Someone hands you a .bc file and asks what is actually in it: llvm-dis-20 turns that opaque bitcode back into LLVM IR you can read. You will send the result to a chosen file or a pipeline, and learn to spot the one input mistake almost everyone makes at least once. The examples use llvm-dis-20 from Debian package llvm-20, version 20.1.8, installed on this machine.

Allow about ten minutes. You need a shell and an existing LLVM bitcode file, usually ending in .bc. The command only reads its input; it does not compile, optimise, execute or rewrite that source file. No elevated privileges are needed unless your input or output path is not readable or writable by your account.

1. Check the installed command

Confirm that the command on your path is the LLVM 20 build you expect:

$ command -v llvm-dis-20
/usr/bin/llvm-dis-20
$ llvm-dis-20 --version
Ubuntu LLVM version 20.1.8
  Optimized build.

The manpage calls the tool llvm-dis, while this package installs the versioned executable llvm-dis-20. Keep the suffix when several LLVM releases are installed side by side; drop it and you can end up disassembling with the wrong release without noticing. The available options in this installed version are -f, -help and -o.

Checkpoint

The version output should identify LLVM 20. If the command is missing, install or enable the package through your normal system administration process; this guide does not change package state.

2. Disassemble a bitcode file to the default path

Run the command with a bitcode path as its only argument:

$ llvm-dis-20 /path/to/module.bc

For a file input, llvm-dis-20 removes an existing .bc suffix and adds .ll. The example above therefore writes /path/to/module.ll. If the input has another name or no .bc suffix, the output name follows that input name with .ll appended.

That default is convenient right up until it is not: a generated file can silently replace an existing output with the same name. Use a new directory or an explicit, unused output path whenever the inspection needs to stay non-destructive.

$ test ! -e /path/to/module.ll && llvm-dis-20 /path/to/module.bc
$ test -s /path/to/module.ll
$ printf 'disassembly written: %s\n' /path/to/module.ll
disassembly written: /path/to/module.ll

Checkpoint

The final test returns status 0 when the output exists and is non-empty. It is an ordinary command sequence and does not require sudo.

3. Choose the output file explicitly

Use -o when the default name is inconvenient, or when the result belongs in a separate working directory:

$ llvm-dis-20 -o /tmp/module-inspection.ll /path/to/module.bc
$ test -s /tmp/module-inspection.ll
$ sed -n '1,12p' /tmp/module-inspection.ll

The output argument is a complete filename, not a directory. Use -o - to send the textual IR to standard output instead:

$ llvm-dis-20 -o - /path/to/module.bc | sed -n '1,12p'
; ModuleID = '/path/to/module.bc'

Safety boundary

Treat an output path as a state-changing choice. Before using a path in a script, decide whether replacement is acceptable. To recover from an unwanted output, remove only that generated .ll file or restore it from your own backup. The input bitcode is never modified by llvm-dis-20.

4. Disassemble standard input in a pipeline

Omit the filename, or pass -, to read bitcode from standard input. Standard output is then the default destination:

$ cat /path/to/module.bc | llvm-dis-20 - | sed -n '1,12p'
; ModuleID = '<stdin>'
source_filename = "/path/to/source.ll"

Handy when another tool produces the bitcode, or when you would rather not leave a temporary output file lying around. The <stdin> module label just describes how llvm-dis-20 received the bitcode; it does not mean the module is empty. The embedded source filename, when present, is metadata carried inside the bitcode itself.

For a script, prefer a form that preserves the exit status you actually care about:

$ llvm-dis-20 -o /tmp/module-inspection.ll < /path/to/module.bc
$ printf 'exit status: %s\n' "$?"
exit status: 0

5. Diagnose invalid input

llvm-dis-20 expects LLVM bitcode, not textual .ll IR, an object file or an arbitrary binary. Feed it the wrong format and it exits non-zero with an error on standard error:

$ llvm-dis-20 /path/to/not-bitcode.ll
llvm-dis-20: error: Invalid bitcode signature
$ printf 'exit status: %s\n' "$?"
exit status: 1

Do not trust a file extension as proof of its format. Check the producer and the file itself, then reach for llvm-as-20 when you need to assemble textual LLVM IR back into bitcode. If the file is truncated or came from an incompatible toolchain, keep the original and go investigate that producer rather than editing the input in place.

For a compact shell check, capture the status before running another command:

if llvm-dis-20 -o /tmp/module-inspection.ll /path/to/module.bc; then
    printf '%s\n' 'LLVM bitcode disassembled'
else
    status=$?
    printf 'llvm-dis-20 failed with status %s\n' "$status" >&2
    exit "$status"
fi

6. Keep the unusual option in context

The -f option enables binary output on terminals. You will not need it for ordinary bitcode disassembly, which produces textual LLVM IR. Avoid it unless you have a specific reason to write raw bitcode to the selected output device: sending binary data to a terminal can make the whole session unreadable. Use -help to display the installed command's short option summary:

$ llvm-dis-20 -help | sed -n '1,20p'

There is no service to restart and no persistent configuration to undo here. The only state introduced by these examples is an output file you deliberately chose to write.

Done means

  • Version confirmed. llvm-dis-20 --version reports the intended LLVM release.
  • Disassembly works. A known-good .bc file produces readable .ll output with exit status 0.
  • Output under control. You can direct output with -o or stream it with -o -.
  • Format understood. .ll input is textual IR, not bitcode this command accepts.
  • Path checked first. You have checked the output path before letting a script replace a file.