Deng, Yimin (NSB - CN/Shanghai)
2018-04-16 07:15:47 UTC
Hi,
I really appreciate for all your contribution to the libunwind. I mainly used the library 'unwind-ptrace' and it's very useful.
But I find that there are some issues when use it on MIPS64 (ABI: N32). After doing the modifications(based on libunwind-1.2.1) below, it works well.
I hope this will help you if you are suffering issues on the same arch and ABI.
diff --git a/include/libunwind-mips.h b/include/libunwind-mips.h
--- a/include/libunwind-mips.h
+++ b/include/libunwind-mips.h
@@ -54,7 +54,11 @@ extern "C" {
addresses and register values. To allow a single library to support
multiple ABIs, and to support N32 at all, we must use a 64-bit type
even when addresses are only 32 bits. */
+#if _MIPS_SIM == _ABI64
typedef uint64_t unw_word_t;
+#else
+typedef uint32_t unw_word_t;
+#endif
typedef int32_t unw_sword_t;
/* FIXME: MIPS ABIs. */
@@ -95,7 +99,7 @@ typedef enum
UNW_MIPS_R30,
UNW_MIPS_R31,
- UNW_MIPS_PC = 34,
+ UNW_MIPS_PC = 64,
/* FIXME: Other registers! */
@@ -103,7 +107,7 @@ typedef enum
previous frame. */
UNW_MIPS_CFA,
- UNW_TDEP_LAST_REG = UNW_MIPS_R31,
+ UNW_TDEP_LAST_REG = UNW_MIPS_PC,
UNW_TDEP_IP = UNW_MIPS_R31,
UNW_TDEP_SP = UNW_MIPS_R29,
diff --git a/include/tdep-mips/libunwind_i.h b/include/tdep-mips/libunwind_i.h
--- a/include/tdep-mips/libunwind_i.h
+++ b/include/tdep-mips/libunwind_i.h
@@ -247,6 +247,14 @@ dwarf_get (struct dwarf_cursor *c, dwarf
0, c->as_arg);
else if (c->as->abi == UNW_MIPS_ABI_O32)
return read_s32 (c, DWARF_GET_LOC (loc), val);
+ else if (c->as->abi == UNW_MIPS_ABI_N32) {
+ if (tdep_big_endian(c->as))
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc) + 4, val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ }
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
0, c->as_arg);
diff --git a/src/mips/Gcreate_addr_space.c b/src/mips/Gcreate_addr_space.c
--- a/src/mips/Gcreate_addr_space.c
+++ b/src/mips/Gcreate_addr_space.c
@@ -58,7 +58,15 @@ unw_create_addr_space (unw_accessors_t *
as->big_endian = (byte_order == __BIG_ENDIAN);
/* FIXME! There is no way to specify the ABI. */
+#if _MIPS_SIM == _ABIO32
as->abi = UNW_MIPS_ABI_O32;
+#elif _MIPS_SIM == _ABIN32
+ as->abi = UNW_MIPS_ABI_N32;
+#elif _MIPS_SIM == _ABI64
+ as->abi = UNW_MIPS_ABI_N64;
+#else
+# error Unsupported ABI
+#endif
as->addr_size = 4;
return as;
diff --git a/src/mips/Gregs.c b/src/mips/Gregs.c
--- a/src/mips/Gregs.c
+++ b/src/mips/Gregs.c
@@ -63,7 +63,7 @@ tdep_access_reg (struct cursor *c, unw_r
case UNW_MIPS_R26:
case UNW_MIPS_R27:
case UNW_MIPS_R28:
- case UNW_MIPS_R29:
+
case UNW_MIPS_R30:
case UNW_MIPS_R31:
loc = c->dwarf.loc[reg - UNW_MIPS_R0];
@@ -73,6 +73,7 @@ tdep_access_reg (struct cursor *c, unw_r
loc = c->dwarf.loc[reg];
break;
+ case UNW_MIPS_R29:
case UNW_MIPS_CFA:
if (write)
return -UNW_EREADONLYREG;
diff --git a/src/ptrace/_UPT_reg_offset.c b/src/ptrace/_UPT_reg_offset.c
--- a/src/ptrace/_UPT_reg_offset.c
+++ b/src/ptrace/_UPT_reg_offset.c
@@ -501,6 +501,42 @@ const int _UPT_reg_offset[UNW_REG_LAST +
[UNW_ARM_R14] = 0x38,
[UNW_ARM_R15] = 0x3c,
#elif defined(UNW_TARGET_MIPS)
+#define UNW_R_OFF(R) [R] = R
+ UNW_R_OFF(UNW_MIPS_R0),
+ UNW_R_OFF(UNW_MIPS_R1),
+ UNW_R_OFF(UNW_MIPS_R2),
+ UNW_R_OFF(UNW_MIPS_R3),
+ UNW_R_OFF(UNW_MIPS_R4),
+ UNW_R_OFF(UNW_MIPS_R5),
+ UNW_R_OFF(UNW_MIPS_R6),
+ UNW_R_OFF(UNW_MIPS_R7),
+ UNW_R_OFF(UNW_MIPS_R8),
+ UNW_R_OFF(UNW_MIPS_R9),
+ UNW_R_OFF(UNW_MIPS_R10),
+ UNW_R_OFF(UNW_MIPS_R11),
+ UNW_R_OFF(UNW_MIPS_R12),
+ UNW_R_OFF(UNW_MIPS_R13),
+ UNW_R_OFF(UNW_MIPS_R14),
+ UNW_R_OFF(UNW_MIPS_R15),
+ UNW_R_OFF(UNW_MIPS_R16),
+ UNW_R_OFF(UNW_MIPS_R17),
+ UNW_R_OFF(UNW_MIPS_R18),
+ UNW_R_OFF(UNW_MIPS_R19),
+ UNW_R_OFF(UNW_MIPS_R20),
+ UNW_R_OFF(UNW_MIPS_R21),
+ UNW_R_OFF(UNW_MIPS_R22),
+ UNW_R_OFF(UNW_MIPS_R23),
+ UNW_R_OFF(UNW_MIPS_R24),
+ UNW_R_OFF(UNW_MIPS_R25),
+ UNW_R_OFF(UNW_MIPS_R26),
+ UNW_R_OFF(UNW_MIPS_R27),
+ UNW_R_OFF(UNW_MIPS_R28),
+ UNW_R_OFF(UNW_MIPS_R29),
+ UNW_R_OFF(UNW_MIPS_R30),
+ UNW_R_OFF(UNW_MIPS_R31),
+ UNW_R_OFF(UNW_MIPS_PC)
+
+#undef UNW_R_OFF
#elif defined(UNW_TARGET_SH)
#elif defined(UNW_TARGET_AARCH64)
[UNW_AARCH64_X0] = 0x00,
Thx & B.R.
Yimin Deng
I really appreciate for all your contribution to the libunwind. I mainly used the library 'unwind-ptrace' and it's very useful.
But I find that there are some issues when use it on MIPS64 (ABI: N32). After doing the modifications(based on libunwind-1.2.1) below, it works well.
I hope this will help you if you are suffering issues on the same arch and ABI.
diff --git a/include/libunwind-mips.h b/include/libunwind-mips.h
--- a/include/libunwind-mips.h
+++ b/include/libunwind-mips.h
@@ -54,7 +54,11 @@ extern "C" {
addresses and register values. To allow a single library to support
multiple ABIs, and to support N32 at all, we must use a 64-bit type
even when addresses are only 32 bits. */
+#if _MIPS_SIM == _ABI64
typedef uint64_t unw_word_t;
+#else
+typedef uint32_t unw_word_t;
+#endif
typedef int32_t unw_sword_t;
/* FIXME: MIPS ABIs. */
@@ -95,7 +99,7 @@ typedef enum
UNW_MIPS_R30,
UNW_MIPS_R31,
- UNW_MIPS_PC = 34,
+ UNW_MIPS_PC = 64,
/* FIXME: Other registers! */
@@ -103,7 +107,7 @@ typedef enum
previous frame. */
UNW_MIPS_CFA,
- UNW_TDEP_LAST_REG = UNW_MIPS_R31,
+ UNW_TDEP_LAST_REG = UNW_MIPS_PC,
UNW_TDEP_IP = UNW_MIPS_R31,
UNW_TDEP_SP = UNW_MIPS_R29,
diff --git a/include/tdep-mips/libunwind_i.h b/include/tdep-mips/libunwind_i.h
--- a/include/tdep-mips/libunwind_i.h
+++ b/include/tdep-mips/libunwind_i.h
@@ -247,6 +247,14 @@ dwarf_get (struct dwarf_cursor *c, dwarf
0, c->as_arg);
else if (c->as->abi == UNW_MIPS_ABI_O32)
return read_s32 (c, DWARF_GET_LOC (loc), val);
+ else if (c->as->abi == UNW_MIPS_ABI_N32) {
+ if (tdep_big_endian(c->as))
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc) + 4, val,
+ 0, c->as_arg);
+ else
+ return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
+ 0, c->as_arg);
+ }
else
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
0, c->as_arg);
diff --git a/src/mips/Gcreate_addr_space.c b/src/mips/Gcreate_addr_space.c
--- a/src/mips/Gcreate_addr_space.c
+++ b/src/mips/Gcreate_addr_space.c
@@ -58,7 +58,15 @@ unw_create_addr_space (unw_accessors_t *
as->big_endian = (byte_order == __BIG_ENDIAN);
/* FIXME! There is no way to specify the ABI. */
+#if _MIPS_SIM == _ABIO32
as->abi = UNW_MIPS_ABI_O32;
+#elif _MIPS_SIM == _ABIN32
+ as->abi = UNW_MIPS_ABI_N32;
+#elif _MIPS_SIM == _ABI64
+ as->abi = UNW_MIPS_ABI_N64;
+#else
+# error Unsupported ABI
+#endif
as->addr_size = 4;
return as;
diff --git a/src/mips/Gregs.c b/src/mips/Gregs.c
--- a/src/mips/Gregs.c
+++ b/src/mips/Gregs.c
@@ -63,7 +63,7 @@ tdep_access_reg (struct cursor *c, unw_r
case UNW_MIPS_R26:
case UNW_MIPS_R27:
case UNW_MIPS_R28:
- case UNW_MIPS_R29:
+
case UNW_MIPS_R30:
case UNW_MIPS_R31:
loc = c->dwarf.loc[reg - UNW_MIPS_R0];
@@ -73,6 +73,7 @@ tdep_access_reg (struct cursor *c, unw_r
loc = c->dwarf.loc[reg];
break;
+ case UNW_MIPS_R29:
case UNW_MIPS_CFA:
if (write)
return -UNW_EREADONLYREG;
diff --git a/src/ptrace/_UPT_reg_offset.c b/src/ptrace/_UPT_reg_offset.c
--- a/src/ptrace/_UPT_reg_offset.c
+++ b/src/ptrace/_UPT_reg_offset.c
@@ -501,6 +501,42 @@ const int _UPT_reg_offset[UNW_REG_LAST +
[UNW_ARM_R14] = 0x38,
[UNW_ARM_R15] = 0x3c,
#elif defined(UNW_TARGET_MIPS)
+#define UNW_R_OFF(R) [R] = R
+ UNW_R_OFF(UNW_MIPS_R0),
+ UNW_R_OFF(UNW_MIPS_R1),
+ UNW_R_OFF(UNW_MIPS_R2),
+ UNW_R_OFF(UNW_MIPS_R3),
+ UNW_R_OFF(UNW_MIPS_R4),
+ UNW_R_OFF(UNW_MIPS_R5),
+ UNW_R_OFF(UNW_MIPS_R6),
+ UNW_R_OFF(UNW_MIPS_R7),
+ UNW_R_OFF(UNW_MIPS_R8),
+ UNW_R_OFF(UNW_MIPS_R9),
+ UNW_R_OFF(UNW_MIPS_R10),
+ UNW_R_OFF(UNW_MIPS_R11),
+ UNW_R_OFF(UNW_MIPS_R12),
+ UNW_R_OFF(UNW_MIPS_R13),
+ UNW_R_OFF(UNW_MIPS_R14),
+ UNW_R_OFF(UNW_MIPS_R15),
+ UNW_R_OFF(UNW_MIPS_R16),
+ UNW_R_OFF(UNW_MIPS_R17),
+ UNW_R_OFF(UNW_MIPS_R18),
+ UNW_R_OFF(UNW_MIPS_R19),
+ UNW_R_OFF(UNW_MIPS_R20),
+ UNW_R_OFF(UNW_MIPS_R21),
+ UNW_R_OFF(UNW_MIPS_R22),
+ UNW_R_OFF(UNW_MIPS_R23),
+ UNW_R_OFF(UNW_MIPS_R24),
+ UNW_R_OFF(UNW_MIPS_R25),
+ UNW_R_OFF(UNW_MIPS_R26),
+ UNW_R_OFF(UNW_MIPS_R27),
+ UNW_R_OFF(UNW_MIPS_R28),
+ UNW_R_OFF(UNW_MIPS_R29),
+ UNW_R_OFF(UNW_MIPS_R30),
+ UNW_R_OFF(UNW_MIPS_R31),
+ UNW_R_OFF(UNW_MIPS_PC)
+
+#undef UNW_R_OFF
#elif defined(UNW_TARGET_SH)
#elif defined(UNW_TARGET_AARCH64)
[UNW_AARCH64_X0] = 0x00,
Thx & B.R.
Yimin Deng