📄 oops.c
字号:
addr_t reg; char regname[7]; char **string = NULL; static const char procname[] = "Oops_set_s390_regs"; /* Loop over s390 unbracketed register values. No keywords so we have to * synthesize the register numbers ourselves, yuck! */ while (1) { if (regexec(&re_unbracketed_address, p, re_unbracketed_address.re_nsub+1, re_unbracketed_address_pmatch, 0) == 0) { re_strings(&re_unbracketed_address, p, re_unbracketed_address_pmatch, &string); reg = hexstring(string[1]); /* contents */ if (errno) { ERROR(" Invalid hex value in s390 register line, ignored - '%s'", string[1]); perror(prefix); reg = 0; } reg = Oops_truncate_address(reg, options); strcpy(regname, ">>"); snprintf(regname, sizeof(regname), "r%-2d; ", s390_reg_num); add_symbol_n(ss, reg, 'R', 1, regname); p += re_unbracketed_address_pmatch[0].rm_eo; ++s390_reg_num; } else break; } if (*p) WARNING("garbage '%s' at end of s390 register line ignored", p); re_strings_free(&re_unbracketed_address, &string);}/* Do pattern matching to decide if the line should be printed. When reading a * syslog containing multiple Oops, you need the intermediate data (registers, * tss etc.) to go with the decoded text. Sets text to the start of the useful * text, after any prefix. Note that any leading white space is treated as part * of the prefix, later routines do not see any indentation. * * Note: If a line is not printed, it will not be scanned for any other text. */#ifdef TIME_RE/* time the re code */#include <sys/time.h>struct timeval before, after;long long diff[30];int count[30];#define START gettimeofday(&before, NULL);#define DIFF(n) gettimeofday(&after, NULL); \ ++count[n]; \ diff[n] += (after.tv_sec - before.tv_sec)*1000001 + (after.tv_usec - before.tv_usec); \ before = after;#else#define START#define DIFF(n)#endifstatic int Oops_print(const char *line, const char **text, char ***string, int string_max){ int i, print = 0; static int stack_line = 0, trace_line = 0; static regex_t re_Oops_prefix; static regmatch_t *re_Oops_prefix_pmatch; static regex_t re_Oops_print_s; static regmatch_t *re_Oops_print_s_pmatch; static regex_t re_Oops_print_a; static regmatch_t *re_Oops_print_a_pmatch; static const char procname[] = "Oops_print"; START *text = line; /* Lines to be ignored. For some reason the "amuse the user" print in * some die_if_kernel routines causes regexec to run very slowly. */ if (strstr(*text, "\\|/ ____ \\|/") || strstr(*text, "\"@'/ ,. \\`@\"") || strstr(*text, "\"@'/ .. \\`@\"") || strstr(*text, "/_| \\__/ |_\\") || strstr(*text, " \\__U_/")) return(1); /* print but avoid regexec */ DIFF(1); /* Trial and error with regex leads me to the following conclusions. * * regex does not like a lot of sub patterns that start with "^". So split * the patterns into two groups, one set must appear at the start of the * line, the other set can appear anywhere. * * Lots of bracketed subexpressions really slows regex down. Only use * brackets where absolutely necessary. Examples are where you want to * extract matching substrings such as stack, call trace etc. Or where * you have suboptions within a string, like the sparc die_if_kernel text. * Otherwise omit brackets, except that every re should have at least one * bracketed expression, that is how RE_COMPILE tells if the expression * has already been compiled. */ /* Prefixes to be ignored. These prefixes were originally done as * ^((pattern1)|(pattern2)|(pattern3))+ but that caused pathological * behaviour in regexec when faced with lines like * : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) * Would you believe 11 seconds just to resolve that one line :(. So just * look for one prefix at a time and loop until all prefixes are stripped. */ RE_COMPILE(&re_Oops_prefix, "^(" /* start of line */ " +" /* leading spaces */ "|[^ ]{3} [ 0-9][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} " "[^ ]+( kernel:)? +" /* syslogd, syslog-ng */ "|<[0-9]+>" /* kmsg */ "|[0-9]+\\|[^|]+\\|[^|]+\\|[^|]+\\|" /* syslog-ng */ "|[0-9][AC] [0-9]{3} [0-9]{3}[cir][0-9]{2}:" /* SNIA */ "\\+" /* leading '+' */ ")", REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_prefix_pmatch); do { i = regexec(&re_Oops_prefix, *text, re_Oops_prefix.re_nsub+1, re_Oops_prefix_pmatch, 0); DEBUG(4, "regexec prefix %d", i); if (i == 0) *text += re_Oops_prefix_pmatch[0].rm_eo; /* step over prefix */ } while (i == 0); DIFF(2); /* Lots of possibilities. Expand as required for all architectures. */ /* These patterns must appear at the start of the line, after stripping * the prefix above. * * The order below is required to handle multiline outupt. * string 2 is defined if the text is 'Stack from '. * string 3 is defined if the text is 'Stack: '. * string 4 is defined if the text might be a stack continuation. * string 5 is defined if the text is 'Call Trace: *'. * string 6 is defined if the text might be a trace continuation. * string 7 is the address part of the BRACKETED_ADDRESS. * * string 8 is defined if the text contains a version number. No Oops * report contains this as of 2.1.125 but IMHO it should be added. If * anybody wants to print a VERSION_nnnn line in their Oops, this code * is ready. * * string 9 is defined if the text is 'Trace:' (alpha). * string 10 is defined if the text is 'Call backtrace:' (ppc, i370). * string 11 is defined if the text is 'bh:' (i386). Stack addresses are * on the next line. In our typical inconsistent manner, the bh: stack * addresses are different from every other address, they are <[...]> * instead of [<...>] so define yet another re, string 12. Sigh. * * The ikd patch adds "(nn)" for the stack frame size after each trace * entry, it should appear on the same line as the bracketed address. Alas * users have been known to split lines so "(nn)" appears at the start of * the continuation line, look for that as well. Life would be so much * easier without users. Andi Kleen's multi cpu traceback patch adds the * module name as "(name)" after addresses. Strings 13 and 14 are * a special case of strings 6 and 7 to handle "(nn)" and "(name)", * in fact anything in "()" between addresses is ignored. * * Both ppc and i370 use 'Call backtrace:' but the i370 data is completely * different from anything else. It starts on a separate line and consists * of multiple lines, each containing a number (trace depth), base=, link=, * stack=. * * s390 decided to do their own thing instead of using the same format as * i370. A bad case of "not invented here". s390 data starts on a separate * line and consists of multiple addresses. * * The SGI kdb backtrace for ix86 prints EBP and EIP, one per line after the * header. * * Some strings indicate stack data (S), some indicate trace data (T). */ RE_COMPILE(&re_Oops_print_s, /* arch type */ /* Required order */ "^(" /* 1 */ /* i386 */ "(Stack: )" /* 2 S */ /* m68k */ "|(Stack from )" /* 3 S */ /* various */ "|([0-9a-fA-F]{4,})" /* 4 S,T */ /* various */ "|(Call Trace: *)" /* 5 T */ /* various */ "|(" BRACKETED_ADDRESS ")" /* 6,7 T */ /* various */ "|(Version_[0-9]+)" /* 8 */ /* alpha */ "|(Trace:)" /* 9 T */ /* ppc, i370 */ "|(Call backtrace:)" /* 10 T */ /* i386 */ "|(bh:)" /* 11 T */ /* i386 */ "|" REVBRACKETED_ADDRESS /* 12 T */ /* ikd/AK */ "|(\\([^ ]+\\) *" /* 13 T */ BRACKETED_ADDRESS ")" /* 14 */ /* i370 */ "|([0-9]+ +base=)" /* 15 T */ /* s390 */ "|(Kernel BackChain)" /* 16 T */ /* kdb ix86 */ "|EBP *EIP" /* 17 T */ /* kdb ix86 */ "|0x" UNBRACKETED_ADDRESS "0x" UNBRACKETED_ADDRESS /* 18, 19 T */ /* order does not matter from here on */ /* various */ "|Process .*stackpage=" /* various */ "|Code *: " /* various */ "|Kernel panic" /* various */ "|In swapper task" /* various */ "|kmem_free" /* various */ "|swapper" /* various */ "|Pid:" /* various */ "|r[0-9]{1,2} *[:=]" /* generic register dump */ /* i386 2.0 */ "|Corrupted stack page" /* i386 */ "|invalid operand: " /* i386 */ "|Oops: " /* i386 */ "|Cpu:* +[0-9]" /* i386 */ "|current->tss" /* i386 */ "|\\*pde +=" /* i386 */ "|EIP: " /* i386 */ "|EFLAGS: " /* i386 */ "|eax: " /* i386 */ "|esi: " /* i386 */ "|ds: " /* i386 */ "|CR0: " /* i386 */ "|wait_on_" /* i386 */ "|irq: " /* i386 */ "|Stack dumps:" /* x86_64 */ "|RAX: " /* x86_64 */ "|RSP: " /* x86_64 */ "|RIP: " /* x86_64 */ "|RDX: " /* x86_64 */ "|RBP: " /* x86_64 */ "|FS: " /* x86_64 */ "|CS: " /* x86_64 */ "|CR2: " /* x86_64 */ "|PML4" /* m68k */ "|pc[:=]" /* m68k */ "|68060 access" /* m68k */ "|Exception at " /* m68k */ "|d[04]: " /* m68k */ "|Frame format=" /* m68k */ "|wb [0-9] stat" /* m68k */ "|push data: " /* m68k */ "|baddr=" /* any other m68K lines to print? */ /* alpha */ "|Arithmetic fault" /* alpha */ "|Instruction fault" /* alpha */ "|Bad unaligned kernel" /* alpha */ "|Forwarding unaligned exception" /* alpha */ "|: unhandled unaligned exception" /* alpha */ "|pc *=" /* alpha */ "|[rvtsa][0-9]+ *=" /* Changed from r to [vtsa] in 2.2.14 */ /* alpha */ "|gp *=" /* alpha */ "|spinlock stuck" /* any other alpha lines to print? */ /* sparc */ "|tsk->" /* sparc */ "|PSR: " /* sparc */ "|[goli]0: " /* sparc */ "|Instruction DUMP: " /* sparc */ "|spin_lock" /* any other sparc lines to print? */ /* sparc64 */ "|TSTATE: " /* sparc64 */ "|[goli]4: " /* sparc64 */ "|Caller\\[" /* sparc64 */ "|CPU\\[" /* any other sparc64 lines to print? */ /* ppc */ "|MSR: " /* ppc */ "|TASK = " /* ppc */ "|last math " /* ppc */ "|GPR[0-9]+: " /* any other ppc lines to print? */ /* mips */ "|.* in .*\\.[ch]:.*, line [0-9]+:" /* mips */ "|\\$[0-9 ]+:" /* mips */ "|Hi *:" /* mips */ "|Lo *:" /* mips */ "|epc *:" /* mips */ "|badvaddr *:" /* mips */ "|Status *:" /* mips */ "|Cause *:" /* any other mips lines to print? */ /* arm */ "|Backtrace:" /* arm */ "|Function entered at" /* arm */ "|\\*pgd =" /* arm */ "|Internal error" /* arm */ "|pc :" /* arm */ "|sp :" /* arm */ "|Flags:" /* arm */ "|Control:" /* any other arm lines to print? */ /* ikd patch */ "|WARNING:" /* ikd patch */ "|this_stack:" /* ikd patch */ "|i:" /* any other ikd lines to print? */ /* i370 */ "|PSW" /* i370 */ "|cr[0-9]+:" /* i370 */ "|machine check" /* i370 */ "|Exception in " /* i370 */ "|Program Check " /* i370 */ "|System restart " /* i370 */ "|IUCV " /* i370 */ "|unexpected external " /* i370 */ "|Kernel stack " /* any other i370 lines to print? */ /* s390 */ "|User process fault:" /* s390 */ "|failing address" /* s390 */ "|User PSW" /* s390 */ "|User GPRS" /* s390 */ "|User ACRS" /* s390 */ "|Kernel PSW" /* s390 */ "|Kernel GPRS" /* s390 */ "|Kernel ACRS" /* s390 */ "|illegal operation" /* s390 */ "|task:" /* any other s390 lines to print? */ /* SGI kdb */ "|Entering kdb" /* SGI kdb */ "|eax *=" /* SGI kdb */ "|esi *=" /* SGI kdb */ "|ebp *=" /* SGI kdb */ "|ds *=" /* any other SGI kdb lines to print? */ /* ia64 */ "|psr " /* ia64 */ "|unat " /* ia64 */ "|rnat " /* ia64 */ "|ldrs " /* ia64 */ "|xip " /* ia64 */ "|iip " /* ia64 */ "|ipsr " /* ia64 */ "|ifa " /* ia64 */ "|pr " /* ia64 */ "|itc " /* ia64 */ "|ifs " /* ia64 */ "|bsp " /* ia64 */ "|[bfr][0-9]+ " /* ia64 */ "|irr[0-9] " /* ia64 */ "|General Exception" /* ia64 */ "|MCA" /* ia64 */ "|SAL" /* ia64 */ "|Processor State" /* ia64 */ "|Bank [0-9]+" /* ia64 */ "|Register Stack" /* ia64 */ "|Processor Error Info" /* ia64 */ "|proc err map" /* ia64 */ "|proc state param" /* ia64 */ "|proc lid" /* ia64 */ "|processor structure" /* ia64 */ "|check info" /* ia64 */ "|target identifier" /* any other ia64 lines to print? */ /* CRIS */ "|IRP *: " /* any other cris lines to print? */ ")", REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_print_s_pmatch); i = regexec(&re_Oops_print_s, *text, re_Oops_print_s.re_nsub+1, re_Oops_print_s_pmatch, 0); DEBUG(4, "regexec start %d", i); DIFF(3); print = 0;#undef MATCHED#define MATCHED(n) (re_Oops_print_s_pmatch[n].rm_so != -1) DIFF(4); /* Handle multiline messages, messy. Only treat strings that look like * addresses as useful when they immediately follow a definite stack or * trace header or a previously valid stack or trace line. * Because of the horribly ambiguous s390 register dump, unbracketed * addresses (string 4) can now be either stack or trace. How not to design * dump output. */ /* Stack lines */ if (!MATCHED(2) && !MATCHED(3) && !MATCHED(4)) stack_line = 0; else if (MATCHED(2) || MATCHED(3)) stack_line = 1; else if (stack_line && !MATCHED(4)) stack_line = 0; /* Trace lines */ if (!MATCHED(4) && !MATCHED(5) && !MATCHED(6) && !MATCHED(9) && !MATCHED(10) && !MATCHED(11) && !MATCHED(12) && !MATCHED(13) && !MATCHED(15) && !MATCHED(16) && !MATCHED(17) && !MATCHED(19)) trace_line = 0; else if (MATCHED(4) || MATCHED(5) || MATCHED(9) || MATCHED(10) || MATCHED(11) || MATCHED(15) || MATCHED(16) || MATCHED(17)) trace_line = 1; else if (trace_line && !MATCHED(4) && !MATCHED(6) && !MATCHED(12) && !MATCHED(13) && !MATCH
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -