Skip to content

Commit 475359b

Browse files
Buristanigormunkin
authored andcommitted
gdb: fix dump stack without function frame
Dummy frame is the "initial" coroutine state, when the framelink slot (i.e. L->base - (1 + LJ_FR2)) is the bottom slot of the guest stack (i.e. L->stack). Since coroutine stack unwinding is implemented via precondition loop, lj-stack doesn't dump the slots for the dummy frame, since the framelink points to the stack bottom. The output looks like the following: | 0x7fb512ac40:0x7fb512ac70 [ ] 7 slots: Red zone | 0x7fb512ac38 [ M] | 0x7fb512ab28:0x7fb512ac30 [ ] 34 slots: Free stack slots | 0x7fb512ab20 [ T ] | 0x7fb512ab08:0x7fb512ab10 [S ] FRAME: dummy L Python doesn't provide post-condition (do-while) syntax construction, that fits better for this case, so the unwinding of the topmost frame is just manually unrolled. As a result of the patch the output looks like the following: | 0x7fb512ac40:0x7fb512ac70 [ ] 7 slots: Red zone | 0x7fb512ac38 [ M] | 0x7fb512ab28:0x7fb512ac30 [ ] 34 slots: Free stack slots | 0x7fb512ab20 [ T ] | 0x7fb512ab18 [ ] VALUE: string 0 "/tmp/net_box.lua:6: err in ser" @ 0x7fb512ade8 | 0x7fb512ab10 [ B ] VALUE: table @ 0x7fb512ac80 (asize: 0, hmask: 0x0) | 0x7fb512ab00:0x7fb512ab08 [S ] FRAME: dummy L Reviewed-by: Igor Munkin <imun@tarantool.org> Reviewed-by: Sergey Ostanevich <sergos@tarantool.org> Signed-off-by: Igor Munkin <imun@tarantool.org>
1 parent 77c4a07 commit 475359b

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

src/luajit-gdb.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,31 @@ def dump_stack(L, base=None, top=None):
427427
slot = top - 1
428428
framelink = base - (1 + LJ_FR2)
429429

430+
# XXX: Lua stack unwinding algorithm consists of the following steps:
431+
# 1. dump all data slots in the (framelink, top) interval
432+
# 2. check whether there are remaining frames
433+
# 3. if there are no slots further, stop the unwinding loop
434+
# 4. otherwise, resolve the next framelink and top and go to (1)
435+
#
436+
# Postcondition (i.e. do-while) loops is the most fitting idiom for such
437+
# case, but Python doesn't provide such lexical construction. Hence step (1)
438+
# is unrolled for the topmost stack frame.
439+
while slot > framelink + LJ_FR2:
440+
dump += dump_stack_slot(L, slot, base, top)
441+
slot -= 1
442+
430443
while framelink > mref('TValue *', L['stack']):
431-
while slot > framelink + LJ_FR2:
432-
dump += dump_stack_slot(L, slot, base, top)
433-
slot -= 1
444+
assert slot == framelink + LJ_FR2, "Invalid slot during frame unwind"
434445
dump += dump_framelink(L, framelink)
435446
framelink = frame_prev(framelink + LJ_FR2) - LJ_FR2
436447
slot -= 1 + LJ_FR2
448+
while slot > framelink + LJ_FR2:
449+
dump += dump_stack_slot(L, slot, base, top)
450+
slot -= 1
451+
452+
assert slot == framelink + LJ_FR2, "Invalid slot after frame unwind"
453+
# Skip a nil slot for the last frame for 2-slot frames.
454+
slot -= LJ_FR2
437455

438456
dump += '{fr}{padding} [S ] FRAME: dummy L'.format(
439457
fr = slot,

0 commit comments

Comments
 (0)