Description
I'm currently in the process of implementing a luau debugger and have ran into one small issue
If you are running in step mode and breaking at every single instruction (The user is wanting to step forward for example), Once a LOP_CALL instruction is reached whenever you next call lua_getinfo
a few odd conditions and assumptions are broken
When you call lua_getinfo
and inside of the auxgetinfo
call during the caculation of the current line
case 'l':
{
if (ci)
{
/*=========>*/ ar->currentline = isLua(ci) ? currentline(L, ci) : -1;
}
else
{
ar->currentline = f->isC ? -1 : f->l.p->linedefined;
}
break;
}
currentline(L, ci)
is called. This is the call that ensures
current line is defined as follows and currentpc
is the reason for the ensure
return luaG_getline(ci_func(ci)->l.p, currentpc(L, ci));
The main issue is that currentpc
returns -1 which immediately hits an ensure on the luaG_getline
call
There's not much documentation on the very very internals of the lua/Luau engine but after doing some investigation my best guess as to what's happening is that CallInfo->savedpc (Which im guessing stands for procedure call) is exactly equal to the stacks current closure instruction pointer
the currentcp
line uses pcRel
#define pcRel(pc, p) ((pc) ? cast_to(int, (pc) - (p)->code) - 1 : 0)
Which just subtracts the CallInfo's Procedure call from the targeted closure (In this case we are targeting level 0 so the top most closure) code pointer and subtracts 1 (Not sure why exactly but I'm guessing its due to things starting at 1) . And because this is Immediately after a
LOP_CALL the current closures code start and the call info's pc are equal.
This -1 value then hits the first ENSURE block of luaG_getline, And also returns junk data
I'm not entirely sure the best way to fix this but my suggestion would be to change
int luaG_getline(Proto* p, int pc)
{
LUAU_ASSERT(pc >= 0 && pc < p->sizecode);
if (!p->lineinfo)
return 0;
return p->abslineinfo[pc >> p->linegaplog2] + p->lineinfo[pc];
}
to
int luaG_getline(Proto* p, int pc)
{
LUAU_ASSERT(pc >= -1 && pc < p->sizecode);
if (pc == -1)
return 0;
if (!p->lineinfo)
return 0;
return p->abslineinfo[pc >> p->linegaplog2] + p->lineinfo[pc];
}
It's not the best solution but it's the one with the least changes needed