Hello everybody, We faced stack unwinding failures during working with libunwind for ARM. libunwind fails to unwind stack using UNW_ARM_METHOD_DWARF when there is ARM vfpv3/NEON register in stack, because libunwind cannot interpret ARM vfpv3/NEON registers(D0~D15) in .debug_frame section written in DWARF format.
These failure are observed while developing dotnet/coreclr using libunwind and clang-3.6. You can find more details at https://github.com/dotnet/coreclr/issues/6698 . For example, libunwind cannot interpret below .debug_frame section, because libunwind doesn't recognize "r264" in "DW_CFA_offset_extended: r264 at cfa-48" which means "d8 register is at cfa-48". (d8 is ARM vfpv3/NEON 64-bit registers which is alias of s16 and s17 registers.) 001644d8 0000002c 00163dc4 FDE cie=00163dc4 pc=0024da6c..0024dccc DW_CFA_advance_loc: 4 to 0024da70 DW_CFA_def_cfa_offset: 36 DW_CFA_offset: r14 at cfa-4 DW_CFA_offset: r11 at cfa-8 DW_CFA_offset: r10 at cfa-12 DW_CFA_offset: r9 at cfa-16 DW_CFA_offset: r8 at cfa-20 DW_CFA_offset: r7 at cfa-24 DW_CFA_offset: r6 at cfa-28 DW_CFA_offset: r5 at cfa-32 DW_CFA_offset: r4 at cfa-36 DW_CFA_advance_loc: 2 to 0024da72 DW_CFA_def_cfa: r7 ofs 24 DW_CFA_advance_loc: 6 to 0024da78 DW_CFA_offset_extended: r264 at cfa-48 DW_CFA_nop DW_CFA_nop ... omitted ... Above .debug_section is generated from below aseembly which is generated from clang 3.6. ... omitted ... .Ltmp2030: .cfi_offset r4, -36 .setfp r7, sp, #12 add r7, sp, #12 .Ltmp2031: .cfi_def_cfa r7, 24 .pad #4 sub sp, #4 .vsave {d8} vpush {d8} .Ltmp2032: .cfi_offset d8, -48 .pad #296 ... omitted ... ARM vpfv3/NEON registers are defined in "DWARF for the ARM architecture" and register number is from r256 to r287. http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf I'm going to post a patch for D0~D15 register support for ARM DWARF. Is it ok to add these feature to libunwind ? At least, the patch worked with my libunwinding failure case from dotnet/coreclr mentioned above. Best regards, Hyung-Kyu Choi >From f348298998ad3a6bd9ccb2276241b9ef3e0e9405 Mon Sep 17 00:00:00 2001 From: Hyung-Kyu Choi <[email protected]> Date: Sat, 13 Aug 2016 00:01:46 +0900 Subject: [PATCH] Support ARM VFP-v3/Neon 64-bit registers in DWARF Add support for ARM vfpv3/neon 64-bit registers (D0~D15) for UNW_ARM_METHOD_DWARF. Signed-off-by: Hyung-Kyu Choi <[email protected]> --- src/dwarf/Gparser.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 3a47255..1ceabed 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -39,7 +39,11 @@ read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0) return ret; +#ifdef UNW_TARGET_ARM + if (!(*valp < DWARF_NUM_PRESERVED_REGS || (UNW_ARM_D0 <= *valp && *valp <=UNW_ARM_D15))) +#else if (*valp >= DWARF_NUM_PRESERVED_REGS) +#endif { Debug (1, "Invalid register number %u\n", (unsigned int) *valp); return -UNW_EBADREG; @@ -62,6 +66,9 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, struct dwarf_cie_info *dci) { unw_word_t curr_ip, operand = 0, regnum, val, len, fde_encoding; +#ifdef UNW_TARGET_ARM + unw_word_t real_regnum; +#endif dwarf_reg_state_t *rs_stack = NULL, *new_rs, *old_rs; unw_addr_space_t as; unw_accessors_t *a; @@ -160,7 +167,23 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0) || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)) goto fail; +#ifdef UNW_TARGET_ARM + if (UNW_ARM_D0 <= regnum && regnum <= UNW_ARM_D15) { + // ARM vfpv3 D0-D15 registers + real_regnum = UNW_ARM_S0 + ((regnum - UNW_ARM_D0) * 2); +#if __BYTE_ORDER == __LITTLE_ENDIAN + set_reg(sr, real_regnum, DWARF_WHERE_CFAREL, (val-1) * dci->data_align); + set_reg(sr, real_regnum+1, DWARF_WHERE_CFAREL, val * dci->data_align); +#else + set_reg(sr, real_regnum, DWARF_WHERE_CFAREL, val * dci->data_align); + set_reg(sr, real_regnum+1, DWARF_WHERE_CFAREL, (val-1) * dci->data_align); +#endif + } else { + set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); + } +#else set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align); +#endif Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n", (long) regnum, (long) (val * dci->data_align)); break; -- 1.9.1 _______________________________________________ Libunwind-devel mailing list [email protected] https://lists.nongnu.org/mailman/listinfo/libunwind-devel
