📄 oops.c
字号:
break; } switch (len) { case 2: code[byte++] = value; break; case 4: u16 = value; memcpy(code+byte, &u16, sizeof(u16)); byte += sizeof(u16); break; case 8: u32 = value; memcpy(code+byte, &u32, sizeof(u32)); byte += sizeof(u32); break; case 16: u64 = value; memcpy(code+byte, &u64, sizeof(u64)); byte += sizeof(u64); break; default: ERROR("invalid value 0x%s in Code line, must be 2, 4, 8 or 16 " "digits, value ignored", string[3]); break; } if (options->endianess && len != 2) { /* Reverse the endianess of the bytes just stored */ char c; len /= 2; while (len) { c = code[byte_prev]; code[byte_prev] = code[byte_prev+len-1]; code[byte_prev+len-1] = c; ++byte_prev; len -= 2; } } p += re_Oops_code_value_pmatch[0].rm_eo; } if (ret && *p) WARNING("garbage '%s' at end of code line ignored", p); re_strings_free(&re_Oops_code_value, &string); return(ret);}/* Add an objdump line to the symbol table. Just to keep the non-ix86 users * happy, replace XXX with an target specific string. */static void Oops_decode_one_add(SYMBOL_SET *ss, const addr_t address, const char *line1, const char type, const OPTIONS *options){ int i; const char *p1; char *line2, *p2, *p3; static char const procname[] = "Oops_decode_one_add"; i = strlen(line1)+1; line2 = malloc(i); if (!line2) malloc_error(procname); memset(line2, '\0', i); p1 = line1; p2 = line2; while (1) { if ((p3 = strstr(p1, "_XXX"))) { memcpy(p2, p1, p3-p1+1); p2 += p3 - p1 + 1; p1 = p3 + 4; strcpy(p2, Oops_arch_to_eip(options)); while (*p2) ++p2; } else { strcpy(p2, p1); break; } } if (strlen(line2) > strlen(line1)) ERROR("line2 overrun, should never happen line1='%s'\nline2='%s'", line1, line2); add_symbol_n(ss, address, type, 1, line2); free(line2);}/* Set the eip from the EIP line */static void Oops_set_eip(const char *value, addr_t *eip, SYMBOL_SET *ss, const char *me, const bfd *ibfd, OPTIONS *options){ static const char procname[] = "Oops_set_eip"; char eip_name[10], *p; /* Ensure target is set so EIP text is correct */ Oops_set_default_ta(me, ibfd, options); *eip = hexstring(value); if (errno) { ERROR("Invalid hex value in %s line, ignored - '%s'", Oops_arch_to_eip(options), value); perror(prefix); *eip = 0; } snprintf(eip_name, sizeof(eip_name), ">>%-3s;", Oops_arch_to_eip(options)); while ((p = strstr(eip_name, " ;"))) strncpy(p, "; ", 2); *eip = Oops_truncate_address(*eip, options); add_symbol_n(ss, *eip, 'E', 1, eip_name);}/* Look for the sysrq-t (show_task) process line and extract the command name */static int Oops_set_task_name(const char *line, char ***string, int string_max, SYMBOL_SET *ss){ int i; char id[64]; static regex_t re_Oops_set_task_name; static regmatch_t *re_Oops_set_task_name_pmatch; static const char procname[] = "Oops_set_task_name"; /* Task header from show_task contains (L-TLB) or (NOTLB), the first field * is the command name. */ RE_COMPILE(&re_Oops_set_task_name, "^([^ ]+) +[^ ] *([^ ]+).*\\((L-TLB|NOTLB)\\)", REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_set_task_name_pmatch); i = regexec(&re_Oops_set_task_name, line, re_Oops_set_task_name.re_nsub+1, re_Oops_set_task_name_pmatch, 0); DEBUG(4, "regexec %d", i); if (i) return(0); re_string_check(re_Oops_set_task_name.re_nsub+1, string_max, procname); re_strings(&re_Oops_set_task_name, line, re_Oops_set_task_name_pmatch, string); snprintf(id, sizeof(id), "Proc; %s", (*string)[1]); add_symbol_n(ss, 0, 'I', 1, id); return(1);}static regex_t re_Oops_regs;static regmatch_t *re_Oops_regs_pmatch;/* Decide if the line contains registers. Returns first register name. */static const char *Oops_regs(const char *line){ int i; const char *p; static const char procname[] = "Oops_regs"; RE_COMPILE(&re_Oops_regs, "^(" /* 1 */ "(GP|o)?r[0-9]{1,2}" /* 2 */ "|[goli][0-9]{1,2}" "|[eR][ABCD]X" "|[eR][DS]I" "|RBP" "|e[bs]p" "|[fsi]p" "|IRP" "|SRP" "|D?CCR" "|USP" "|MOF" "|ret_pc" ")" " *[:=] *" UNBRACKETED_ADDRESS /* 3 */ " *" , REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_regs_pmatch); i = regexec(&re_Oops_regs, line, re_Oops_regs.re_nsub+1, re_Oops_regs_pmatch, 0); DEBUG(4, "regexec %d", i); if (i) return(NULL); /* Some lines just have one register at the start followed by a set of * values, those lines are handled as special cases because I have to * generate the register numbers. This code only routines lines that * contain exactly one value or each value is preceded by ':' or '='. * Lazy check, any ':' or '=' in the rest of the line will do. */ p = line + re_Oops_regs_pmatch[0].rm_eo; if (*p && !index(p, ':') && !index(p, '=')) return(NULL); return(line + re_Oops_regs_pmatch[0].rm_so);}/* Process a register line, extract addresses */static void Oops_set_regs(const char *line, const char *p, SYMBOL_SET *ss, const OPTIONS *options){ addr_t reg; char regname[20]; char **string = NULL; static const char procname[] = "Oops_set_regs"; /* Loop over register names and unbracketed addresses */ while (1) { if (regexec(&re_Oops_regs, p, re_Oops_regs.re_nsub+1, re_Oops_regs_pmatch, 0) == 0) { re_strings(&re_Oops_regs, p, re_Oops_regs_pmatch, &string); reg = hexstring(string[3]); /* contents */ if (errno) { ERROR(" Invalid hex value in register line, ignored - '%s'", string[3]); perror(prefix); reg = 0; } reg = Oops_truncate_address(reg, options); strcpy(regname, ">>"); strncpy(regname+2, string[1], sizeof(regname)-2); if (strlen(regname) < sizeof(regname)-1) strcat(regname, ";"); add_symbol_n(ss, reg, 'R', 1, regname); p += re_Oops_regs_pmatch[0].rm_eo; } else break; } if (*p) WARNING("garbage '%s' at end of register line ignored", p); re_strings_free(&re_Oops_regs, &string);}/******************************************************************************//* Start architecture sensitive code *//******************************************************************************/static regex_t re_Oops_cris_regs;static regmatch_t *re_Oops_cris_regs_pmatch;static int s390_reg_num = -1;/* All address arithmetic is done in 64 bit mode, truncate to the result to * a valid range for the target. */static addr_t Oops_truncate_address(addr_t address, const OPTIONS *options){ if (options->address_bits == 32 || (options->target && ( strstr(options->target, "i370") || strstr(options->target, "s390")))) { U32 u32 = address; if (strstr(options->target, "i370") || strstr(options->target, "s390")) u32 &= 0x7fffffff; /* Really 31 bit addressing on i370/s390 */ address = u32; } address &= truncate_mask; return(address);}/* Return a string to represent the eip, depending on the target. */static const char *Oops_arch_to_eip(const OPTIONS *options){ if (!options->target) return("???"); if (strstr(options->target, "i386")) return("EIP"); if (strstr(options->target, "alpha") || strstr(options->target, "arm") || strstr(options->target, "cris") || strstr(options->target, "m68k") || strstr(options->target, "mips")) return("PC"); if (strstr(options->target, "sparc")) { if (strstr(options->target, "64")) return("TPC"); else return("PC"); } if (strstr(options->target, "powerpc")) return("NIP"); if (strstr(options->target, "i370") || strstr(options->target, "s390")) return("PSW"); if (strstr(options->target, "ia64")) return("IP"); if (strstr(options->target, "x86_64") || strstr(options->target, "x86-64") || strstr(options->target, "x8664")) return("RIP"); return("???");}/* Look for the EIP: line, returns start of the relevant hex value */static char *Oops_eip(const char *line, char ***string, int string_max, const bfd *ibfd, OPTIONS *options){ int i; static regex_t re_Oops_eip_sparc; static regmatch_t *re_Oops_eip_sparc_pmatch; static regex_t re_Oops_eip_sparc64; static regmatch_t *re_Oops_eip_sparc64_pmatch; static regex_t re_Oops_eip_ppc; static regmatch_t *re_Oops_eip_ppc_pmatch; static regex_t re_Oops_eip_mips; static regmatch_t *re_Oops_eip_mips_pmatch; static regex_t re_Oops_eip_kdb; static regmatch_t *re_Oops_eip_kdb_pmatch; static regex_t re_Oops_eip_ia64; static regmatch_t *re_Oops_eip_ia64_pmatch; static regex_t re_Oops_mca_ip_ia64; static regmatch_t *re_Oops_mca_ip_ia64_pmatch; static regex_t re_Oops_eip_cris; static regmatch_t *re_Oops_eip_cris_pmatch; static regex_t re_Oops_eip_other; static regmatch_t *re_Oops_eip_other_pmatch; static const char procname[] = "Oops_eip"; /* Oops 'EIP:' line for sparc, actually PSR followed by PC */ RE_COMPILE(&re_Oops_eip_sparc, "^PSR: [0-9a-fA-F]+ PC: " UNBRACKETED_ADDRESS, REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_eip_sparc_pmatch); i = regexec(&re_Oops_eip_sparc, line, re_Oops_eip_sparc.re_nsub+1, re_Oops_eip_sparc_pmatch, 0); DEBUG(4, "regexec sparc %d", i); if (i == 0) { re_string_check(re_Oops_eip_sparc.re_nsub+1, string_max, procname); re_strings(&re_Oops_eip_sparc, line, re_Oops_eip_sparc_pmatch, string); return((*string)[re_Oops_eip_sparc.re_nsub]); } /* Oops 'EIP:' line for sparc64, actually TSTATE followed by TPC */ RE_COMPILE(&re_Oops_eip_sparc64, "^TSTATE: [0-9a-fA-F]{16} TPC: " UNBRACKETED_ADDRESS, REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_eip_sparc64_pmatch); re_string_check(re_Oops_eip_sparc64.re_nsub+1, string_max, procname); i = regexec(&re_Oops_eip_sparc64, line, re_Oops_eip_sparc64.re_nsub+1, re_Oops_eip_sparc64_pmatch, 0); DEBUG(4, "regexec sparc64 %d", i); if (i == 0) { /* Special case for sparc64. If the output target is defaulting to the * same format as ksymoops then the default is wrong, kernel is 64 bit, * ksymoops is 32 bit. When we see an EIP from sparc64, set the correct * default. */ if (!options->target && !options->architecture && strcmp(bfd_get_target(ibfd), "elf32-sparc")) { options->target = "elf64-sparc"; options->architecture = "sparc:v9a"; } re_strings(&re_Oops_eip_sparc64, line, re_Oops_eip_sparc64_pmatch, string); return((*string)[re_Oops_eip_sparc64.re_nsub]); } /* Oops 'EIP:' line for PPC, all over the place */ RE_COMPILE(&re_Oops_eip_ppc, "(" "kernel pc " "|trap at PC: " "|bad area pc " "|NIP: " ")" UNBRACKETED_ADDRESS, REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_eip_ppc_pmatch); i = regexec(&re_Oops_eip_ppc, line, re_Oops_eip_ppc.re_nsub+1, re_Oops_eip_ppc_pmatch, 0); DEBUG(4, "regexec ppc %d", i); if (i == 0) { re_string_check(re_Oops_eip_ppc.re_nsub+1, string_max, procname); re_strings(&re_Oops_eip_ppc, line, re_Oops_eip_ppc_pmatch, string); return((*string)[re_Oops_eip_ppc.re_nsub]); } /* Oops 'EIP:' line for mips, epc, optional white space, ':', * optional white space, unbracketed address. */ RE_COMPILE(&re_Oops_eip_mips, "^epc *:+ *" UNBRACKETED_ADDRESS, REG_NEWLINE|REG_EXTENDED|REG_ICASE, &re_Oops_eip_mips_pmatch); i = regexec(&re_Oops_eip_mips, line, re_Oops_eip_mips.re_nsub+1, re_Oops_eip_mips_pmatch, 0); DEBUG(4, "regexec mips %d", i); if (i == 0) { re_string_check(re_Oops_eip_mips.re_nsub+1, string_max, procname); re_strings(&re_Oops_eip_mips, line, re_Oops_eip_mips_pmatch, string); return((*string)[re_Oops_eip_mips.re_nsub]); } /* Oops 'IP' line for ia64, space, ip, optional white space, ':', * optional white space, bracketed address. */ RE_COMPILE(&re_Oops_eip_ia64, " ip *:+ *" BRACKETED_ADDRESS, REG_NEWLINE|REG_EXTENDED|REG_ICASE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -