Debugging LuaJIT

LuaJIT

# Debugging LuaJIT

LuaJIT is a rather complex application. There will undoubtedly be bugs lurking in there. You have been warned. :-)

If you came here looking for information on how to debug your application (and not LuaJIT itself) then please check out `jit.debug()` and the `-j debug` command line option.

But if you suspect a problem with LuaJIT itself, then try any of the following suggestions (in order).

## Is LuaJIT the Problem?

Try to run your application in several different ways:

- `luajit app.lua`
- `luajit -O1 app.lua`
- `luajit -O app.lua`
- `luajit -j off app.lua`
- `lua app.lua` (i.e. with standard Lua)

If the behaviour is the same as with standard Lua then ... well ... that's what LuaJIT is about: doing the same things, just faster. Even bugs fly faster. :-)

So this is most likely a bug in your application then. It may be easier to debug this with plain Lua — the remainder of this page is probably not helpful for you.

But if the behaviour is different, there is some likelihood that you caught a bug in LuaJIT. Oh dear ...

Ok, so don't just give up. Please read on and help the community by finding the bug. Thank you!

## Get the Latest Version

Number one on your list of things to check is the » Online Change History.

Please check if a newer version is available. Maybe the bug you have encountered has been fixed already. Always download the latest version and try it with your application before continuing.

## Reproduce the Bug

First try to make the bug reproducible. Try to isolate the module and the function the bug occurs in:

Either selectively turn off compilation for some modules with
`jit.off(true, true)`
until the bug disappears ...

And/or turn the whole JIT engine off and selectively compile functions with
`jit.compile(func)`
until it reappears.

If you have isolated the point where it happens, it's most helpful to reduce the affected Lua code to a short code snippet that still shows the problem. You may need to `print()` some variables until you can pinpoint the exact spot where it happens.

If you've got a reproducible and short test you can either send it directly to me or the mailing list (see the Contact Information) or you can try to debug this a bit further.

Well — if you are brave enough. :-)

## Look at the Generated Code

You may want to have a look at the output of `-j dumphints` first. Try to change things around until you can see which hint or which instruction is the cause of the bug. If you suspect an optimizer bug then have a look at the backend (`*.das[ch]`) and check how the hint is encoded.

Otherwise have a look at `-j dump` and see whether you can spot the problem around the affected instruction. It's helpful to have a good knowledge of assembler, though (sorry).

## Locate a Crash

If you get a crash, you should compile LuaJIT with debugging turned on:

Add `-g` to `CFLAGS` and `MYLDFLAGS` or whatever is needed to turn on debugging. For Windows you need both an executable and a DLL built with debugging.

Then start LuaJIT with your debugger. Run it with `-j dump=test.dump`.

Have a look at the backtrace and compare it with the generated dump file to find out exactly where it crashes. I'm sorry, but symbols or instructions for JIT compiled functions are not displayed in your debugger (this is really hard to solve).

## Turn on Assertions

Another way to debug LuaJIT is to turn on assertions. They can be turned on only for the JIT engine by adding `-DLUAJIT_ASSERT` to `JITCFLAGS` in `src/Makefile`. Then recompile with `make clean` and `make`.

Add these two lines to `src/luaconf.h` to turn on all assertions in the Lua core:
`#include <assert.h>`
`#define lua_assert(x) assert(x)`
This turns on the JIT engine assertions, too. Recompile and see whether any assertions trigger. Don't forget to turn off the (slow) assertions when you're done!

## Use Valgrind

A tremendously useful (and free) tool for runtime code analysis is » Valgrind. Regularly run your applications with `valgrind --memcheck` and your life will be better.

To run LuaJIT under Valgrind you must add `-DUSE_VALGRIND` to `MYCFLAGS` and recompile LuaJIT. You will get random errors if you don't! Valgrind 3.x or later is required. Earlier versions do not work well with newly allocated C stacks.

An executable built with this option runs fine without Valgrind and without a performance loss. But it needs the Valgrind header files for compilation (which is why it's not enabled by default).

It's helpful to compile LuaJIT with debugging turned on, too (see above).

If Valgrind spots many invalid memory accesses that involve memory allocation/free functions you've probably found a bug related to garbage collection. Some object reference must have gone astray.

Try to find out which object is disappearing. You can force eager garbage collection with repeated calls to `collectgarbage()` or by setting a very low threshold with `collectgarbage("setpause", 1)`.

## Don't Despair

If all of this doesn't help to find the bug, please send a summary of your findings to the mailing list. Describe as much of the circumstances you think are relevant.

Please don't send your whole application to me (without asking first) and especially not to the mailing list. Code snippets should preferrably be less than 50 lines and up to the point.

All bug reports are helpful, even if no immediate solution is available. Often enough someone else finds the same bug in a different setting and together with your bug report this may help to track it down.

Finally I have to say a BIG THANK YOU to everyone who has helped to make LuaJIT better by finding and fixing bugs!

Copyright © 2005-2008 Mike Pall · Contact