소스 검색

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>
Matt Fleming 15 년 전
부모
커밋
5580e9044d
2개의 변경된 파일14개의 추가작업 그리고 2개의 파일을 삭제
  1. 3 0
      arch/sh/include/asm/dwarf.h
  2. 11 2
      arch/sh/kernel/dwarf.c

+ 3 - 0
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)

+ 11 - 2
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, &reg);
 			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;