mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-11-27 01:11:31 +00:00
x86/dumpstack: Add get_stack_pointer() and get_frame_pointer()
The various functions involved in dumping the stack all do similar things with regard to getting the stack pointer and the frame pointer based on the regs and task arguments. Create helper functions to do that instead. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Reviewed-by: Andy Lutomirski <luto@kernel.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Brian Gerst <brgerst@gmail.com> Cc: Byungchul Park <byungchul.park@lge.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Nilay Vaish <nilayvaish@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/f448914885a35f333fe04da1b97a6c2cc1f80974.1472057064.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
d438f5fda3
commit
4b8afafbe7
4 changed files with 33 additions and 68 deletions
|
|
@ -50,36 +50,41 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
#define STACKSLOTS_PER_LINE 8
|
#define STACKSLOTS_PER_LINE 8
|
||||||
#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :)
|
|
||||||
#else
|
#else
|
||||||
#define STACKSLOTS_PER_LINE 4
|
#define STACKSLOTS_PER_LINE 4
|
||||||
#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_FRAME_POINTER
|
#ifdef CONFIG_FRAME_POINTER
|
||||||
static inline unsigned long
|
static inline unsigned long *
|
||||||
stack_frame(struct task_struct *task, struct pt_regs *regs)
|
get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
unsigned long bp;
|
|
||||||
|
|
||||||
if (regs)
|
if (regs)
|
||||||
return regs->bp;
|
return (unsigned long *)regs->bp;
|
||||||
|
|
||||||
if (task == current) {
|
if (!task || task == current)
|
||||||
/* Grab bp right from our regs */
|
return __builtin_frame_address(0);
|
||||||
get_bp(bp);
|
|
||||||
return bp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((struct inactive_task_frame *)task->thread.sp)->bp;
|
return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline unsigned long
|
static inline unsigned long *
|
||||||
stack_frame(struct task_struct *task, struct pt_regs *regs)
|
get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
return 0;
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FRAME_POINTER */
|
||||||
|
|
||||||
|
static inline unsigned long *
|
||||||
|
get_stack_pointer(struct task_struct *task, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
if (regs)
|
||||||
|
return (unsigned long *)kernel_stack_pointer(regs);
|
||||||
|
|
||||||
|
if (!task || task == current)
|
||||||
|
return __builtin_frame_address(0);
|
||||||
|
|
||||||
|
return (unsigned long *)task->thread.sp;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
||||||
|
|
@ -106,7 +111,7 @@ static inline unsigned long caller_frame_pointer(void)
|
||||||
{
|
{
|
||||||
struct stack_frame *frame;
|
struct stack_frame *frame;
|
||||||
|
|
||||||
get_bp(frame);
|
frame = __builtin_frame_address(0);
|
||||||
|
|
||||||
#ifdef CONFIG_FRAME_POINTER
|
#ifdef CONFIG_FRAME_POINTER
|
||||||
frame = frame->next_frame;
|
frame = frame->next_frame;
|
||||||
|
|
|
||||||
|
|
@ -170,15 +170,14 @@ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
||||||
void show_stack(struct task_struct *task, unsigned long *sp)
|
void show_stack(struct task_struct *task, unsigned long *sp)
|
||||||
{
|
{
|
||||||
unsigned long bp = 0;
|
unsigned long bp = 0;
|
||||||
unsigned long stack;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stack frames below this one aren't interesting. Don't show them
|
* Stack frames below this one aren't interesting. Don't show them
|
||||||
* if we're printing for %current.
|
* if we're printing for %current.
|
||||||
*/
|
*/
|
||||||
if (!sp && (!task || task == current)) {
|
if (!sp && (!task || task == current)) {
|
||||||
sp = &stack;
|
sp = get_stack_pointer(current, NULL);
|
||||||
bp = stack_frame(current, NULL);
|
bp = (unsigned long)get_frame_pointer(current, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
show_stack_log_lvl(task, NULL, sp, bp, "");
|
show_stack_log_lvl(task, NULL, sp, bp, "");
|
||||||
|
|
|
||||||
|
|
@ -46,19 +46,9 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
|
||||||
int graph = 0;
|
int graph = 0;
|
||||||
u32 *prev_esp;
|
u32 *prev_esp;
|
||||||
|
|
||||||
if (!task)
|
task = task ? : current;
|
||||||
task = current;
|
stack = stack ? : get_stack_pointer(task, regs);
|
||||||
|
bp = bp ? : (unsigned long)get_frame_pointer(task, regs);
|
||||||
if (!stack) {
|
|
||||||
unsigned long dummy;
|
|
||||||
|
|
||||||
stack = &dummy;
|
|
||||||
if (task != current)
|
|
||||||
stack = (unsigned long *)task->thread.sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bp)
|
|
||||||
bp = stack_frame(task, regs);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
void *end_stack;
|
void *end_stack;
|
||||||
|
|
@ -95,14 +85,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
||||||
unsigned long *stack;
|
unsigned long *stack;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (sp == NULL) {
|
sp = sp ? : get_stack_pointer(task, regs);
|
||||||
if (regs)
|
|
||||||
sp = (unsigned long *)regs->sp;
|
|
||||||
else if (task)
|
|
||||||
sp = (unsigned long *)task->thread.sp;
|
|
||||||
else
|
|
||||||
sp = (unsigned long *)&sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
stack = sp;
|
stack = sp;
|
||||||
for (i = 0; i < kstack_depth_to_print; i++) {
|
for (i = 0; i < kstack_depth_to_print; i++) {
|
||||||
|
|
|
||||||
|
|
@ -151,25 +151,14 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
|
||||||
{
|
{
|
||||||
const unsigned cpu = get_cpu();
|
const unsigned cpu = get_cpu();
|
||||||
unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
|
unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
|
||||||
unsigned long dummy;
|
|
||||||
unsigned used = 0;
|
unsigned used = 0;
|
||||||
int graph = 0;
|
int graph = 0;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
if (!task)
|
task = task ? : current;
|
||||||
task = current;
|
stack = stack ? : get_stack_pointer(task, regs);
|
||||||
|
bp = bp ? : (unsigned long)get_frame_pointer(task, regs);
|
||||||
|
|
||||||
if (!stack) {
|
|
||||||
if (regs)
|
|
||||||
stack = (unsigned long *)regs->sp;
|
|
||||||
else if (task != current)
|
|
||||||
stack = (unsigned long *)task->thread.sp;
|
|
||||||
else
|
|
||||||
stack = &dummy;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bp)
|
|
||||||
bp = stack_frame(task, regs);
|
|
||||||
/*
|
/*
|
||||||
* Print function call entries in all stacks, starting at the
|
* Print function call entries in all stacks, starting at the
|
||||||
* current stack address. If the stacks consist of nested
|
* current stack address. If the stacks consist of nested
|
||||||
|
|
@ -256,18 +245,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
||||||
irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
|
irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
|
||||||
irq_stack = irq_stack_end - (IRQ_STACK_SIZE / sizeof(long));
|
irq_stack = irq_stack_end - (IRQ_STACK_SIZE / sizeof(long));
|
||||||
|
|
||||||
/*
|
sp = sp ? : get_stack_pointer(task, regs);
|
||||||
* Debugging aid: "show_stack(NULL, NULL);" prints the
|
|
||||||
* back trace for this cpu:
|
|
||||||
*/
|
|
||||||
if (sp == NULL) {
|
|
||||||
if (regs)
|
|
||||||
sp = (unsigned long *)regs->sp;
|
|
||||||
else if (task)
|
|
||||||
sp = (unsigned long *)task->thread.sp;
|
|
||||||
else
|
|
||||||
sp = (unsigned long *)&sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
stack = sp;
|
stack = sp;
|
||||||
for (i = 0; i < kstack_depth_to_print; i++) {
|
for (i = 0; i < kstack_depth_to_print; i++) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue