Run and Verify Object Files with llvm-rtdyld-18
llvm-rtdyld-18 loads an LLVM object file the way a JIT would. From there you can inspect its functions, verify the linked memory image, or run a chosen entry point. Allow about 15 minutes if you already have an object file and the LLVM tools installed.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide targets the installed Ubuntu LLVM 18.1.3 build. The local manual describes llvm-rtdyld as an LLVM MC-JIT tool. It is a loader and test utility, not a replacement for a normal application linker or runtime.
Safety warning
--execute runs machine code from the input object. Do not use it on an untrusted object, and do not assume a harmless-looking symbol name makes the file safe. The inspection and verification examples below never call the loaded entry point.
1. Check the installed command
Confirm which executable will run and record its version:
$ command -v llvm-rtdyld-18
/usr/bin/llvm-rtdyld-18
$ llvm-rtdyld-18 --version
Ubuntu LLVM version 18.1.3
Optimized build.
Use the versioned command explicitly in scripts when the machine has more than one LLVM release. The available actions are --execute, --printline, --printdebugline, --printobjline and --verify. General help is available with --help; it does not load an input file.
2. Start with a real object file
The input is an object file that LLVM can recognise. For a quick local test, assemble a tiny function with the installed Clang:
$ clang-18 -c -o /tmp/rtdyld-demo.o demo.s
$ file /tmp/rtdyld-demo.o
/tmp/rtdyld-demo.o: ELF 64-bit LSB relocatable, x86-64, ...
Replace /tmp/rtdyld-demo.o with the path to your own object. Keep the source architecture and the RTDyld target aligned. A file that is text, a binary for the wrong target, or otherwise unsupported gets rejected before loading even starts.
Checkpoint
If the first error says the file was not recognised as a valid object file, stop and fix the input path or format. Adding more RTDyld options will not repair an invalid object.
3. List functions without executing them
Use --printline to load and link the object, then print line information for each function:
$ llvm-rtdyld-18 --printline /tmp/rtdyld-demo.o
Function: demo, Size = 0, Addr = 139140502913024
The address is allocated for that one invocation, so do not compare it as a stable identifier between runs. The useful result here is that the object loaded and the function name was found. On this installed build, a minimal assembly function can report a size of zero and still be perfectly loadable.
--printdebuglineloads, links and prints line information using the debug object.--printobjlineprints object line information without loading the object first. Choose this when you want an inspection that does not allocate the loaded image.
4. Verify the linked image
Run the verifier with an explicit target triple:
$ llvm-rtdyld-18 --verify --triple=x86_64-pc-linux-gnu /tmp/rtdyld-demo.o
$ printf '%s\n' "$?"
0
The manpage lists --triple as the target triple for the disassembler. On this LLVM 18 build it is also required by verify mode: leave it out and the command stops with -triple required when running in -verify mode, even when the object itself is perfectly valid.
Use the triple that matches the object and the environment you are testing. A zero status means this one verification run completed successfully. It does not prove an arbitrary program is safe to execute, or that its external runtime dependencies are present.
5. Execute one named entry point
Only do this with object code you trust and actually intend to run. Pass --execute, select the function with --entry, and put program arguments after --args:
$ llvm-rtdyld-18 --execute --entry=demo /tmp/rtdyld-demo.o --args alpha beta
loaded 'demo' at: 0x77dfe89ba000
$ printf '%s\n' "$?"
7
Here the function returns 7, so the tool exits with status 7. The loaded address is not stable and should never be parsed by a script. If you leave out --entry, this build looks for _main; an object containing only demo fails with no definition for '_main'.
Warning
Keep --args at the end of the command and treat everything after it as program arguments. Do not build this command from shell text you got from an untrusted source. Quote arguments containing spaces the normal shell way, and check the resulting status immediately if it drives a test or build step.
6. Add optional inputs deliberately
The RTDyld-specific options let you adjust a test without changing the object.
--dylib=<file>adds a library.--mcpu=<cpu-name>targets a specific CPU. Use--mcpu=helpto ask the installed build for its accepted CPU names.--preallocate=<ulong>allocates memory up front rather than on demand.--check=<file>supplies a file of RuntimeDyld verifier checks. The local manpage documents the option but does not define the check-file language, so do not invent a format. Use it only when you have the matching LLVM test or project documentation.--show-timesadds timings for RTDyld phases, useful when comparing repeated test runs, though the printed addresses and timing values are run-specific.
The --color option controls coloured output and defaults to autodetection.
7. Diagnose failures without changing state
Capture the exit status immediately after the RTDyld command:
llvm-rtdyld-18 --verify --triple=x86_64-pc-linux-gnu /path/to/input.o
status=$?
if [ "$status" -ne 0 ]; then
printf 'llvm-rtdyld verification failed with status %s\n' "$status" >&2
exit "$status"
fi
A missing entry point is an object-content problem, not a request for elevated privileges. Check a bad object path or unreadable file with ls -l and test -r. There is normally no reason to use sudo here: RTDyld reads the input and allocates memory in the current process. Running it as root only increases the consequence of executing unsafe code, and it does not make an incompatible object valid.
Recovery
When a test has changed state outside the tool, recover that state using the owning build or test system. The commands in this guide do not modify the input object or install anything. If you created a temporary object under /tmp, remove that disposable file only once you have finished inspecting it.
Done means
- Version confirmed:
llvm-rtdyld-18 --versionidentified the intended LLVM 18 installation. - Input checked: the object file was readable and matched the target being tested.
- Inspected without running:
--printlineor--printobjlineshowed the expected function without executing it. - Image verified:
--verifyused an explicit matching--tripleand returned status 0. - Execution controlled:
--executewas used only for trusted code, with an explicit entry point and its exit status checked.