[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Libunwind-devel] [PATCH 31/35] MIPS coredump support
From: |
Tommi Rantala |
Subject: |
[Libunwind-devel] [PATCH 31/35] MIPS coredump support |
Date: |
Tue, 18 Sep 2012 16:31:40 +0300 |
Add MIPS support to the coredump library. Explicit support for the MIPS
program counter register is added so that we can start backtracing from
the program counter value we read from a core dump. The PC register
support was not strictly required for local backtracing, and we will in
fact just plug the return address to the PC register in getcontext().
I have only tested the 32bit "OABI" paths.
---
configure.ac | 2 +-
include/libunwind-mips.h | 2 ++
src/coredump/_UCD_access_reg_linux.c | 37 +++++++++++++++++++++++++++++++++-
src/mips/Gget_save_loc.c | 1 +
src/mips/Ginit.c | 2 ++
src/mips/Gregs.c | 4 ++++
src/mips/getcontext.S | 8 ++++++++
src/mips/init.h | 4 +++-
src/mips/offsets.h | 3 +++
src/mips/regname.c | 2 ++
10 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index 0312b24..aed7eab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -103,7 +103,7 @@ SET_ARCH([$target_cpu],[target_arch])
AC_ARG_ENABLE(coredump,
AS_HELP_STRING([--enable-coredump],[building libunwind-coredump
library]),,
- [AS_CASE([$host_arch], [x86*], [enable_coredump=yes],
[enable_coredump=no])]
+ [AS_CASE([$host_arch], [mips*|x86*], [enable_coredump=yes],
[enable_coredump=no])]
)
AC_MSG_CHECKING([if we should build libunwind-coredump])
diff --git a/include/libunwind-mips.h b/include/libunwind-mips.h
index 91f7001..cf22fc9 100644
--- a/include/libunwind-mips.h
+++ b/include/libunwind-mips.h
@@ -95,6 +95,8 @@ typedef enum
UNW_MIPS_R30,
UNW_MIPS_R31,
+ UNW_MIPS_PC = 34,
+
/* FIXME: Other registers! */
/* For MIPS, the CFA is the value of SP (r29) at the call site in the
diff --git a/src/coredump/_UCD_access_reg_linux.c
b/src/coredump/_UCD_access_reg_linux.c
index c48f5c9..9fd7f7d 100644
--- a/src/coredump/_UCD_access_reg_linux.c
+++ b/src/coredump/_UCD_access_reg_linux.c
@@ -43,7 +43,42 @@ _UCD_access_reg (unw_addr_space_t as,
if (regnum < 0 || regnum >= 16)
goto badreg;
#else
-#if defined(UNW_TARGET_X86)
+#if defined(UNW_TARGET_MIPS)
+ static const uint8_t remap_regs[] =
+ {
+ [UNW_MIPS_R0] = EF_REG0,
+ [UNW_MIPS_R1] = EF_REG1,
+ [UNW_MIPS_R2] = EF_REG2,
+ [UNW_MIPS_R3] = EF_REG3,
+ [UNW_MIPS_R4] = EF_REG4,
+ [UNW_MIPS_R5] = EF_REG5,
+ [UNW_MIPS_R6] = EF_REG6,
+ [UNW_MIPS_R7] = EF_REG7,
+ [UNW_MIPS_R8] = EF_REG8,
+ [UNW_MIPS_R9] = EF_REG9,
+ [UNW_MIPS_R10] = EF_REG10,
+ [UNW_MIPS_R11] = EF_REG11,
+ [UNW_MIPS_R12] = EF_REG12,
+ [UNW_MIPS_R13] = EF_REG13,
+ [UNW_MIPS_R14] = EF_REG14,
+ [UNW_MIPS_R15] = EF_REG15,
+ [UNW_MIPS_R16] = EF_REG16,
+ [UNW_MIPS_R17] = EF_REG17,
+ [UNW_MIPS_R18] = EF_REG18,
+ [UNW_MIPS_R19] = EF_REG19,
+ [UNW_MIPS_R20] = EF_REG20,
+ [UNW_MIPS_R21] = EF_REG21,
+ [UNW_MIPS_R22] = EF_REG22,
+ [UNW_MIPS_R23] = EF_REG23,
+ [UNW_MIPS_R24] = EF_REG24,
+ [UNW_MIPS_R25] = EF_REG25,
+ [UNW_MIPS_R28] = EF_REG28,
+ [UNW_MIPS_R29] = EF_REG29,
+ [UNW_MIPS_R30] = EF_REG30,
+ [UNW_MIPS_R31] = EF_REG31,
+ [UNW_MIPS_PC] = EF_CP0_EPC,
+ };
+#elif defined(UNW_TARGET_X86)
static const uint8_t remap_regs[] =
{
/* names from libunwind-x86.h */
diff --git a/src/mips/Gget_save_loc.c b/src/mips/Gget_save_loc.c
index 262e23e..0f90847 100644
--- a/src/mips/Gget_save_loc.c
+++ b/src/mips/Gget_save_loc.c
@@ -68,6 +68,7 @@ unw_get_save_loc (unw_cursor_t *cursor, int reg,
unw_save_loc_t *sloc)
case UNW_MIPS_R29:
case UNW_MIPS_R30:
case UNW_MIPS_R31:
+ case UNW_MIPS_PC:
loc = c->dwarf.loc[reg - UNW_MIPS_R0];
break;
diff --git a/src/mips/Ginit.c b/src/mips/Ginit.c
index 6ffeabf..31000b3 100644
--- a/src/mips/Ginit.c
+++ b/src/mips/Ginit.c
@@ -46,6 +46,8 @@ uc_addr (ucontext_t *uc, int reg)
{
if (reg >= UNW_MIPS_R0 && reg < UNW_MIPS_R0 + 32)
return &uc->uc_mcontext.gregs[reg - UNW_MIPS_R0];
+ else if (reg == UNW_MIPS_PC)
+ return &uc->uc_mcontext.pc;
else
return NULL;
}
diff --git a/src/mips/Gregs.c b/src/mips/Gregs.c
index 9f37299..0dfc4a9 100644
--- a/src/mips/Gregs.c
+++ b/src/mips/Gregs.c
@@ -69,6 +69,10 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg,
unw_word_t *valp,
loc = c->dwarf.loc[reg - UNW_MIPS_R0];
break;
+ case UNW_MIPS_PC:
+ loc = c->dwarf.loc[reg];
+ break;
+
case UNW_MIPS_CFA:
if (write)
return -UNW_EREADONLYREG;
diff --git a/src/mips/getcontext.S b/src/mips/getcontext.S
index ad9e1f0..d1dbd57 100644
--- a/src/mips/getcontext.S
+++ b/src/mips/getcontext.S
@@ -1,5 +1,6 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2008 CodeSourcery
+ Copyright (C) 2012 Tommi Rantala <address@hidden>
This file is part of libunwind.
@@ -37,8 +38,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */
sw $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X + OFFSET) ($4); \
sra $1, $X, 31; \
sw $1, (LINUX_UC_MCONTEXT_GREGS + 8 * X + 4 - OFFSET) ($4)
+/* Yes, we save the return address to PC. */
+# define SPC \
+ sw $31, (LINUX_UC_MCONTEXT_PC + OFFSET) ($4); \
+ sra $1, $31, 31; \
+ sw $1, (LINUX_UC_MCONTEXT_PC + 4 - OFFSET) ($4)
#else
# define SREG(X) sd $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ($4)
+# define SPC sd $31, (LINUX_UC_MCONTEXT_PC) ($4)
#endif
.global _Umips_getcontext
@@ -79,6 +86,7 @@ _Umips_getcontext:
SREG (29)
SREG (30)
SREG (31)
+ SPC
li $2, 0
j $31
diff --git a/src/mips/init.h b/src/mips/init.h
index 3a4bb00..95322c6 100644
--- a/src/mips/init.h
+++ b/src/mips/init.h
@@ -34,7 +34,9 @@ common_init (struct cursor *c, unsigned use_prev_instr)
for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i)
c->dwarf.loc[i] = DWARF_NULL_LOC;
- ret = dwarf_get (&c->dwarf, c->dwarf.loc[31], &c->dwarf.ip);
+ c->dwarf.loc[UNW_MIPS_PC] = DWARF_REG_LOC (&c->dwarf, UNW_MIPS_PC);
+
+ ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_MIPS_PC], &c->dwarf.ip);
if (ret < 0)
return ret;
diff --git a/src/mips/offsets.h b/src/mips/offsets.h
index 8040f6a..49af970 100644
--- a/src/mips/offsets.h
+++ b/src/mips/offsets.h
@@ -16,6 +16,7 @@
# define LINUX_UC_STACK_OFF 0x8
# define LINUX_UC_MCONTEXT_OFF 0x18
# define LINUX_UC_SIGMASK_OFF 0x268
+# define LINUX_UC_MCONTEXT_PC 0x20
# define LINUX_UC_MCONTEXT_GREGS 0x28
#elif _MIPS_SIM == _ABIN32
@@ -25,6 +26,7 @@
# define LINUX_UC_STACK_OFF 0x8
# define LINUX_UC_MCONTEXT_OFF 0x18
# define LINUX_UC_SIGMASK_OFF 0x270
+# define LINUX_UC_MCONTEXT_PC 0x258
# define LINUX_UC_MCONTEXT_GREGS 0x18
#elif _MIPS_SIM == _ABI64
@@ -34,6 +36,7 @@
# define LINUX_UC_STACK_OFF 0x10
# define LINUX_UC_MCONTEXT_OFF 0x28
# define LINUX_UC_SIGMASK_OFF 0x280
+# define LINUX_UC_MCONTEXT_PC 0x268
# define LINUX_UC_MCONTEXT_GREGS 0x28
#endif
diff --git a/src/mips/regname.c b/src/mips/regname.c
index 94000d4..a4a6334 100644
--- a/src/mips/regname.c
+++ b/src/mips/regname.c
@@ -41,6 +41,8 @@ unw_regname (unw_regnum_t reg)
{
if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
return regname[reg];
+ else if (reg == UNW_MIPS_PC)
+ return "pc";
else
return "???";
}
--
1.7.9.5
- [Libunwind-devel] [PATCH 25/35] Rename `rs-race' to `Lrs-race', (continued)
- [Libunwind-devel] [PATCH 25/35] Rename `rs-race' to `Lrs-race', Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 26/35] Call `unw_backtrace()' explicitly in test-flush-cache.c, Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 22/35] Rename `test-varargs' to `Ltest-varargs', Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 27/35] Roll `test-nocalloc' into `Ltest-nocalloc.c', Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 32/35] Enable coredump library build on ARM by default, Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 30/35] Stop including `memory.h', Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 34/35] ppc32: include `libunwind_i.h' for UNUSED in ucontext_i.h, Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 33/35] SuperH port, Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 35/35] ppc32: `UNW_PPC32_REGS' fixlet, Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 28/35] Call snprintf() from signal handler only if required in test-async-sig, Tommi Rantala, 2012/09/18
- [Libunwind-devel] [PATCH 31/35] MIPS coredump support,
Tommi Rantala <=