diff options
Diffstat (limited to 'arch/x86/kernel/dumpstack.c')
| -rw-r--r-- | arch/x86/kernel/dumpstack.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 5fa110699ed2..d0bb176a7261 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
| @@ -76,12 +76,23 @@ void show_iret_regs(struct pt_regs *regs) | |||
| 76 | regs->sp, regs->flags); | 76 | regs->sp, regs->flags); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | static void show_regs_safe(struct stack_info *info, struct pt_regs *regs) | 79 | static void show_regs_if_on_stack(struct stack_info *info, struct pt_regs *regs, |
| 80 | bool partial) | ||
| 80 | { | 81 | { |
| 81 | if (on_stack(info, regs, sizeof(*regs))) | 82 | /* |
| 83 | * These on_stack() checks aren't strictly necessary: the unwind code | ||
| 84 | * has already validated the 'regs' pointer. The checks are done for | ||
| 85 | * ordering reasons: if the registers are on the next stack, we don't | ||
| 86 | * want to print them out yet. Otherwise they'll be shown as part of | ||
| 87 | * the wrong stack. Later, when show_trace_log_lvl() switches to the | ||
| 88 | * next stack, this function will be called again with the same regs so | ||
| 89 | * they can be printed in the right context. | ||
| 90 | */ | ||
| 91 | if (!partial && on_stack(info, regs, sizeof(*regs))) { | ||
| 82 | __show_regs(regs, 0); | 92 | __show_regs(regs, 0); |
| 83 | else if (on_stack(info, (void *)regs + IRET_FRAME_OFFSET, | 93 | |
| 84 | IRET_FRAME_SIZE)) { | 94 | } else if (partial && on_stack(info, (void *)regs + IRET_FRAME_OFFSET, |
| 95 | IRET_FRAME_SIZE)) { | ||
| 85 | /* | 96 | /* |
| 86 | * When an interrupt or exception occurs in entry code, the | 97 | * When an interrupt or exception occurs in entry code, the |
| 87 | * full pt_regs might not have been saved yet. In that case | 98 | * full pt_regs might not have been saved yet. In that case |
| @@ -98,6 +109,7 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
| 98 | struct stack_info stack_info = {0}; | 109 | struct stack_info stack_info = {0}; |
| 99 | unsigned long visit_mask = 0; | 110 | unsigned long visit_mask = 0; |
| 100 | int graph_idx = 0; | 111 | int graph_idx = 0; |
| 112 | bool partial; | ||
| 101 | 113 | ||
| 102 | printk("%sCall Trace:\n", log_lvl); | 114 | printk("%sCall Trace:\n", log_lvl); |
| 103 | 115 | ||
| @@ -140,7 +152,7 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
| 140 | printk("%s <%s>\n", log_lvl, stack_name); | 152 | printk("%s <%s>\n", log_lvl, stack_name); |
| 141 | 153 | ||
| 142 | if (regs) | 154 | if (regs) |
| 143 | show_regs_safe(&stack_info, regs); | 155 | show_regs_if_on_stack(&stack_info, regs, partial); |
| 144 | 156 | ||
| 145 | /* | 157 | /* |
| 146 | * Scan the stack, printing any text addresses we find. At the | 158 | * Scan the stack, printing any text addresses we find. At the |
| @@ -164,7 +176,7 @@ void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
| 164 | 176 | ||
| 165 | /* | 177 | /* |
| 166 | * Don't print regs->ip again if it was already printed | 178 | * Don't print regs->ip again if it was already printed |
| 167 | * by show_regs_safe() below. | 179 | * by show_regs_if_on_stack(). |
| 168 | */ | 180 | */ |
| 169 | if (regs && stack == ®s->ip) | 181 | if (regs && stack == ®s->ip) |
| 170 | goto next; | 182 | goto next; |
| @@ -199,9 +211,9 @@ next: | |||
| 199 | unwind_next_frame(&state); | 211 | unwind_next_frame(&state); |
| 200 | 212 | ||
| 201 | /* if the frame has entry regs, print them */ | 213 | /* if the frame has entry regs, print them */ |
| 202 | regs = unwind_get_entry_regs(&state); | 214 | regs = unwind_get_entry_regs(&state, &partial); |
| 203 | if (regs) | 215 | if (regs) |
| 204 | show_regs_safe(&stack_info, regs); | 216 | show_regs_if_on_stack(&stack_info, regs, partial); |
| 205 | } | 217 | } |
| 206 | 218 | ||
| 207 | if (stack_name) | 219 | if (stack_name) |
