diff options
Diffstat (limited to 'arch/sh/kernel/dwarf.c')
-rw-r--r-- | arch/sh/kernel/dwarf.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index 3576b709f052..e51168064e56 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c | |||
@@ -540,6 +540,8 @@ void dwarf_free_frame(struct dwarf_frame *frame) | |||
540 | mempool_free(frame, dwarf_frame_pool); | 540 | mempool_free(frame, dwarf_frame_pool); |
541 | } | 541 | } |
542 | 542 | ||
543 | extern void ret_from_irq(void); | ||
544 | |||
543 | /** | 545 | /** |
544 | * dwarf_unwind_stack - unwind the stack | 546 | * dwarf_unwind_stack - unwind the stack |
545 | * | 547 | * |
@@ -678,6 +680,24 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | |||
678 | addr = frame->cfa + reg->addr; | 680 | addr = frame->cfa + reg->addr; |
679 | frame->return_addr = __raw_readl(addr); | 681 | frame->return_addr = __raw_readl(addr); |
680 | 682 | ||
683 | /* | ||
684 | * Ah, the joys of unwinding through interrupts. | ||
685 | * | ||
686 | * Interrupts are tricky - the DWARF info needs to be _really_ | ||
687 | * accurate and unfortunately I'm seeing a lot of bogus DWARF | ||
688 | * info. For example, I've seen interrupts occur in epilogues | ||
689 | * just after the frame pointer (r14) had been restored. The | ||
690 | * problem was that the DWARF info claimed that the CFA could be | ||
691 | * reached by using the value of the frame pointer before it was | ||
692 | * restored. | ||
693 | * | ||
694 | * So until the compiler can be trusted to produce reliable | ||
695 | * DWARF info when it really matters, let's stop unwinding once | ||
696 | * we've calculated the function that was interrupted. | ||
697 | */ | ||
698 | if (prev && prev->pc == (unsigned long)ret_from_irq) | ||
699 | frame->return_addr = 0; | ||
700 | |||
681 | return frame; | 701 | return frame; |
682 | 702 | ||
683 | bail: | 703 | bail: |
@@ -892,18 +912,18 @@ static struct unwinder dwarf_unwinder = { | |||
892 | 912 | ||
893 | static void dwarf_unwinder_cleanup(void) | 913 | static void dwarf_unwinder_cleanup(void) |
894 | { | 914 | { |
895 | struct dwarf_cie *cie; | 915 | struct dwarf_cie *cie, *cie_tmp; |
896 | struct dwarf_fde *fde; | 916 | struct dwarf_fde *fde, *fde_tmp; |
897 | 917 | ||
898 | /* | 918 | /* |
899 | * Deallocate all the memory allocated for the DWARF unwinder. | 919 | * Deallocate all the memory allocated for the DWARF unwinder. |
900 | * Traverse all the FDE/CIE lists and remove and free all the | 920 | * Traverse all the FDE/CIE lists and remove and free all the |
901 | * memory associated with those data structures. | 921 | * memory associated with those data structures. |
902 | */ | 922 | */ |
903 | list_for_each_entry(cie, &dwarf_cie_list, link) | 923 | list_for_each_entry_safe(cie, cie_tmp, &dwarf_cie_list, link) |
904 | kfree(cie); | 924 | kfree(cie); |
905 | 925 | ||
906 | list_for_each_entry(fde, &dwarf_fde_list, link) | 926 | list_for_each_entry_safe(fde, fde_tmp, &dwarf_fde_list, link) |
907 | kfree(fde); | 927 | kfree(fde); |
908 | 928 | ||
909 | kmem_cache_destroy(dwarf_reg_cachep); | 929 | kmem_cache_destroy(dwarf_reg_cachep); |