1
0
Fork 0
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:
Tommi Rantala 2012-09-07 12:12:50 +03:00
parent ded94b98ff
commit 79c2c254a7
10 changed files with 62 additions and 3 deletions

View file

@ -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])

View file

@ -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

View file

@ -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 */

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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 "???";
} }