mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-25 16:47:38 +01:00
MIPS coredump support
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.
This commit is contained in:
parent
ded94b98ff
commit
79c2c254a7
10 changed files with 62 additions and 3 deletions
|
@ -103,7 +103,7 @@ SET_ARCH([$target_cpu],[target_arch])
|
||||||
|
|
||||||
AC_ARG_ENABLE(coredump,
|
AC_ARG_ENABLE(coredump,
|
||||||
AS_HELP_STRING([--enable-coredump],[building libunwind-coredump library]),,
|
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])
|
AC_MSG_CHECKING([if we should build libunwind-coredump])
|
||||||
|
|
|
@ -95,6 +95,8 @@ typedef enum
|
||||||
UNW_MIPS_R30,
|
UNW_MIPS_R30,
|
||||||
UNW_MIPS_R31,
|
UNW_MIPS_R31,
|
||||||
|
|
||||||
|
UNW_MIPS_PC = 34,
|
||||||
|
|
||||||
/* FIXME: Other registers! */
|
/* FIXME: Other registers! */
|
||||||
|
|
||||||
/* For MIPS, the CFA is the value of SP (r29) at the call site in the
|
/* For MIPS, the CFA is the value of SP (r29) at the call site in the
|
||||||
|
|
|
@ -43,7 +43,42 @@ _UCD_access_reg (unw_addr_space_t as,
|
||||||
if (regnum < 0 || regnum >= 16)
|
if (regnum < 0 || regnum >= 16)
|
||||||
goto badreg;
|
goto badreg;
|
||||||
#else
|
#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[] =
|
static const uint8_t remap_regs[] =
|
||||||
{
|
{
|
||||||
/* names from libunwind-x86.h */
|
/* names from libunwind-x86.h */
|
||||||
|
|
|
@ -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_R29:
|
||||||
case UNW_MIPS_R30:
|
case UNW_MIPS_R30:
|
||||||
case UNW_MIPS_R31:
|
case UNW_MIPS_R31:
|
||||||
|
case UNW_MIPS_PC:
|
||||||
loc = c->dwarf.loc[reg - UNW_MIPS_R0];
|
loc = c->dwarf.loc[reg - UNW_MIPS_R0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,8 @@ uc_addr (ucontext_t *uc, int reg)
|
||||||
{
|
{
|
||||||
if (reg >= UNW_MIPS_R0 && reg < UNW_MIPS_R0 + 32)
|
if (reg >= UNW_MIPS_R0 && reg < UNW_MIPS_R0 + 32)
|
||||||
return &uc->uc_mcontext.gregs[reg - UNW_MIPS_R0];
|
return &uc->uc_mcontext.gregs[reg - UNW_MIPS_R0];
|
||||||
|
else if (reg == UNW_MIPS_PC)
|
||||||
|
return &uc->uc_mcontext.pc;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
loc = c->dwarf.loc[reg - UNW_MIPS_R0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UNW_MIPS_PC:
|
||||||
|
loc = c->dwarf.loc[reg];
|
||||||
|
break;
|
||||||
|
|
||||||
case UNW_MIPS_CFA:
|
case UNW_MIPS_CFA:
|
||||||
if (write)
|
if (write)
|
||||||
return -UNW_EREADONLYREG;
|
return -UNW_EREADONLYREG;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2008 CodeSourcery
|
Copyright (C) 2008 CodeSourcery
|
||||||
|
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
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); \
|
sw $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X + OFFSET) ($4); \
|
||||||
sra $1, $X, 31; \
|
sra $1, $X, 31; \
|
||||||
sw $1, (LINUX_UC_MCONTEXT_GREGS + 8 * X + 4 - OFFSET) ($4)
|
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
|
#else
|
||||||
# define SREG(X) sd $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ($4)
|
# define SREG(X) sd $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X) ($4)
|
||||||
|
# define SPC sd $31, (LINUX_UC_MCONTEXT_PC) ($4)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.global _Umips_getcontext
|
.global _Umips_getcontext
|
||||||
|
@ -79,6 +86,7 @@ _Umips_getcontext:
|
||||||
SREG (29)
|
SREG (29)
|
||||||
SREG (30)
|
SREG (30)
|
||||||
SREG (31)
|
SREG (31)
|
||||||
|
SPC
|
||||||
li $2, 0
|
li $2, 0
|
||||||
j $31
|
j $31
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,9 @@ common_init (struct cursor *c, unsigned use_prev_instr)
|
||||||
for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i)
|
for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i)
|
||||||
c->dwarf.loc[i] = DWARF_NULL_LOC;
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
# define LINUX_UC_STACK_OFF 0x8
|
# define LINUX_UC_STACK_OFF 0x8
|
||||||
# define LINUX_UC_MCONTEXT_OFF 0x18
|
# define LINUX_UC_MCONTEXT_OFF 0x18
|
||||||
# define LINUX_UC_SIGMASK_OFF 0x268
|
# define LINUX_UC_SIGMASK_OFF 0x268
|
||||||
|
# define LINUX_UC_MCONTEXT_PC 0x20
|
||||||
# define LINUX_UC_MCONTEXT_GREGS 0x28
|
# define LINUX_UC_MCONTEXT_GREGS 0x28
|
||||||
|
|
||||||
#elif _MIPS_SIM == _ABIN32
|
#elif _MIPS_SIM == _ABIN32
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
# define LINUX_UC_STACK_OFF 0x8
|
# define LINUX_UC_STACK_OFF 0x8
|
||||||
# define LINUX_UC_MCONTEXT_OFF 0x18
|
# define LINUX_UC_MCONTEXT_OFF 0x18
|
||||||
# define LINUX_UC_SIGMASK_OFF 0x270
|
# define LINUX_UC_SIGMASK_OFF 0x270
|
||||||
|
# define LINUX_UC_MCONTEXT_PC 0x258
|
||||||
# define LINUX_UC_MCONTEXT_GREGS 0x18
|
# define LINUX_UC_MCONTEXT_GREGS 0x18
|
||||||
|
|
||||||
#elif _MIPS_SIM == _ABI64
|
#elif _MIPS_SIM == _ABI64
|
||||||
|
@ -34,6 +36,7 @@
|
||||||
# define LINUX_UC_STACK_OFF 0x10
|
# define LINUX_UC_STACK_OFF 0x10
|
||||||
# define LINUX_UC_MCONTEXT_OFF 0x28
|
# define LINUX_UC_MCONTEXT_OFF 0x28
|
||||||
# define LINUX_UC_SIGMASK_OFF 0x280
|
# define LINUX_UC_SIGMASK_OFF 0x280
|
||||||
|
# define LINUX_UC_MCONTEXT_PC 0x268
|
||||||
# define LINUX_UC_MCONTEXT_GREGS 0x28
|
# define LINUX_UC_MCONTEXT_GREGS 0x28
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,6 +41,8 @@ unw_regname (unw_regnum_t reg)
|
||||||
{
|
{
|
||||||
if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
|
if (reg < (unw_regnum_t) ARRAY_SIZE (regname))
|
||||||
return regname[reg];
|
return regname[reg];
|
||||||
|
else if (reg == UNW_MIPS_PC)
|
||||||
|
return "pc";
|
||||||
else
|
else
|
||||||
return "???";
|
return "???";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue