Created attachment 53126 [details] testcase Version: unspecified OS: Linux 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))) return esp_top_of_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. Reproducible: Always
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.