libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] [PATCH] Support ARM VFP-v3/Neon 64-bit registers in DW


From: Hyung-Kyu Choi
Subject: [Libunwind-devel] [PATCH] Support ARM VFP-v3/Neon 64-bit registers in DWARF
Date: Sat, 13 Aug 2016 00:34:35 +0900

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 <address@hidden>
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 <address@hidden>
---
 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, &regnum, 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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]