http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58486
Bug ID: 58486 Summary: insufficient CFI generated for call-saved VFP registers Product: gcc Version: 4.8.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: roland at gnu dot org Target: arm-linux-gnueabi I think this bug exists in trunk and in all past versions (seen in 4.6, at least), but I did the detailed testing on today's gcc-4_8-branch. The DWARF CFI generated to describe the save/restore of the call-saved VFP registers (d8-d15) is insufficient: it covers only half of each register. Consider this test case: __attribute__((noinline)) void foo(void) { struct { unsigned i[2]; } x = { 0xaaaaaaaa, 0xbbbbbbbb }; asm("vldr d8, %0; bkpt" :: "m" (x) : "d8"); } __attribute__((noinline)) void bar(void) { struct { unsigned i[2]; } x = { 0xffffffff, 0xeeeeeeee }; asm("vldr d8, %0" :: "m" (x) : "d8"); foo(); } int main(void) { bar(); return 0; } Compiled with: gcc -O2 -g -marm -mfpu=neon -mhard-float This gdb session demonstrates the failure: $ cat > foo.x r i reg s17 up i reg s17 k q $ gdb -x foo.x foo GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "arm-linux-gnueabihf". For bug reporting instructions, please see: <http://bugs.launchpad.net/gdb-linaro/>... Reading symbols from /home/user/mcgrathr/foo...done. Program received signal SIGTRAP, Trace/breakpoint trap. 0x0000838c in foo () at foo.c:3 3 asm("vldr d8, %0; bkpt" :: "m" (x) : "d8"); s17 -0.00572916633 (raw 0xbbbbbbbb) #1 0x000083c0 in bar () at foo.c:9 9 foo(); s17 -0.00572916633 (raw 0xbbbbbbbb) Kill the program being debugged? (y or n) [answered Y; input not from terminal] The second display of s17 should show 0xeeeeeeee, not 0xbbbbbbbb. Examination of the prologue code shows: @ for foo fstmfdd sp!, {d8} .cfi_def_cfa_offset 8 .cfi_offset 80, -8 @ for bar fstmfdd sp!, {d8} .cfi_def_cfa_offset 12 .cfi_offset 80, -12 The detailed analysis: The 64-bit VFP registers d0-d15 use the same space as the 32-bit VFP registers s0-s31. Hence, d8 is the same as the pair {s16,s17}. 80 is the DWARF register number for the 32-bit register s16. So this CFI describes restoring only s16 but not s17, i.e. only half of d8, while the code uses the full d8 register. The spec at: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf says 64-95 are obsolescent DWARF register numbers for 32-bit registers s0-s31. It recommends instead using the newly-assigned numbers 256-271 for the 64-bit registers d0-d15, and describing e.g. s16 as number 264 (d8) with DW_OP_piece to slice it in half (not relevant in CFI). With the GDB version I have on hand, register number 264 for d8 does work correctly. I'm not sure if there are older GDB versions that fail to recognize that number. To be compatible with an older debugger that doesn't know the 264+ range of DWARF register numbers, the other option is to emit CFI for d8 as the two registers s16 and s17, e.g. (for foo above): .cfi_offset 80, -8 .cfi_offset 81, -4 This also works with the GDB I have on hand.