diff options
author | Matt Fleming <matt@console-pimps.org> | 2009-08-20 14:53:49 -0400 |
---|---|---|
committer | Matt Fleming <matt@console-pimps.org> | 2009-08-21 08:04:11 -0400 |
commit | 5580e9044df9c0e87861739d8c527006ead92e52 (patch) | |
tree | ef7c280cbc9e5b9f22170485cf05e7ebbe6c01f5 /arch | |
parent | 5480675dc60c7dda7146e506981b2b40a775cc1e (diff) |
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')
-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 8b0bcc087385..c367ed3373c5 100644 --- a/arch/sh/include/asm/dwarf.h +++ b/arch/sh/include/asm/dwarf.h | |||
@@ -297,6 +297,7 @@ struct dwarf_reg { | |||
297 | unsigned long flags; | 297 | unsigned long flags; |
298 | #define DWARF_REG_OFFSET (1 << 0) | 298 | #define DWARF_REG_OFFSET (1 << 0) |
299 | #define DWARF_VAL_OFFSET (1 << 1) | 299 | #define DWARF_VAL_OFFSET (1 << 1) |
300 | #define DWARF_UNDEFINED (1 << 2) | ||
300 | }; | 301 | }; |
301 | 302 | ||
302 | /* | 303 | /* |
@@ -370,6 +371,7 @@ extern struct dwarf_frame *dwarf_unwind_stack(unsigned long, | |||
370 | #define CFI_DEF_CFA .cfi_def_cfa | 371 | #define CFI_DEF_CFA .cfi_def_cfa |
371 | #define CFI_REGISTER .cfi_register | 372 | #define CFI_REGISTER .cfi_register |
372 | #define CFI_REL_OFFSET .cfi_rel_offset | 373 | #define CFI_REL_OFFSET .cfi_rel_offset |
374 | #define CFI_UNDEFINED .cfi_undefined | ||
373 | 375 | ||
374 | #else | 376 | #else |
375 | 377 | ||
@@ -383,6 +385,7 @@ extern struct dwarf_frame *dwarf_unwind_stack(unsigned long, | |||
383 | #define CFI_DEF_CFA CFI_IGNORE | 385 | #define CFI_DEF_CFA CFI_IGNORE |
384 | #define CFI_REGISTER CFI_IGNORE | 386 | #define CFI_REGISTER CFI_IGNORE |
385 | #define CFI_REL_OFFSET CFI_IGNORE | 387 | #define CFI_REL_OFFSET CFI_IGNORE |
388 | #define CFI_UNDEFINED CFI_IGNORE | ||
386 | 389 | ||
387 | #ifndef __ASSEMBLY__ | 390 | #ifndef __ASSEMBLY__ |
388 | static inline void dwarf_unwinder_init(void) | 391 | static inline void dwarf_unwinder_init(void) |
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index e6f427cff5ba..577302f31e6a 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, | |||
452 | case DW_CFA_undefined: | 452 | case DW_CFA_undefined: |
453 | count = dwarf_read_uleb128(current_insn, ®); | 453 | count = dwarf_read_uleb128(current_insn, ®); |
454 | current_insn += count; | 454 | current_insn += count; |
455 | regp = dwarf_frame_alloc_reg(frame, reg); | ||
456 | regp->flags |= DWARF_UNDEFINED; | ||
455 | break; | 457 | break; |
456 | case DW_CFA_def_cfa: | 458 | case DW_CFA_def_cfa: |
457 | count = dwarf_read_uleb128(current_insn, | 459 | count = dwarf_read_uleb128(current_insn, |
@@ -629,9 +631,16 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | |||
629 | UNWINDER_BUG(); | 631 | UNWINDER_BUG(); |
630 | } | 632 | } |
631 | 633 | ||
632 | /* If we haven't seen the return address reg, we're screwed. */ | ||
633 | reg = dwarf_frame_reg(frame, DWARF_ARCH_RA_REG); | 634 | reg = dwarf_frame_reg(frame, DWARF_ARCH_RA_REG); |
634 | UNWINDER_BUG_ON(!reg); | 635 | |
636 | /* | ||
637 | * If we haven't seen the return address register or the return | ||
638 | * address column is undefined then we must assume that this is | ||
639 | * the end of the callstack. | ||
640 | */ | ||
641 | if (!reg || reg->flags == DWARF_UNDEFINED) | ||
642 | goto bail; | ||
643 | |||
635 | UNWINDER_BUG_ON(reg->flags != DWARF_REG_OFFSET); | 644 | UNWINDER_BUG_ON(reg->flags != DWARF_REG_OFFSET); |
636 | 645 | ||
637 | addr = frame->cfa + reg->addr; | 646 | addr = frame->cfa + reg->addr; |