It seems you’re on the right path (I didn’t try, I’m assuming this worked for you).
What’s missing for you is invoking somehow, it seems both (or I see now all tree) of these Julia 1.8 options from https://github.com/JuliaLang/julia/blob/master/NEWS.md
Command-line option changes
- New option --strip-metadata to remove docstrings, source location information, and local variable names when building a system image ([#42513]).
- New option --strip-ir to remove the compiler’s IR (intermediate representation) of source code when building a system image. The resulting image will only work if --compile=all is used, or if all needed code is precompiled ([#42925]).
To add them this seem to be the option you need: References · PackageCompiler
- sysimage_build_args::Cmd: A set of command line options that is used in the Julia process building the sysimage, for example -O1 --check-bounds=yes.
But even as is, might be ok, depending how paranoid you are.
Yes, I believe none of the (Julia) source code is directly accessible already (or at least not the full Julia source code), even if you don’t add any of those options. What you have is LLVM bitcode (aka “compiler’s IR (intermediate representation)”), unless you strip it, plus machine code and either could theoretically be decompiled. Just as C or C++ machine code can be decomplied, with tools (or manually), Julia or any other compiled language can.
There is no specific Julia decompiler available, that I know of. I think I would know of such a tool. However, it could be made later, at any point in time (and some programmers are good with reading machine code/assembly and “decompiling”/inferring manually). You don’t want to be leaving clues like “local variable names” around, that you can strip out. If you decompile, you would get some cryptic made-up variable names, at best, unless you have great expectations for artificial intelligence (it’s getting good at making up code, and converting between some programming languages, just like ok for translating natural languages, so while I’ve not seen from machine code, I wouldn’t rule out later).
I sould also want method (i.e. “function”) names to be stripped out too, but it’s NOT clear from the (Julia 1.8) docs above, that it’s done. It’s possible it’s done for non-exported methods, I wouldn’t rule out it’s done, but wouldn’t bet on it. You could run Unix
strings command on the sysimage, to see if you find something interesting like that. If those two (and the docstrings) are absent, I think you’re as obfuscated as you can expect possible (for any other language).
At least the (one) “entry-point”, i.e. the method
my_printand the module
MyModule, need to be not stripped, or your code wouldn’t work (from Python) because of
MyModule.my_print() so I find it likely that none of the module or method names are stripped, until proven otherwise. This would be unlike C/C++ where even
main shouldn’t need to be part of the executable. It’s plausible that non-exported methods names are not there, or at least could be stripped.
Even with the info there, I believe it’s not simple to get source code back, i.e. an equivalent, less readable one. The exact same would be impossible.
FYI: older discussion (one of my old comment from pre-discourse time, there as first answer under my full name, here I use my nickname):
It’s extremely easy to decompile. LLVM for a long time shipped with a CBackend that would convert LLVM into C.
I would really like to see that… decompiling Julia and getting C code. I wouldn’t rule out the possibility, since often Julia generates identical code (thus as optimized) code as C or C++. You would likely see some boilerplate code for allocation (should for C too, as there it’s explicit). Maybe a little less code, since Julia code isn’t littered with deallocation (“free” in C or “delete” in C++), so that code wouldn’t be as easily usable (GC code takes care of that).