22
22
#include <asm/stacktrace.h>
23
23
#include <asm/unwind.h>
24
24
25
+ #define OPCODE_BUFSIZE 64
26
+
25
27
int panic_on_unrecovered_nmi ;
26
28
int panic_on_io_nmi ;
27
- static unsigned int code_bytes = 64 ;
28
29
static int die_counter ;
29
30
31
+ static struct pt_regs exec_summary_regs ;
32
+
30
33
bool in_task_stack (unsigned long * stack , struct task_struct * task ,
31
34
struct stack_info * info )
32
35
{
@@ -69,9 +72,62 @@ static void printk_stack_address(unsigned long address, int reliable,
69
72
printk ("%s %s%pB\n" , log_lvl , reliable ? "" : "? " , (void * )address );
70
73
}
71
74
75
+ /*
76
+ * There are a couple of reasons for the 2/3rd prologue, courtesy of Linus:
77
+ *
78
+ * In case where we don't have the exact kernel image (which, if we did, we can
79
+ * simply disassemble and navigate to the RIP), the purpose of the bigger
80
+ * prologue is to have more context and to be able to correlate the code from
81
+ * the different toolchains better.
82
+ *
83
+ * In addition, it helps in recreating the register allocation of the failing
84
+ * kernel and thus make sense of the register dump.
85
+ *
86
+ * What is more, the additional complication of a variable length insn arch like
87
+ * x86 warrants having longer byte sequence before rIP so that the disassembler
88
+ * can "sync" up properly and find instruction boundaries when decoding the
89
+ * opcode bytes.
90
+ *
91
+ * Thus, the 2/3rds prologue and 64 byte OPCODE_BUFSIZE is just a random
92
+ * guesstimate in attempt to achieve all of the above.
93
+ */
94
+ void show_opcodes (u8 * rip , const char * loglvl )
95
+ {
96
+ unsigned int code_prologue = OPCODE_BUFSIZE * 2 / 3 ;
97
+ u8 opcodes [OPCODE_BUFSIZE ];
98
+ u8 * ip ;
99
+ int i ;
100
+
101
+ printk ("%sCode: " , loglvl );
102
+
103
+ ip = (u8 * )rip - code_prologue ;
104
+ if (probe_kernel_read (opcodes , ip , OPCODE_BUFSIZE )) {
105
+ pr_cont ("Bad RIP value.\n" );
106
+ return ;
107
+ }
108
+
109
+ for (i = 0 ; i < OPCODE_BUFSIZE ; i ++ , ip ++ ) {
110
+ if (ip == rip )
111
+ pr_cont ("<%02x> " , opcodes [i ]);
112
+ else
113
+ pr_cont ("%02x " , opcodes [i ]);
114
+ }
115
+ pr_cont ("\n" );
116
+ }
117
+
118
+ void show_ip (struct pt_regs * regs , const char * loglvl )
119
+ {
120
+ #ifdef CONFIG_X86_32
121
+ printk ("%sEIP: %pS\n" , loglvl , (void * )regs -> ip );
122
+ #else
123
+ printk ("%sRIP: %04x:%pS\n" , loglvl , (int )regs -> cs , (void * )regs -> ip );
124
+ #endif
125
+ show_opcodes ((u8 * )regs -> ip , loglvl );
126
+ }
127
+
72
128
void show_iret_regs (struct pt_regs * regs )
73
129
{
74
- printk ( KERN_DEFAULT "RIP: %04x:%pS\n" , ( int ) regs -> cs , ( void * ) regs -> ip );
130
+ show_ip ( regs , KERN_DEFAULT );
75
131
printk (KERN_DEFAULT "RSP: %04x:%016lx EFLAGS: %08lx" , (int )regs -> ss ,
76
132
regs -> sp , regs -> flags );
77
133
}
@@ -267,7 +323,6 @@ unsigned long oops_begin(void)
267
323
bust_spinlocks (1 );
268
324
return flags ;
269
325
}
270
- EXPORT_SYMBOL_GPL (oops_begin );
271
326
NOKPROBE_SYMBOL (oops_begin );
272
327
273
328
void __noreturn rewind_stack_do_exit (int signr );
@@ -287,6 +342,9 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
287
342
raw_local_irq_restore (flags );
288
343
oops_exit ();
289
344
345
+ /* Executive summary in case the oops scrolled away */
346
+ __show_regs (& exec_summary_regs , true);
347
+
290
348
if (!signr )
291
349
return ;
292
350
if (in_interrupt ())
@@ -305,10 +363,10 @@ NOKPROBE_SYMBOL(oops_end);
305
363
306
364
int __die (const char * str , struct pt_regs * regs , long err )
307
365
{
308
- #ifdef CONFIG_X86_32
309
- unsigned short ss ;
310
- unsigned long sp ;
311
- #endif
366
+ /* Save the regs of the first oops for the executive summary later. */
367
+ if (! die_counter )
368
+ exec_summary_regs = * regs ;
369
+
312
370
printk (KERN_DEFAULT
313
371
"%s: %04lx [#%d]%s%s%s%s%s\n" , str , err & 0xffff , ++ die_counter ,
314
372
IS_ENABLED (CONFIG_PREEMPT ) ? " PREEMPT" : "" ,
@@ -318,26 +376,13 @@ int __die(const char *str, struct pt_regs *regs, long err)
318
376
IS_ENABLED (CONFIG_PAGE_TABLE_ISOLATION ) ?
319
377
(boot_cpu_has (X86_FEATURE_PTI ) ? " PTI" : " NOPTI" ) : "" );
320
378
379
+ show_regs (regs );
380
+ print_modules ();
381
+
321
382
if (notify_die (DIE_OOPS , str , regs , err ,
322
383
current -> thread .trap_nr , SIGSEGV ) == NOTIFY_STOP )
323
384
return 1 ;
324
385
325
- print_modules ();
326
- show_regs (regs );
327
- #ifdef CONFIG_X86_32
328
- if (user_mode (regs )) {
329
- sp = regs -> sp ;
330
- ss = regs -> ss ;
331
- } else {
332
- sp = kernel_stack_pointer (regs );
333
- savesegment (ss , ss );
334
- }
335
- printk (KERN_EMERG "EIP: %pS SS:ESP: %04x:%08lx\n" ,
336
- (void * )regs -> ip , ss , sp );
337
- #else
338
- /* Executive summary in case the oops scrolled away */
339
- printk (KERN_ALERT "RIP: %pS RSP: %016lx\n" , (void * )regs -> ip , regs -> sp );
340
- #endif
341
386
return 0 ;
342
387
}
343
388
NOKPROBE_SYMBOL (__die );
@@ -356,30 +401,9 @@ void die(const char *str, struct pt_regs *regs, long err)
356
401
oops_end (flags , regs , sig );
357
402
}
358
403
359
- static int __init code_bytes_setup (char * s )
360
- {
361
- ssize_t ret ;
362
- unsigned long val ;
363
-
364
- if (!s )
365
- return - EINVAL ;
366
-
367
- ret = kstrtoul (s , 0 , & val );
368
- if (ret )
369
- return ret ;
370
-
371
- code_bytes = val ;
372
- if (code_bytes > 8192 )
373
- code_bytes = 8192 ;
374
-
375
- return 1 ;
376
- }
377
- __setup ("code_bytes=" , code_bytes_setup );
378
-
379
404
void show_regs (struct pt_regs * regs )
380
405
{
381
406
bool all = true;
382
- int i ;
383
407
384
408
show_regs_print_info (KERN_DEFAULT );
385
409
@@ -389,36 +413,8 @@ void show_regs(struct pt_regs *regs)
389
413
__show_regs (regs , all );
390
414
391
415
/*
392
- * When in-kernel, we also print out the stack and code at the
393
- * time of the fault..
416
+ * When in-kernel, we also print out the stack at the time of the fault..
394
417
*/
395
- if (!user_mode (regs )) {
396
- unsigned int code_prologue = code_bytes * 43 / 64 ;
397
- unsigned int code_len = code_bytes ;
398
- unsigned char c ;
399
- u8 * ip ;
400
-
418
+ if (!user_mode (regs ))
401
419
show_trace_log_lvl (current , regs , NULL , KERN_DEFAULT );
402
-
403
- printk (KERN_DEFAULT "Code: " );
404
-
405
- ip = (u8 * )regs -> ip - code_prologue ;
406
- if (ip < (u8 * )PAGE_OFFSET || probe_kernel_address (ip , c )) {
407
- /* try starting at IP */
408
- ip = (u8 * )regs -> ip ;
409
- code_len = code_len - code_prologue + 1 ;
410
- }
411
- for (i = 0 ; i < code_len ; i ++ , ip ++ ) {
412
- if (ip < (u8 * )PAGE_OFFSET ||
413
- probe_kernel_address (ip , c )) {
414
- pr_cont (" Bad RIP value." );
415
- break ;
416
- }
417
- if (ip == (u8 * )regs -> ip )
418
- pr_cont ("<%02x> " , c );
419
- else
420
- pr_cont ("%02x " , c );
421
- }
422
- }
423
- pr_cont ("\n" );
424
420
}
0 commit comments