Skip to content

Commit fd3f061

Browse files
committed
gdb: unwind Lua stack top part
Prior to this patch the dump of Lua stack top (or bottom if we consider address growth direction) part was almost hardcoded except the number of its free slots. This leads to the following drawbacks of <lj-stack> command: * Red zone stack slots are collapsed like the way similar to free stack slots are except for the single difference: one needs to use <lj-tv> to inspect them regardless the fact they are used or not. * Top slot is hardcoded, that is confusing in case both base and top point to a single slot (e.g. function call with no arguments given). As a result of these changes red zone slots are dumped unconditionally on the top of the stack dump and top slot is unwound like the occupied slots are. The only artefact of the latter is the possible garbage printed as the top slot value. One can find the new example of <lj-stack> output below: | (gdb) lj-stack L | ----------- Red zone: 5 slots ----------- | 0x40047fc0 [ ] VALUE: nil | 0x40047fb8 [ ] VALUE: nil | 0x40047fb0 [ ] VALUE: nil | 0x40047fa8 [ ] VALUE: nil | 0x40047fa0 [ ] VALUE: nil | ----------- Stack: 168 slots ----------- | 0x40047f98 [ M] VALUE: nil | 0x40047ae0:0x40047f90 [ ] 151 slots: Free stack slots | 0x40047ad8 [ BT ] VALUE: number 2.3873123941281106e-313 | 0x40047ad0 [ ] FRAME: [PP] delta=1, fast function LuaJIT#27 | 0x40047ac8 [ ] FRAME: [L] delta=7, fast function LuaJIT#20 | 0x40047ac0 [ ] VALUE: Lua function @ 0x400c00b0, 2 upvalues, "@builtin/box/console.lua":243 | 0x40047ab8 [ ] VALUE: nil | 0x40047ab0 [ ] VALUE: Lua function @ 0x4014bb78, 0 upvalues, "return collectgarbage()":0 | 0x40047aa8 [ ] VALUE: nil | 0x40047aa0 [ ] VALUE: string "collectgarbage()" @ 0x40116660 | 0x40047a98 [ ] VALUE: table @ 0x400c0f88 (asize: 0, hmask: 0x1) | 0x40047a90 [ ] FRAME: [LP] delta=3, Lua function @ 0x4014fe30, 3 upvalues, "@builtin/box/console.lua":379 | 0x40047a88 [ ] VALUE: string "collectgarbage()" @ 0x40116660 | 0x40047a80 [ ] VALUE: table @ 0x400c0f88 (asize: 0, hmask: 0x1) | 0x40047a78 [ ] FRAME: [L] delta=3, Lua function @ 0x40075aa8, 1 upvalues, "@builtin/box/console.lua":701 | 0x40047a70 [ ] VALUE: string "/home/imun" @ 0x400ff388 | 0x40047a68 [ ] VALUE: table @ 0x400c0f88 (asize: 0, hmask: 0x1) | 0x40047a60 [ ] FRAME: [CP] delta=1, Lua function @ 0x4014d0c8, 5 upvalues, "@builtin/box/console.lua":746 | 0x40047a58 [S ] FRAME: dummy L Reviewed-by: Sergey Kaplun <skaplun@tarantool.org> Reviewed-by: Maxim Kokryashkin <m.kokryashkin@tarantool.org> Signed-off-by: Igor Munkin <imun@tarantool.org>
1 parent 196d4ca commit fd3f061

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

src/luajit-gdb.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -391,47 +391,49 @@ def dump_framelink(L, fr):
391391
f = dump_lj_tfunc(fr),
392392
)
393393

394-
def dump_stack_slot(L, slot, base=None, top=None):
394+
def dump_stack_slot(L, slot, base=None, top=None, eol='\n'):
395395
base = base or L['base']
396396
top = top or L['top']
397397

398-
return '{addr}{padding} [ {B}{T}{M}] VALUE: {value}\n'.format(
398+
return '{addr}{padding} [ {B}{T}{M}] VALUE: {value}{eol}'.format(
399399
addr = strx64(slot),
400400
padding = PADDING,
401401
B = 'B' if slot == base else ' ',
402402
T = 'T' if slot == top else ' ',
403403
M = 'M' if slot == mref('TValue *', L['maxstack']) else ' ',
404404
value = dump_tvalue(slot),
405+
eol = eol,
405406
)
406407

407408
def dump_stack(L, base=None, top=None):
408409
base = base or L['base']
409410
top = top or L['top']
411+
stack = mref('TValue *', L['stack'])
410412
maxstack = mref('TValue *', L['maxstack'])
411413
red = 5 + 2 * LJ_FR2
412414

413415
dump = '\n'.join([
414-
'{start}:{end} [ ] {n} slots: Red zone'.format(
415-
start = strx64(maxstack + 1),
416-
end = strx64(maxstack + red),
417-
n = red,
416+
'{padding} Red zone: {nredslots: >2} slots {padding}'.format(
417+
padding = '-' * len(PADDING),
418+
nredslots = red,
418419
),
419-
'{maxstack}{padding} [ M]'.format(
420-
maxstack = strx64(maxstack),
421-
padding = PADDING,
420+
*(
421+
dump_stack_slot(L, maxstack + offset, base, top, '')
422+
for offset in range(red, 0, -1)
422423
),
424+
'{padding} Stack: {nstackslots: >5} slots {padding}'.format(
425+
padding = '-' * len(PADDING),
426+
nstackslots = int((tou64(maxstack) - tou64(stack)) >> 3),
427+
),
428+
dump_stack_slot(L, maxstack, base, top, ''),
423429
'{start}:{end} [ ] {nfreeslots} slots: Free stack slots'.format(
424430
start = strx64(top + 1),
425431
end = strx64(maxstack - 1),
426432
nfreeslots = int((tou64(maxstack) - tou64(top) - 8) >> 3),
427433
),
428-
'{top}{padding} [ T ]'.format(
429-
top = strx64(top),
430-
padding = PADDING,
431-
)
432434
]) + '\n'
433435

434-
slot = top - 1
436+
slot = top
435437
framelink = base - (1 + LJ_FR2)
436438

437439
# XXX: Lua stack unwinding algorithm consists of the following steps:
@@ -447,7 +449,7 @@ def dump_stack(L, base=None, top=None):
447449
dump += dump_stack_slot(L, slot, base, top)
448450
slot -= 1
449451

450-
while framelink > mref('TValue *', L['stack']):
452+
while framelink > stack:
451453
assert slot == framelink + LJ_FR2, "Invalid slot during frame unwind"
452454
dump += dump_framelink(L, framelink)
453455
framelink = frame_prev(framelink + LJ_FR2) - LJ_FR2

0 commit comments

Comments
 (0)