📄 oops.c
字号:
"|Instruction DUMP: " "|Caller\\[" ")", REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_sparc_regdump_pmatch); i = regexec(&re_Oops_sparc_regdump, line, re_Oops_sparc_regdump.re_nsub+1, re_Oops_sparc_regdump_pmatch, 0); DEBUG(4, "regexec %d", i); if (i == 0) return 1; return 0;}/* Look for the i370 PSW line, returns start of the relevant hex value */static char *Oops_i370_psw(const char *line, char ***string, int string_max){ int i; static regex_t re_Oops_i370_psw; static regmatch_t *re_Oops_i370_psw_pmatch; static const char procname[] = "Oops_i370_psw"; /* Oops 'PSW:' line for i370, PSW at start of line, value is second * address. */ RE_COMPILE(&re_Oops_i370_psw, "^PSW *flags: *" UNBRACKETED_ADDRESS /* flags */ " *PSW addr: *" UNBRACKETED_ADDRESS, REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_i370_psw_pmatch); i = regexec(&re_Oops_i370_psw, line, re_Oops_i370_psw.re_nsub+1, re_Oops_i370_psw_pmatch, 0); DEBUG(4, "regexec %d", i); if (i == 0) { re_string_check(re_Oops_i370_psw.re_nsub+1, string_max, procname); re_strings(&re_Oops_i370_psw, line, re_Oops_i370_psw_pmatch, string); return((*string)[re_Oops_i370_psw.re_nsub]); } return(NULL);}/* Set the i370 PSW from the PSW line */static void Oops_set_i370_psw(const char *value, SYMBOL_SET *ss, const char *me, const bfd *ibfd, OPTIONS *options){ static const char procname[] = "Oops_set_i370_psw"; addr_t PSW; /* Ensure target is set so EIP text is correct */ Oops_set_default_ta(me, ibfd, options); PSW = hexstring(value); if (errno) { ERROR(" Invalid hex value in PSW line, ignored - '%s'", value); perror(prefix); PSW = 0; } PSW = Oops_truncate_address(PSW, options); add_symbol_n(ss, PSW, 'E', 1, ">>PSW;");}/* Look for the s390 PSW line, returns start of the relevant hex value */static char *Oops_s390_psw(const char *line, char ***string, int string_max){ int i; static regex_t re_Oops_s390_psw; static regmatch_t *re_Oops_s390_psw_pmatch; static const char procname[] = "Oops_s390_psw"; /* Oops 'Kernel PSW:' line for s390, PSW at start of line, value is * second address. */ RE_COMPILE(&re_Oops_s390_psw, "^Kernel PSW: *" UNBRACKETED_ADDRESS /* flags */ UNBRACKETED_ADDRESS, REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_s390_psw_pmatch); i = regexec(&re_Oops_s390_psw, line, re_Oops_s390_psw.re_nsub+1, re_Oops_s390_psw_pmatch, 0); DEBUG(4, "regexec %d", i); if (i == 0) { re_string_check(re_Oops_s390_psw.re_nsub+1, string_max, procname); re_strings(&re_Oops_s390_psw, line, re_Oops_s390_psw_pmatch, string); return((*string)[re_Oops_s390_psw.re_nsub]); } return(NULL);}/* No need for Oops_set_s390_psw, can use Oops_set_i370_psw for both */#define Oops_set_s390_psw(line, string, me, ibfd, options) \ Oops_set_i370_psw(line, string, me, ibfd, options)/* Extract ppc registers. */static void Oops_ppc_regs(const char *line, SYMBOL_SET *ss, const OPTIONS *options){ int i, reg_num; addr_t reg; char regname[9]; char **string = NULL; const char *p; static regex_t re_Oops_ppc_regs; static regmatch_t *re_Oops_ppc_regs_pmatch; static const char procname[] = "Oops_ppc_regs"; RE_COMPILE(&re_Oops_ppc_regs, "^(GPR[0-9]{1,2}) *: *" /* 1 */ UNBRACKETED_ADDRESS /* 2 */ , REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_ppc_regs_pmatch); i = regexec(&re_Oops_ppc_regs, line, re_Oops_ppc_regs.re_nsub+1, re_Oops_ppc_regs_pmatch, 0); DEBUG(4, "regexec %d", i); if (i) return; p = line + re_Oops_ppc_regs_pmatch[0].rm_so + 3; reg_num = strtoul(p, NULL, 10); p = line + re_Oops_ppc_regs_pmatch[2].rm_so; /* Loop over unbracketed addresses */ 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 register line, ignored - '%s'", string[1]); perror(prefix); break; } reg = Oops_truncate_address(reg, options); snprintf(regname, sizeof(regname), ">>GPR%d;", reg_num); add_symbol_n(ss, reg, 'R', 1, regname); p += re_unbracketed_address_pmatch[0].rm_eo; ++reg_num; } else break; } if (*p) WARNING("garbage '%s' at end of ppc register line ignored", p); re_strings_free(&re_unbracketed_address, &string);}/* Look for the Trace multilines :(. Returns start of addresses. */static const char *Oops_trace(const char *line){ int i; const char *start = NULL; static int trace_line = 0; static regex_t re_Oops_trace; static regmatch_t *re_Oops_trace_pmatch; static const char procname[] = "Oops_trace"; /* Oops 'Trace' lines. 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. * The person who did the s390 trace obviously did not like any of the ways * that other Linux kernels report problems so they invented a system all on * their own. It is different from the i370 trace and even more ambiguous * than the other trace formats. That is what happens when code is written * in secret! */ RE_COMPILE(&re_Oops_trace, "^(" /* 1 */ "(Call Trace: *)" /* 2 */ /* alpha */ "|(Trace:)" /* 3 */ /* various */ "|(" BRACKETED_ADDRESS ")" /* 4,5 */ /* ppc */ "|(Call backtrace:)" /* 6 */ /* ppc, s390 */ "|" UNBRACKETED_ADDRESS /* 7 */ /* arm */ "|Function entered at (" BRACKETED_ADDRESS ")" /* 8,9 */ /* sparc64 */ "|Caller\\[" UNBRACKETED_ADDRESS "\\]" /* 10 */ /* i386 */ "|(" REVBRACKETED_ADDRESS ")" /* 11,12 */ /* ikd patch */ "|(\\([0-9]+\\) *(" BRACKETED_ADDRESS "))" /* 13,14,15 */ /* i370 */ "|([0-9]+ +base=0x" UNBRACKETED_ADDRESS ")" /* 16,17 */ /* s390 */ "|(Kernel BackChain.*)" /* 18 */ ")", REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_trace_pmatch); i = regexec(&re_Oops_trace, line, re_Oops_trace.re_nsub+1, re_Oops_trace_pmatch, 0); DEBUG(4, "regexec %d", i); if (i == 0) {#undef MATCHED#define MATCHED(n) (re_Oops_trace_pmatch[n].rm_so != -1) if (MATCHED(2) || MATCHED(3)) { /* Most start lines */ trace_line = 1; start = line + re_Oops_trace_pmatch[0].rm_eo; } else if (MATCHED(6)) { /* ppc start line, not a bracketed address, just an address */ trace_line = 2; /* ppc */ start = line + re_Oops_trace_pmatch[0].rm_eo; } else if (MATCHED(8)) { /* arm only line, two bracketed addresses on each line */ trace_line = 3; start = line + re_Oops_trace_pmatch[8].rm_so; } else if (MATCHED(10)) { /* sparc64 only line, one unbracketed address */ trace_line = 3; start = line + re_Oops_trace_pmatch[10].rm_so; } else if (MATCHED(17)) { /* i370 only line, one unbracketed address */ trace_line = 3; start = line + re_Oops_trace_pmatch[17].rm_so; } else if (MATCHED(18)) { /* s390 only line, no addresses on this line */ trace_line = 4; start = line + re_Oops_trace_pmatch[18].rm_eo; } else if (MATCHED(11)) { /* Reversed addresses for spinloops :( */ trace_line = 1; start = line + re_Oops_trace_pmatch[11].rm_so; } else if (trace_line == 1 && MATCHED(4)) /* Most continuation lines */ start = line + re_Oops_trace_pmatch[4].rm_so; else if (trace_line == 1 && MATCHED(14)) /* incorrectly split trace lines from ikd patch */ start = line + re_Oops_trace_pmatch[14].rm_so; else if ((trace_line == 2 || trace_line == 4) && MATCHED(7)) /* ppc/s390 continuation line */ start = line + re_Oops_trace_pmatch[7].rm_so; else trace_line = 0; } else trace_line = 0; if (trace_line) { if (trace_line == 3) trace_line = 0; /* no continuation lines */ return(start); } return(NULL);}/* Process a trace call line, extract addresses */static void Oops_trace_line(const char *line, const char *p, SYMBOL_SET *ss, const OPTIONS *options){ char **string = NULL; regex_t *pregex; regmatch_t *pregmatch; static regex_t re_ikd; static regmatch_t *re_ikd_pmatch; static const char procname[] = "Oops_trace_line"; /* ikd adds "(nn)" for stack frame size after each 'Trace' field. */ RE_COMPILE(&re_ikd, "^(\\([0-9]+\\) *)", REG_NEWLINE|REG_EXTENDED, &re_ikd_pmatch); /* ppc/s390 does not bracket its addresses */ if (isxdigit(*p)) { pregex = &re_unbracketed_address; pregmatch = re_unbracketed_address_pmatch; } else if (strncmp(p, "<[", 2) == 0) { /* I hate special cases! */ pregex = &re_revbracketed_address; pregmatch = re_revbracketed_address_pmatch; } else { pregex = &re_bracketed_address; pregmatch = re_bracketed_address_pmatch; } /* Loop over (un|rev)?bracketed addresses */ while (1) { if (regexec(pregex, p, pregex->re_nsub+1, pregmatch, 0) == 0) { addr_t addr; re_strings(pregex, p, pregmatch, &string); addr = hexstring(string[1]); addr = Oops_truncate_address(addr, options); add_symbol_n(ss, addr, 'T', 1, "Trace;"); p += pregmatch[0].rm_eo; } else if (strncmp(p, "from ", 5) == 0) p += 5; /* arm does "address from address" */ else if (regexec(&re_ikd, p, re_ikd.re_nsub+1, re_ikd_pmatch, 0) == 0) p += re_ikd_pmatch[0].rm_eo; /* step over ikd stack frame size */ else break; } if (*p && !strcmp(p, "...")) WARNING("garbage '%s' at end of trace line ignored", p); re_strings_free(pregex, &string);}/* Decide if the line contains CRIS registers. Returns first register name. */static const char *Oops_cris_regs(const char *line){ int i; static const char procname[] = "Oops_cris_regs"; /* Note that most of the register dump, the r0: to oR10: lines, are handled by Oops_regs. */ RE_COMPILE(&re_Oops_cris_regs, "^(IRP|SRP|D?CCR|USP|MOF): *" UNBRACKETED_ADDRESS, REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_cris_regs_pmatch); i = regexec(&re_Oops_cris_regs, line, re_Oops_cris_regs.re_nsub+1, re_Oops_cris_regs_pmatch, 0); DEBUG(4, "regexec %d", i); if (i == 0) return(line + re_Oops_cris_regs_pmatch[0].rm_so); return(NULL);}/* Process a CRIS register line, extract addresses */static void Oops_set_cris_regs(const char *line, const char *p, SYMBOL_SET *ss, const OPTIONS *options){ addr_t reg; char regname[7]; char **string = NULL; static const char procname[] = "Oops_set_cris_regs"; /* Loop over CRIS register names and unbracketed addresses. */ while (1) { if (regexec(&re_Oops_cris_regs, p, re_Oops_cris_regs.re_nsub+1, re_Oops_cris_regs_pmatch, 0) == 0) { re_strings(&re_Oops_cris_regs, p, re_Oops_cris_regs_pmatch, &string); reg = hexstring(string[2]); /* contents */ if (errno) { ERROR(" Invalid hex value in CRIS register line, ignored - '%s'", string[2]); perror(prefix); reg = 0; } else { reg = Oops_truncate_address(reg, options); strcpy(regname, ">>"); strncpy(regname+2, string[1], sizeof(regname)-3); strcat(regname, ";"); add_symbol_n(ss, reg, 'R', 1, regname); } p += re_Oops_cris_regs_pmatch[0].rm_eo; } else break; } if (*p) WARNING("garbage '%s' at end of CRIS register line ignored", p); re_strings_free(&re_Oops_cris_regs, &string);}/* Decide if the line contains s390 registers. Returns first register value. * This is messier than the trace lines. The heading is on one line followed by * the registers with *NO* keywords. Fine for a dedicated JESMSG file, very * poor design for a multi-user log system. */static const char *Oops_s390_regs(const char *line){ int i; static regex_t re_Oops_s390_regs; static regmatch_t *re_Oops_s390_regs_pmatch; static const char procname[] = "Oops_s390_regs"; RE_COMPILE(&re_Oops_s390_regs, "^(Kernel GPRS.*)", REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_s390_regs_pmatch); i = regexec(&re_Oops_s390_regs, line, re_Oops_s390_regs.re_nsub+1, re_Oops_s390_regs_pmatch, 0); DEBUG(4, "regexec %d", i); if (i == 0) { s390_reg_num = 0; /* Start with R0 */ return(line + re_Oops_s390_regs_pmatch[0].rm_eo); } else if (s390_reg_num >= 0) /* Header already seen */ { i = regexec(&re_unbracketed_address, line, re_unbracketed_address.re_nsub+1, re_unbracketed_address_pmatch, 0); DEBUG(4, "regexec %d", i); if (i == 0) return(line + re_unbracketed_address_pmatch[0].rm_so); } s390_reg_num = -1; /* Not processing s390 registers */ return(NULL);}/* Process a s390 register line, extract addresses */static void Oops_set_s390_regs(const char *line, const char *p, SYMBOL_SET *ss, const OPTIONS *options){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -