aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/dwarf.c
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-08-16 16:54:48 -0400
committerMatt Fleming <matt@console-pimps.org>2009-08-21 08:02:44 -0400
commitb344e24a8e8ceda83d1285d22e3e5baf4f5e42d3 (patch)
tree4b9500264a797736b48b59c3f0977277ace53386 /arch/sh/kernel/dwarf.c
parent97efbbd5886e27b61c19c77d41f6491f5d96fbd0 (diff)
sh: unwinder: Introduce UNWINDER_BUG() and UNWINDER_BUG_ON()
We can't assume that if we execute the unwinder code and the unwinder was already running that it has faulted. Clearly two kernel threads can invoke the unwinder at the same time and may be running simultaneously. The previous approach used BUG() and BUG_ON() in the unwinder code to detect whether the unwinder was incapable of unwinding the stack, and that the next available unwinder should be used instead. A better approach is to explicitly invoke a trap handler to switch unwinders when the current unwinder cannot continue. Signed-off-by: Matt Fleming <matt@console-pimps.org>
Diffstat (limited to 'arch/sh/kernel/dwarf.c')
-rw-r--r--arch/sh/kernel/dwarf.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index d271d04adccd..606ece37eb42 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -69,7 +69,7 @@ static struct dwarf_reg *dwarf_frame_alloc_reg(struct dwarf_frame *frame,
69 * Let's just bomb hard here, we have no way to 69 * Let's just bomb hard here, we have no way to
70 * gracefully recover. 70 * gracefully recover.
71 */ 71 */
72 BUG(); 72 UNWINDER_BUG();
73 } 73 }
74 74
75 reg->number = reg_num; 75 reg->number = reg_num;
@@ -232,7 +232,7 @@ static int dwarf_read_encoded_value(char *addr, unsigned long *val,
232 break; 232 break;
233 default: 233 default:
234 pr_debug("encoding=0x%x\n", (encoding & 0x70)); 234 pr_debug("encoding=0x%x\n", (encoding & 0x70));
235 BUG(); 235 UNWINDER_BUG();
236 } 236 }
237 237
238 if ((encoding & 0x07) == 0x00) 238 if ((encoding & 0x07) == 0x00)
@@ -247,7 +247,7 @@ static int dwarf_read_encoded_value(char *addr, unsigned long *val,
247 break; 247 break;
248 default: 248 default:
249 pr_debug("encoding=0x%x\n", encoding); 249 pr_debug("encoding=0x%x\n", encoding);
250 BUG(); 250 UNWINDER_BUG();
251 } 251 }
252 252
253 return count; 253 return count;
@@ -519,6 +519,7 @@ static int dwarf_cfa_execute_insns(unsigned char *insn_start,
519 break; 519 break;
520 default: 520 default:
521 pr_debug("unhandled DWARF instruction 0x%x\n", insn); 521 pr_debug("unhandled DWARF instruction 0x%x\n", insn);
522 UNWINDER_BUG();
522 break; 523 break;
523 } 524 }
524 } 525 }
@@ -535,8 +536,8 @@ static int dwarf_cfa_execute_insns(unsigned char *insn_start,
535 * on the callstack. Each of the lower (older) stack frames are 536 * on the callstack. Each of the lower (older) stack frames are
536 * linked via the "prev" member. 537 * linked via the "prev" member.
537 */ 538 */
538struct dwarf_frame *dwarf_unwind_stack(unsigned long pc, 539struct dwarf_frame * dwarf_unwind_stack(unsigned long pc,
539 struct dwarf_frame *prev) 540 struct dwarf_frame *prev)
540{ 541{
541 struct dwarf_frame *frame; 542 struct dwarf_frame *frame;
542 struct dwarf_cie *cie; 543 struct dwarf_cie *cie;
@@ -558,7 +559,7 @@ struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
558 frame = mempool_alloc(dwarf_frame_pool, GFP_ATOMIC); 559 frame = mempool_alloc(dwarf_frame_pool, GFP_ATOMIC);
559 if (!frame) { 560 if (!frame) {
560 printk(KERN_ERR "Unable to allocate a dwarf frame\n"); 561 printk(KERN_ERR "Unable to allocate a dwarf frame\n");
561 BUG(); 562 UNWINDER_BUG();
562 } 563 }
563 564
564 INIT_LIST_HEAD(&frame->reg_list); 565 INIT_LIST_HEAD(&frame->reg_list);
@@ -605,7 +606,8 @@ struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
605 case DWARF_FRAME_CFA_REG_OFFSET: 606 case DWARF_FRAME_CFA_REG_OFFSET:
606 if (prev) { 607 if (prev) {
607 reg = dwarf_frame_reg(prev, frame->cfa_register); 608 reg = dwarf_frame_reg(prev, frame->cfa_register);
608 BUG_ON(!reg); 609 UNWINDER_BUG_ON(!reg);
610 UNWINDER_BUG_ON(reg->flags != DWARF_REG_OFFSET);
609 611
610 addr = prev->cfa + reg->addr; 612 addr = prev->cfa + reg->addr;
611 frame->cfa = __raw_readl(addr); 613 frame->cfa = __raw_readl(addr);
@@ -624,12 +626,13 @@ struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
624 frame->cfa += frame->cfa_offset; 626 frame->cfa += frame->cfa_offset;
625 break; 627 break;
626 default: 628 default:
627 BUG(); 629 UNWINDER_BUG();
628 } 630 }
629 631
630 /* If we haven't seen the return address reg, we're screwed. */ 632 /* If we haven't seen the return address reg, we're screwed. */
631 reg = dwarf_frame_reg(frame, DWARF_ARCH_RA_REG); 633 reg = dwarf_frame_reg(frame, DWARF_ARCH_RA_REG);
632 BUG_ON(!reg); 634 UNWINDER_BUG_ON(!reg);
635 UNWINDER_BUG_ON(reg->flags != DWARF_REG_OFFSET);
633 636
634 addr = frame->cfa + reg->addr; 637 addr = frame->cfa + reg->addr;
635 frame->return_addr = __raw_readl(addr); 638 frame->return_addr = __raw_readl(addr);
@@ -664,7 +667,7 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
664 cie->cie_pointer = (unsigned long)entry; 667 cie->cie_pointer = (unsigned long)entry;
665 668
666 cie->version = *(char *)p++; 669 cie->version = *(char *)p++;
667 BUG_ON(cie->version != 1); 670 UNWINDER_BUG_ON(cie->version != 1);
668 671
669 cie->augmentation = p; 672 cie->augmentation = p;
670 p += strlen(cie->augmentation) + 1; 673 p += strlen(cie->augmentation) + 1;
@@ -694,7 +697,7 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
694 count = dwarf_read_uleb128(p, &length); 697 count = dwarf_read_uleb128(p, &length);
695 p += count; 698 p += count;
696 699
697 BUG_ON((unsigned char *)p > end); 700 UNWINDER_BUG_ON((unsigned char *)p > end);
698 701
699 cie->initial_instructions = p + length; 702 cie->initial_instructions = p + length;
700 cie->augmentation++; 703 cie->augmentation++;
@@ -722,16 +725,16 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
722 * routine in the CIE 725 * routine in the CIE
723 * augmentation. 726 * augmentation.
724 */ 727 */
725 BUG(); 728 UNWINDER_BUG();
726 } else if (*cie->augmentation == 'S') { 729 } else if (*cie->augmentation == 'S') {
727 BUG(); 730 UNWINDER_BUG();
728 } else { 731 } else {
729 /* 732 /*
730 * Unknown augmentation. Assume 733 * Unknown augmentation. Assume
731 * 'z' augmentation. 734 * 'z' augmentation.
732 */ 735 */
733 p = cie->initial_instructions; 736 p = cie->initial_instructions;
734 BUG_ON(!p); 737 UNWINDER_BUG_ON(!p);
735 break; 738 break;
736 } 739 }
737 } 740 }
@@ -805,9 +808,11 @@ static int dwarf_parse_fde(void *entry, u32 entry_type,
805 return 0; 808 return 0;
806} 809}
807 810
808static void dwarf_unwinder_dump(struct task_struct *task, struct pt_regs *regs, 811static void dwarf_unwinder_dump(struct task_struct *task,
812 struct pt_regs *regs,
809 unsigned long *sp, 813 unsigned long *sp,
810 const struct stacktrace_ops *ops, void *data) 814 const struct stacktrace_ops *ops,
815 void *data)
811{ 816{
812 struct dwarf_frame *frame, *_frame; 817 struct dwarf_frame *frame, *_frame;
813 unsigned long return_addr; 818 unsigned long return_addr;
@@ -831,7 +836,6 @@ static void dwarf_unwinder_dump(struct task_struct *task, struct pt_regs *regs,
831 return_addr = frame->return_addr; 836 return_addr = frame->return_addr;
832 ops->address(data, return_addr, 1); 837 ops->address(data, return_addr, 1);
833 } 838 }
834
835} 839}
836 840
837static struct unwinder dwarf_unwinder = { 841static struct unwinder dwarf_unwinder = {