Discussion:
[Libunwind-devel] A modification suggestion on MIPS64 N32 on libunwind
Deng, Yimin (NSB - CN/Shanghai)
2018-04-16 07:15:47 UTC
Permalink
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
Dave Watson
2018-04-17 14:56:34 UTC
Permalink
Hello,
Post by Deng, Yimin (NSB - CN/Shanghai)
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.
It appears parts of this patch have already been added to master. Can
you rebase this on top of the master branch and resend? Thanks!
Deng, Yimin (NSB - CN/Shanghai)
2018-04-18 03:12:45 UTC
Permalink
Hello,
I'm sorry for that. Thanks for your reminding!

Rebased (B.T.W. I have only N32 setup, so I'm not so sure whether it will affect other ABIs):

diff --git a/include/libunwind-mips.h b/include/libunwind-mips.h
--- a/include/libunwind-mips.h
+++ b/include/libunwind-mips.h
@@ -98,7 +98,7 @@ typedef enum
UNW_MIPS_R30,
UNW_MIPS_R31,

- UNW_MIPS_PC = 34,
+ UNW_MIPS_PC = 64,

/* FIXME: Other registers! */

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];
@@ -75,6 +75,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;

B.R.
Yimin Deng

-----Original Message-----
From: Dave Watson [mailto:***@fb.com]
Sent: 2018年4月17日 22:57
To: Deng, Yimin (NSB - CN/Shanghai)
Cc: libunwind-***@nongnu.org
Subject: Re: [Libunwind-devel] A modification suggestion on MIPS64 N32 on libunwind

Hello,
Post by Deng, Yimin (NSB - CN/Shanghai)
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.
It appears parts of this patch have already been added to master. Can you rebase this on top of the master branch and resend? Thanks!
Dave Watson
2018-04-24 18:57:36 UTC
Permalink
Post by Dave Watson
Hello,
I'm sorry for that. Thanks for your reminding!
This is merged, thanks.

Loading...