edubart / nelua-lang

Minimal, efficient, statically-typed and meta-programmable systems programming language heavily inspired by Lua, which compiles to C and native code.
https://nelua.io
MIT License
1.99k stars 64 forks source link

we need nelua debugger(vscode) or tell us how to debug my app? #250

Closed acodervic closed 7 months ago

acodervic commented 7 months ago

we need nelua debugger(vscode) or tell us how to debug my app?

cattokomo commented 7 months ago

Is it a problem to debug Nelua with gdb/lldb?

edubart commented 7 months ago

Using --sanitize

For quick fixes, you can use --sanitize to debug most memory corruption errors and also have a backtrace of aborts and crashes.

For example, given the following test.nelua buggy program:

local a: [4]integer

local function foo(i: integer, x: integer)
  a[i] = i
end

foo(-1, 2)
print 'finished!'

Lets run it:

$ nelua test.nelua 
array index: position out of bounds
Aborted (SIGABRT)

It aborted because of out of bounds error, but where it happened? Let's debug with --sanitize:

$ nelua --sanitize test.nelua 
array index: position out of bounds
/home/bart/.cache/nelua/test.c:164:3: runtime error: execution reached an unreachable program point
    #0 0x5d6b38f8427c in nelua_abort /home/bart/.cache/nelua/test.c:164
    #1 0x5d6b38f843ee in nelua_panic_cstring /home/bart/.cache/nelua/test.c:171
    #2 0x5d6b38f84446 in nelua_assert_bounds_nlint64 /home/bart/.cache/nelua/test.c:175
    #3 0x5d6b38f84446 in test_foo /home/bart/.cache/nelua/test.c:180
    #4 0x5d6b38f847d4 in nelua_main /home/bart/.cache/nelua/test.c:190
    #5 0x5d6b38f8482e in main /home/bart/.cache/nelua/test.c:195
    #6 0x7e245aa43ccf  (/usr/lib/libc.so.6+0x25ccf) (BuildId: c0caa0b7709d3369ee575fcd7d7d0b0fc48733af)
    #7 0x7e245aa43d89 in __libc_start_main (/usr/lib/libc.so.6+0x25d89) (BuildId: c0caa0b7709d3369ee575fcd7d7d0b0fc48733af)
    #8 0x5d6b38f84184 in _start (/home/bart/.cache/nelua/test+0x2184) (BuildId: 9693d1c0f62bf813909741afbe9e72c06622061c)

From reading the backgtrace it happend inside #3 test_foo called from #4 nelua_main. test_foo is the name of the function (foo) prefixed with the name of the program (test). nelua_main is the function that executes all top scope code. But what were the values and exactly where in foo?

Using --debug

If we want more details we can combine --sanitize --debug, the --debug option will run through gdb and show even more details about backtrace:

$ nelua --sanitize --debug test.nelua 
Reading symbols from /home/bart/.cache/nelua/test...
Breakpoint 1 at 0x1060
Starting program: /home/bart/.cache/nelua/test 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
array index: position out of bounds

Breakpoint 1, 0x00007ffff76423e1 in abort () from /usr/lib/libc.so.6
#0  0x00007ffff76423e1 in abort () from /usr/lib/libc.so.6
#1  0x0000555555555225 in nelua_abort () at /home/bart/.cache/nelua/test.c:165
165   abort();
#2  0x0000555555555355 in nelua_panic_cstring (s=0x555555556060 "array index: position out of bounds") at /home/bart/.cache/nelua/test.c:171
171   nelua_abort();
#3  0x00005555555553ac in nelua_assert_bounds_nlint64 (len=4, index=-1) at /home/bart/.cache/nelua/test.c:175
175     nelua_panic_cstring("array index: position out of bounds");
#4  test_foo (i=-1, x=2) at /home/bart/.cache/nelua/test.c:180
180   test_a.v[nelua_assert_bounds_nlint64(i, 4)] = i;
#5  0x00005555555556ae in nelua_main (argc=1, argv=0x7fffffffda28) at /home/bart/.cache/nelua/test.c:190
190   test_foo(-1, 2);
#6  0x0000555555555708 in main (argc=1, argv=0x7fffffffda28) at /home/bart/.cache/nelua/test.c:195
195   return nelua_main(argc, argv);

Ok the values of i was -1 and x was 2 as seen in #4 test_foo (i=-1, x=2) at /home/bart/.cache/nelua/test.c:180.

If we want to dive further we can open the file /home/bart/.cache/nelua/test.c:180 and inspect the C code:

void play_foo(int64_t i, int64_t x) {
  play_a.v[nelua_assert_bounds_nlint64(i, 4)] = i;
}

Using gdb

You can go further and manually run gdb and debug on you own:

gdb /home/bart/.cache/nelua/test -ex run -ex bt
GNU gdb (GDB) 14.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /home/bart/.cache/nelua/test...
Starting program: /home/bart/.cache/nelua/test 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
array index: position out of bounds

Program received signal SIGABRT, Aborted.
0x00007ffff76ab32c in ?? () from /usr/lib/libc.so.6
#0  0x00007ffff76ab32c in ?? () from /usr/lib/libc.so.6
#1  0x00007ffff765a6c8 in raise () from /usr/lib/libc.so.6
#2  0x00007ffff76424b8 in abort () from /usr/lib/libc.so.6
#3  0x0000555555555225 in nelua_abort () at /home/bart/.cache/nelua/test.c:165
#4  0x0000555555555355 in nelua_panic_cstring (s=0x555555556060 "array index: position out of bounds") at /home/bart/.cache/nelua/test.c:171
#5  0x00005555555553ac in nelua_assert_bounds_nlint64 (len=4, index=-1) at /home/bart/.cache/nelua/test.c:175
#6  play_foo (i=-1, x=2) at /home/bart/.cache/nelua/test.c:180
#7  0x00005555555556ae in nelua_main (argc=1, argv=0x7fffffffda98) at /home/bart/.cache/nelua/test.c:190
#8  0x0000555555555708 in main (argc=1, argv=0x7fffffffda98) at /home/bart/.cache/nelua/test.c:195
(gdb) frame 6
#6  play_foo (i=-1, x=2) at /home/bart/.cache/nelua/test.c:180
180   play_a.v[nelua_assert_bounds_nlint64(i, 4)] = i;
(gdb) p i
$1 = -1
(gdb) p x
$2 = 2

About debugging C code instead of Nelua code

As you noticed, debugging happens at a lower level C code. You might complain that you need to debug in another language, but it's often common even in C/C++ to debug nasty bugs in assembly machine level code, so debugging in a another lower code is not novel, and typically you only need to do this in very nasty situations.

Most case having the name of the function you crashed and its input values is enough, so you may not really need to understand much of C. The same happens when debugging C programs with assembly x86 machine code, while most developers don't fully understand x86 machine code, they sometimes reason about assembly machine code when debugging.

It's possible to create compiler plugins that converts back C function names/variables names/source locations back to Nelua, but currently this is not planned or being worked on, because most of times debugging in C is enough.

About support of --sanitize and --gdb

Both options require some support in the environment. --debug you need to have gdb installed and ready. --sanitize your C compiler need to have sanitizer libraries available. This might not be the case in all platforms or compilers. Try using a combination of the options that works for you.