From: Julian Seward Date: Wed, 28 Feb 2007 13:27:37 +0000 (+0000) Subject: Add a regression test for unwind handling of DW_CFA_def_cfa_expression. X-Git-Tag: svn/VALGRIND_3_3_0~338 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9218c18f456fdcea4b541738b3de0527201498f8;p=thirdparty%2Fvalgrind.git Add a regression test for unwind handling of DW_CFA_def_cfa_expression. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6628 --- diff --git a/memcheck/tests/amd64/Makefile.am b/memcheck/tests/amd64/Makefile.am index b11dfc34da..2a5b5bc61e 100644 --- a/memcheck/tests/amd64/Makefile.am +++ b/memcheck/tests/amd64/Makefile.am @@ -11,13 +11,14 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ bt_everything.stderr.exp bt_everything.stdout.exp \ bt_everything.vgtest \ bug132146.vgtest bug132146.stderr.exp bug132146.stdout.exp \ + defcfaexpr.vgtest defcfaexpr.stderr.exp \ fxsave-amd64.vgtest fxsave-amd64.stdout.exp fxsave-amd64.stderr.exp \ more_x87_fp.stderr.exp more_x87_fp.stdout.exp more_x87_fp.vgtest \ sse_memory.stderr.exp sse_memory.stdout.exp sse_memory.vgtest \ xor-undef-amd64.stderr.exp xor-undef-amd64.stdout.exp \ xor-undef-amd64.vgtest -check_PROGRAMS = bt_everything bug132146 fxsave-amd64 \ +check_PROGRAMS = bt_everything bug132146 defcfaexpr fxsave-amd64 \ more_x87_fp sse_memory xor-undef-amd64 AM_CPPFLAGS = -I$(top_srcdir)/include @@ -28,3 +29,5 @@ AM_CXXFLAGS = $(AM_CFLAGS) more_x87_fp_CFLAGS = $(AM_CFLAGS) -O -ffast-math -mfpmath=387 \ -mfancy-math-387 more_x87_fp_LDADD = -lm + +defcfaexpr_SOURCES = defcfaexpr.S diff --git a/memcheck/tests/amd64/defcfaexpr.S b/memcheck/tests/amd64/defcfaexpr.S new file mode 100644 index 0000000000..23306b25e1 --- /dev/null +++ b/memcheck/tests/amd64/defcfaexpr.S @@ -0,0 +1,186 @@ + +/* This is really horrible. It checks that the + stack unwinder understands DW_CFA_def_cfa_expression. It is + the result of compiling this: + +void bbb ( long x ) +{ + __asm__ __volatile__( + "cmp %0,%0\n\t" + "jz .Lxyzzy\n" + ".Lxyzzy:\n\t" + : : "r"(x) : "cc" + ); +} + +void aaa ( long x ) { + bbb(x); +} + +int main ( void ) +{ + long *p = malloc(8); + aaa( *p ); + return 0; +} + +and bracketing the cmp/jz insns with a move down/up by 256 of %rsp. +The .jz causes memcheck to complain, hence unwind the stack, but +that cannot be successfully done unless the return address can +be found. Hence the handwritten CFI below uses +DW_CFA_def_cfa_expression to make that possible. + +The CFI below isn't really right in that aaa appears twice +in the backtrace + +==12868== Conditional jump or move depends on uninitialised value(s) +==12868== at 0x400512: bbb (in /home/sewardj/VgTRUNK/trunk/mad0) +==12868== by 0x400520: aaa (in /home/sewardj/VgTRUNK/trunk/mad0) +==12868== by 0x400520: aaa (in /home/sewardj/VgTRUNK/trunk/mad0) +==12868== by 0x400538: main (in /home/sewardj/VgTRUNK/trunk/mad0) + +but GDB behaves the same, so I'm not too concerned - indicates +the problem is with the handwritten CFI and not with +V's interpretation of it. +*/ + + + .file "bad0.c" + .text + + +.globl bbb + .type bbb, @function +bbb: +.LFB2: +.Lbbb1: + subq $256,%rsp +.Lbbb2: + cmp %rdi,%rdi + jz .Lxyzzy +.Lxyzzy: + addq $256,%rsp +.Lbbb3: + ret +.Lbbb4: +.LFE2: + .size bbb, .-bbb + + + +.globl aaa + .type aaa, @function +aaa: +.LFB3: + call bbb + rep ; ret +.LFE3: + .size aaa, .-aaa +.globl main + .type main, @function +main: +.LFB4: + subq $8, %rsp +.LCFI0: + movl $8, %edi + call malloc + movq (%rax), %rdi + call aaa + movl $0, %eax + addq $8, %rsp + ret +.LFE4: + .size main, .-main + .section .eh_frame,"a",@progbits +.Lframe1: + .long .LECIE1-.LSCIE1 +.LSCIE1: + .long 0x0 + .byte 0x1 + .string "zR" + .uleb128 0x1 + .sleb128 -8 + .byte 0x10 + .uleb128 0x1 + .byte 0x3 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .byte 0x90 + .uleb128 0x1 + .align 8 +.LECIE1: + +/* start of the FDE for bbb */ +.LSFDE1: + .long .LEFDE1-.LASFDE1 /* length of FDE */ +.LASFDE1: + .long .LASFDE1-.Lframe1 /* CIE pointer */ + .long .LFB2 /* & bbb */ + .long .LFE2-.LFB2 /* sizeof(bbb) */ + .uleb128 0 /* augmentation length */ + .byte 0x40 + .Lbbb2 - .Lbbb1 /* _advance_loc to .Lbbb2 */ + + /* For the section in between .Lbbb2 and .Lbbb3, set the + CFA to be %rsp+256, and set the return address (dwarf r16) + to be *(CFA+0). */ + .byte 0x0f /* _def_cfa_expression */ + .uleb128 .Lexpr1e-.Lexpr1s /* length of expression */ +.Lexpr1s: + .byte 0x77 /* DW_OP_breg7 == %rsp + sleb128(0) */ + .sleb128 0 + .byte 0x40 /* DW_OP_lit16 */ + .byte 0x40 /* DW_OP_lit16 */ + .byte 0x1e /* DW_OP_mul */ + .byte 0x22 /* DW_OP_plus */ +.Lexpr1e: + .byte 0x90 /* _cfa_offset: r16 = *(cfa+0) */ + .uleb128 0 + + .byte 0x40 + .Lbbb3 - .Lbbb2 /* _advance_loc to .Lbbb3 */ + + /* For the section .Lbbb3 to .Lbbb4, should set CFA back to + something sensible. This tries to do it but still causes + GDB to show an extraneous aaa frame on the stack. Oh well. */ + /* Now set CFA back to %rsp+0 */ + .byte 0x0f /* _def_cfa_expression */ + .uleb128 .Lexpr2e-.Lexpr2s /* length of expression */ +.Lexpr2s: + .byte 0x77 /* DW_OP_breg7 == %rsp + sleb128(0) */ + .sleb128 0 + .byte 0x30 /* DW_OP_lit0 */ + .byte 0x1c /* DW_OP_minus */ +.Lexpr2e: + .byte 0x90 /* _cfa_offset: r16 = *(cfa+0) */ + .uleb128 0 + + .byte 0x40 + .Lbbb4 - .Lbbb3 /* _advance_loc to .Lbbb4 */ + .uleb128 0x0 /* ??? */ + .align 8 +.LEFDE1: +/* end of the FDE for bbb */ + +.LSFDE3: + .long .LEFDE3-.LASFDE3 +.LASFDE3: + .long .LASFDE3-.Lframe1 + .long .LFB3 + .long .LFE3-.LFB3 + .uleb128 0x0 + .align 8 +.LEFDE3: +.LSFDE5: + .long .LEFDE5-.LASFDE5 +.LASFDE5: + .long .LASFDE5-.Lframe1 + .long .LFB4 + .long .LFE4-.LFB4 + .uleb128 0x0 + .byte 0x4 + .long .LCFI0-.LFB4 + .byte 0xe + .uleb128 0x10 + .align 8 +.LEFDE5: + .ident "GCC: (GNU) 4.1.2 20061115 (prerelease) (SUSE Linux)" + .section .note.GNU-stack,"",@progbits diff --git a/memcheck/tests/amd64/defcfaexpr.stderr.exp b/memcheck/tests/amd64/defcfaexpr.stderr.exp new file mode 100644 index 0000000000..7a24ccd1dc --- /dev/null +++ b/memcheck/tests/amd64/defcfaexpr.stderr.exp @@ -0,0 +1,5 @@ +Conditional jump or move depends on uninitialised value(s) + at 0x........: bbb (in ...) + by 0x........: aaa (in ...) + by 0x........: aaa (in ...) + by 0x........: main (in ...) diff --git a/memcheck/tests/amd64/defcfaexpr.vgtest b/memcheck/tests/amd64/defcfaexpr.vgtest new file mode 100644 index 0000000000..1e1008cc8a --- /dev/null +++ b/memcheck/tests/amd64/defcfaexpr.vgtest @@ -0,0 +1,2 @@ +prog: defcfaexpr +vgopts: -q