Bug 256043

Summary: massif (update_stack_stats): Assertion 'stacks_szB >= -stack_szB_delta' failed.
Product: [Developer tools] valgrind Reporter: Christian Borntraeger <borntraeger>
Component: massifAssignee: Nicholas Nethercote <njn>
Status: REPORTED ---    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Debian unstable   
OS: Linux   
Latest Commit: Version Fixed In:
Attachments: testcase
possible fix for x86

Description Christian Borntraeger 2010-11-04 12:58:22 UTC
Created attachment 53126 [details]

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
Comment 1 Christian Borntraeger 2010-11-04 13:18:11 UTC
For completeness: Problem was originally reported by Stefan Wild during system test of valgrind for s390x.
Comment 2 Christian Borntraeger 2011-01-18 09:31:36 UTC
Created attachment 56155 [details]
possible fix for x86

Here is a possible fix for x86.It solves testcase problem.