Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47ad7b9b authored by Chris Metcalf's avatar Chris Metcalf
Browse files

tile: improve stack backtrace



This commit fixes a number of issues with the tile backtrace code.

- Don't try to identify userspace shared object or executable paths
  if we are doing a backtrace from an interrupt; it's not legal,
  and also unlikely to be interesting.  Likewise, don't try to do
  it for other address spaces, since d_path() assumes it is being
  called in "current" context.

- Move "in_backtrace" from thread_struct to thread_info.
  This way we can access it even if our stack thread_info has been
  clobbered, which makes backtracing more robust.

- Avoid using "current" directly when testing for is_sigreturn().
  Since "current" may be corrupt, we're better off using kbt->task
  explicitly to look up the vdso_base for the current task.
  Conveniently, this simplifies the internal APIs (we only need
  one is_sigreturn() function now).

- Avoid bogus "Odd fault" warning when pc/sp/ex1 are all zero,
  as is true for kernel threads above the last frame.

- Hook into Tejun Heo's dump_stack() framework in lib/dump_stack.c.

- Write last entry in save_stack_trace() as ULONG_MAX, not zero,
  since ftrace (at least) relies on finding that marker.

- Implement save_stack_trace_regs() and save_strack_trace_user(),
  and set CONFIG_USER_STACKTRACE_SUPPORT.

Signed-off-by: default avatarChris Metcalf <cmetcalf@ezchip.com>
parent e8200baa
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ config TILE
	select MODULES_USE_ELF_RELA
	select MODULES_USE_ELF_RELA
	select HAVE_ARCH_TRACEHOOK
	select HAVE_ARCH_TRACEHOOK
	select HAVE_SYSCALL_TRACEPOINTS
	select HAVE_SYSCALL_TRACEPOINTS
	select USER_STACKTRACE_SUPPORT
	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
	select HAVE_DEBUG_STACKOVERFLOW
	select HAVE_DEBUG_STACKOVERFLOW
	select ARCH_WANT_FRAME_POINTERS
	select ARCH_WANT_FRAME_POINTERS
+0 −2
Original line number Original line Diff line number Diff line
@@ -111,8 +111,6 @@ struct thread_struct {
	unsigned long long interrupt_mask;
	unsigned long long interrupt_mask;
	/* User interrupt-control 0 state */
	/* User interrupt-control 0 state */
	unsigned long intctrl_0;
	unsigned long intctrl_0;
	/* Is this task currently doing a backtrace? */
	bool in_backtrace;
	/* Any other miscellaneous processor state bits */
	/* Any other miscellaneous processor state bits */
	unsigned long proc_status;
	unsigned long proc_status;
#if !CHIP_HAS_FIXED_INTVEC_BASE()
#if !CHIP_HAS_FIXED_INTVEC_BASE()
+5 −8
Original line number Original line Diff line number Diff line
@@ -58,17 +58,14 @@ extern int KBacktraceIterator_end(struct KBacktraceIterator *kbt);
/* Advance to the next frame. */
/* Advance to the next frame. */
extern void KBacktraceIterator_next(struct KBacktraceIterator *kbt);
extern void KBacktraceIterator_next(struct KBacktraceIterator *kbt);


/* Dump just the contents of the pt_regs structure. */
extern void tile_show_regs(struct pt_regs *);

/*
/*
 * Dump stack given complete register info. Use only from the
 * Dump stack given complete register info. Use only from the
 * architecture-specific code; show_stack()
 * architecture-specific code; show_stack()
 * and dump_stack() (in entry.S) are architecture-independent entry points.
 * and dump_stack() are architecture-independent entry points.
 */
 */
extern void tile_show_stack(struct KBacktraceIterator *, int headers);
extern void tile_show_stack(struct KBacktraceIterator *);

/* Dump stack of current process, with registers to seed the backtrace. */
extern void dump_stack_regs(struct pt_regs *);

/* Helper method for assembly dump_stack(). */
extern void _dump_stack(int dummy, ulong pc, ulong lr, ulong sp, ulong r52);


#endif /* _ASM_TILE_STACK_H */
#endif /* _ASM_TILE_STACK_H */
+1 −0
Original line number Original line Diff line number Diff line
@@ -42,6 +42,7 @@ struct thread_info {
	unsigned long		unalign_jit_tmp[4]; /* temp r0..r3 storage */
	unsigned long		unalign_jit_tmp[4]; /* temp r0..r3 storage */
	void __user		*unalign_jit_base; /* unalign fixup JIT base */
	void __user		*unalign_jit_base; /* unalign fixup JIT base */
#endif
#endif
	bool in_backtrace;			/* currently doing backtrace? */
};
};


/*
/*
+0 −7
Original line number Original line Diff line number Diff line
@@ -27,13 +27,6 @@ STD_ENTRY(current_text_addr)
	{ move r0, lr; jrp lr }
	{ move r0, lr; jrp lr }
	STD_ENDPROC(current_text_addr)
	STD_ENDPROC(current_text_addr)


STD_ENTRY(dump_stack)
	{ move r2, lr; lnk r1 }
	{ move r4, r52; addli r1, r1, dump_stack - . }
	{ move r3, sp; j _dump_stack }
	jrp lr   /* keep backtracer happy */
	STD_ENDPROC(dump_stack)

STD_ENTRY(KBacktraceIterator_init_current)
STD_ENTRY(KBacktraceIterator_init_current)
	{ move r2, lr; lnk r1 }
	{ move r2, lr; lnk r1 }
	{ move r4, r52; addli r1, r1, KBacktraceIterator_init_current - . }
	{ move r4, r52; addli r1, r1, KBacktraceIterator_init_current - . }
Loading