diff options
author | Matt Fleming <matt@console-pimps.org> | 2009-08-20 19:53:49 +0100 |
---|---|---|
committer | Matt Fleming <matt@console-pimps.org> | 2009-08-21 13:04:11 +0100 |
commit | 5580e9044df9c0e87861739d8c527006ead92e52 (patch) | |
tree | ef7c280cbc9e5b9f22170485cf05e7ebbe6c01f5 /arch/sh | |
parent | 5480675dc60c7dda7146e506981b2b40a775cc1e (diff) | |
download | op-kernel-dev-5580e9044df9c0e87861739d8c527006ead92e52.zip op-kernel-dev-5580e9044df9c0e87861739d8c527006ead92e52.tar.gz |
sh: Handle the DWARF op, DW_CFA_undefined
Allow a DWARF register to have an undefined value. When applied to the
DWARF return address register this lets lets us label a function as
having no direct caller, e.g. kernel_thread_helper().
Signed-off-by: Matt Fleming <matt@console-pimps.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/include/asm/dwarf.h | 3 | ||||
-rw-r--r-- | arch/sh/kernel/dwarf.c | 13 |
2 files changed, 14 insertions, 2 deletions
diff --git a/arch/sh/include/asm/dwarf.h b/arch/sh/include/asm/dwarf.h index 8b0bcc0..c367ed3 100644 --- a/arch/sh/include/asm/dwarf.h +++ b/arch/sh/include/asm/dwarf.h @@ -297,6 +297,7 @@ struct dwarf_reg { unsigned long flags; #define DWARF_REG_OFFSET (1 << 0) #define DWARF_VAL_OFFSET (1 << 1) +#define DWARF_UNDEFINED (1 << 2) }; /* @@ -370,6 +371,7 @@ extern struct dwarf_frame *dwarf_unwind_stack(unsigned long, #define CFI_DEF_CFA .cfi_def_cfa #define CFI_REGISTER .cfi_register #define CFI_REL_OFFSET .cfi_rel_offset +#define CFI_UNDEFINED .cfi_undefined #else @@ -383,6 +385,7 @@ extern struct dwarf_frame *dwarf_unwind_stack(unsigned long, #define CFI_DEF_CFA CFI_IGNORE #define CFI_REGISTER CFI_IGNORE #define CFI_REL_OFFSET CFI_IGNORE +#define CFI_UNDEFINED CFI_IGNORE #ifndef __ASSEMBLY__ static inline void dwarf_unwinder_init(void) diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index e6f427c..577302f 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c @@ -452,6 +452,8 @@ static int dwarf_cfa_execute_insns(unsigned char *insn_start, case DW_CFA_undefined: count = dwarf_read_uleb128(current_insn, ®); current_insn += count; + regp = dwarf_frame_alloc_reg(frame, reg); + regp->flags |= DWARF_UNDEFINED; break; case DW_CFA_def_cfa: count = dwarf_read_uleb128(current_insn, @@ -629,9 +631,16 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, UNWINDER_BUG(); } - /* If we haven't seen the return address reg, we're screwed. */ reg = dwarf_frame_reg(frame, DWARF_ARCH_RA_REG); - UNWINDER_BUG_ON(!reg); + + /* + * If we haven't seen the return address register or the return + * address column is undefined then we must assume that this is + * the end of the callstack. + */ + if (!reg || reg->flags == DWARF_UNDEFINED) + goto bail; + UNWINDER_BUG_ON(reg->flags != DWARF_REG_OFFSET); addr = frame->cfa + reg->addr; |