Created attachment 53126 [details]
The attached test case triggers the following assertion failure with
--tool=massif --stacks=yes :
Massif: ms_main.c:1926 (update_stack_stats): Assertion 'stacks_szB >= -stack_szB_delta' failed.
==13802== at 0x38006C05: report_and_quit (m_libcassert.c:191)
==13802== by 0x38006DD7: vgPlain_assert_fail (m_libcassert.c:265)
==13802== by 0x38000E24: update_stack_stats (ms_main.c:1926)
==13802== by 0x3800398A: die_mem_stack (ms_main.c:1949)
==13802== by 0x38019B53: vgPlain_unknown_SP_update (m_stacks.c:322)
==13802== by 0x4FFB8FE: ???
The problem happens, if m_sigframe creates a signal frame, but the user code returns with longjmp.
Turns out that there is a real problem in the code:
m_sigframe will increase the stack size by
sizeof(frame) + ALIGNMENT done by VG_ROUNDDN:
esp -= sizeof(*frame);
esp = VG_ROUNDDN(esp, 16);
frame = (struct rt_sigframe *)esp;
if (!extend(tst, esp, sizeof(*frame)))
but extend will announce only sizeof(frame):
static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
size + VG_STACK_REDZONE_SZB, tid );
longjump does restore the full SP change (which will be tracked by the SP change), leading to a miscounted stack size.
On s390x I was able to fix this, by something like
+ vg_assert((sizeof(*frame) & 7) == 0);
+ vg_assert((sp & 7) == 0);
sp -= sizeof(*frame);
- sp = VG_ROUNDDN(sp, 8);
Since the we know that the stack pointer is always 8 byte aligned.
Dont know if x86 might use the same method.
For completeness: Problem was originally reported by Stefan Wild during system test of valgrind for s390x.
Created attachment 56155 [details]
possible fix for x86
Here is a possible fix for x86.It solves testcase problem.