llvm-extract-20 pulls named functions out of a bulky LLVM bitcode module, so you get a small, focused test case instead of the whole program. You will save the result as readable LLVM IR and verify that the functions you did not want are actually gone. This guide uses Ubuntu's llvm-extract-20 20.1.8 package. Allow about 10 minutes if you already have a bitcode file and know the function name; no elevated privileges are needed.
First confirm which version will run, and make sure the input is genuinely an LLVM bitcode module rather than an object file or an executable:
llvm-extract-20 --version
llvm-dis-20 -o - /path/to/input.bc | sed -n '1,80p'
On the machine used for this guide, the first command reports Ubuntu LLVM version 20.1.8, and the second prints the start of the module as LLVM intermediate language. If llvm-dis-20 reports that the file is not bitcode, stop and locate the original .bc file or assemble an LLVM IR file with the matching LLVM toolchain.
Checkpoint: you have a readable .bc input and the exact function name, including any leading or unusual characters used in the IR.
Use --func to select a function and -S to request textual LLVM IR. Supplying -o keeps the result out of your terminal:
llvm-extract-20 \
--func=keep_me \
-S \
-o /tmp/keep-me.ll \
/path/to/input.bc
A successful run exits with status 0 and creates /tmp/keep-me.ll. Inspect it before feeding it to another tool:
sed -n '1,100p' /tmp/keep-me.ll
llvm-as-20 -o /tmp/keep-me.bc /tmp/keep-me.ll
The extracted module normally keeps the selected function plus whatever declarations or globals it needs. Unreachable globals, prototypes and unused types are removed. This is a reduction tool, not a compiler optimisation pass, so do not treat the output as a stand-in for the original program.
Repeat --func when your reduced test case needs several independent functions:
llvm-extract-20 \
--func=keep_me \
--func=also_keep \
-S \
-o /tmp/selected.ll \
/path/to/input.bc
Use --recursive when you want the selected function plus everything it calls. This can produce a much larger result than you expect, especially once the call graph reaches library wrappers or generated helpers. Check the size and contents rather than assuming recursive extraction stays minimal:
llvm-extract-20 --func=keep_me --recursive -S -o /tmp/call-tree.ll /path/to/input.bc
grep -E '^define |^declare ' /tmp/call-tree.ll
Search the textual output for definitions. The names you selected should be present, and anything you meant to discard should not be defined unless it is reachable through a recursive extraction or was explicitly selected:
grep -E '^define .*@(keep_me|also_keep)\b' /tmp/selected.ll
if grep -Eq '^define .*@discard_me\b' /tmp/selected.ll; then
echo 'unexpected function retained' >&2
exit 1
fi
llvm-as-20 -o /tmp/selected.bc /tmp/selected.ll
Reassembling the output is a useful structural check on its own: it catches malformed hand-edits and confirms the selected file is still acceptable LLVM IR. Keep the original bitcode, since extraction only produces a new output file and never alters the input.
Without -o, output goes to standard output. With -S, that output is readable text, which is convenient for a quick look:
llvm-extract-20 --func=keep_me -S /path/to/input.bc | sed -n '1,60p'
Warning: without -S, the default output is binary bitcode. Redirect it to a file or pipe it straight into another program; do not let raw bitcode scroll into a terminal. The -f option explicitly permits binary output to a terminal, but that is rarely useful and can leave your shell session hard to read afterwards.
If the input filename is omitted, or is -, the command reads bitcode from standard input:
llvm-extract-20 --func=keep_me -S - < /path/to/input.bc > /tmp/from-stdin.ll
A misspelled function name is an error, not an empty successful reduction. The command exits non-zero and reports a message such as program doesn't contain function named 'missing'!. Check the spelling with llvm-dis-20, then retry with the name shown after define:
llvm-dis-20 -o - /path/to/input.bc | grep -E '^define .*@'
Recovery: use a new output path while experimenting. Before replacing a useful file, compare the result and make a backup, because extraction has no built-in undo for a file you overwrite; a separate copy is your recovery plan:
cp -- /tmp/selected.ll /tmp/selected.ll.backup
llvm-extract-20 --func=keep_me -S -o /tmp/selected.ll.new /path/to/input.bc
mv -- /tmp/selected.ll.new /tmp/selected.ll
That last command renames the destination, so run it only after checking the new file. No command in this workflow needs sudo: elevated privileges here would only make a temporary-file mistake more damaging, not less.
llvm-extract-20 --version identified the tool you actually ran.llvm-as-20 accepted the extracted LLVM IR.