Skip to content
LuaJIT Raw-Bytecode Decompiler (LJD)
Python Lua
Branch: master
Clone or download
Pull request Compare This branch is even with colpocleisis:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
ljd Fix for undefined local variables in certain cases Jul 7, 2018
test Fix for unary expressions that leave the target variable unchanged Jun 19, 2018
LICENSE Fix the name in the LICENSE file Dec 29, 2013 Minor unwarping and typo fixes. Revised Added compiled tests. May 19, 2018 Use the python3 executable in the current PATH Aug 22, 2018

LuaJIT Raw-Bytecode Decompiler (LJD)

The original name was ljwthgnd, as in LuaJIT 'What The Hell is Going On' Decompiler; named under the LuaJIT C sources variable-naming convention.

WARNING! This code is not finished or tested! There is not even the slightest warranty that the resulting code is even close to the original. Use the decompiled code at your own risk.

SECOND WARNING! This is all a huge prototype. The "release" version should be written in Lua itself, because it's cool to decompile the decompiler — a great test too!


Python 3.0+ from

How To Use:

Typical usage (no version configuration list, all files in a directory):

python ./ljd/ --recursive ./<input directory> --dir_out ./<output directory> --catch_asserts


"-f", "--file" : Single file input target. Not to be used with "-r"

"-o", "--output" : Single file output destination. Not to be used with "-r"

"-r", "--recursive" : Directory in which to recurse and process all files. Not to be used with "-f"

"-d", "--dir_out" : Directory to output processed files during recursion. Not to be used with "-f"

"-j", "--jit_version" : Global override of LuaJIT version, ignores -j, currently supports 2.1b3, 2.0

"-v", "--version_config_list" : 'Profiles' that hardcode LuaJIT versions per file,

"-c", "--catch_asserts" : Prevent most integrity asserts from canceling decompilation

"-l", "--enable_logging" : Output a log of exceptions and information during decompilation


#ljd at freenode


There is a lot of work to do. In order of priority:

  1. Logical subexpressions in while statements:

    	while x < (xi and 2 or 3) do
    		print ("Hello crazy world!")

    Logical subexpressions (the subexpressions used as operands in ariphmetic or comparison operations inside other expressions) are currently supported only for ifs. To support them for whiles and repeat-untils, the expression unwarping logic should be moved to the very beginning. This won't work without all the fixes in the loop unwarping logic, so we need to split that and move the fixes before expressions, before loops, before ifs. That's not that easy...

  2. AST Mutations:

    1. Use the line information (or common sense if there is no line information) to squash similar expressions into single expressions.
  3. Formatting improvements (partially-implemented):

    1. Use the line information (or common sense) to preserve empty lines and break long statements like in the original code.

      This is mostly done, but only in the "common sense" part.

  4. Features not supported:

    1. GOTO statement (from Lua 5.2). All the required functionality is now in place, but that's a rather low-priority task right now.

    2. Local sub-blocks:

    These subblocks are not directly reflected in the bytecode.
    The only way to guess their presence is to watch local variable scopes.
    Simple enough in case of non-stripped bytecode, but a bit
    harder otherwise.
You can’t perform that action at this time.