oops.c
上传用户:hxtd_72
上传日期:2007-06-06
资源大小:64k
文件大小:79k
源码类别:

驱动编程

开发平台:

C/C++

  1. /*
  2.     oops.c.
  3.     Oops processing for ksymoops.
  4.     Copyright 1999 Keith Owens <kaos@ocs.com.au>.
  5.     Released under the GNU Public Licence, Version 2.
  6.  */
  7. #include "ksymoops.h"
  8. #include <ctype.h>
  9. #include <errno.h>
  10. #include <malloc.h>
  11. #include <memory.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. /* Error detected by bfd */
  16. static void Oops_bfd_perror(const char *msg)
  17. {
  18.     static char const procname[] = "Oops_bfd_perror";
  19.     bfd_error_type err = bfd_get_error();
  20.     ERROR("%s %s", msg, bfd_errmsg(err));
  21. }
  22. /* Open the ksymoops binary so we have an input bfd to copy data from. */
  23. static void Oops_open_input_bfd(char **me, bfd **ibfd, const OPTIONS *options)
  24. {
  25.     char **matches, **match;
  26.     static char const procname[] = "Oops_open_input_bfd";
  27.     *me = find_fullpath(prefix);
  28.     if (!*ibfd && !(*ibfd = bfd_openr(*me, NULL))) {
  29. Oops_bfd_perror(*me);
  30. FATAL("%s", "giving up");
  31.     }
  32.     if (!bfd_check_format_matches(*ibfd, bfd_object, &matches)) {
  33. Oops_bfd_perror(*me);
  34. if (bfd_get_error() == bfd_error_file_ambiguously_recognized) {
  35.     printf("%s Matching formats:", procname);
  36.     match = matches;
  37.     while (*match)
  38. printf(" %s", *match++);
  39.     printf("n");
  40.     free(matches);
  41. }
  42. FATAL("%s", "giving up");
  43.     }
  44. }
  45. /* If target or architecture is not already set, default to the same as
  46.  * ksymoops.
  47.  */
  48. static void Oops_set_default_ta(const char *me, const bfd *ibfd,
  49. OPTIONS *options)
  50. {
  51.     static char const procname[] = "Oops_set_default_ta";
  52.     const char *bt;
  53.     const bfd_arch_info_type *bai;
  54.     int t = 0, a = 0;
  55.     if (!options->target) {
  56. bt = bfd_get_target(ibfd); /* Bah, undocumented bfd function */
  57. if (!bt) {
  58.     Oops_bfd_perror(me);
  59.     FATAL("cannot get bfd_target for %s:", me);
  60. }
  61. options->target = bt;
  62. t = 1;
  63.     }
  64.     if (!options->architecture) {
  65. /* bfd_get_arch_info should really take (const bfd *) */
  66. bai = bfd_get_arch_info((bfd *)ibfd);
  67. if (!bai) {
  68.     Oops_bfd_perror(me);
  69.     FATAL("cannot get bfd_arch_info for %s:", me);
  70. }
  71. options->architecture = bai->printable_name;
  72. a = 1;
  73.     }
  74.     if (t || a) {
  75. printf("Using defaults from ksymoops");
  76. if (t)
  77.     printf(" -t %s", options->target);
  78. if (a)
  79.     printf(" -a %s", options->architecture);
  80. printf("n");
  81.     }
  82. }
  83. /* Write the code values to a file using bfd. */
  84. static int Oops_write_bfd_data(const bfd *ibfd, bfd *obfd,
  85.        const char *code, int size)
  86. {
  87.     asection *isec, *osec;
  88.     asymbol *osym;
  89.     /* bfd_get_section_by_name should really take (const bfd *,) */
  90.     if (!(isec = bfd_get_section_by_name((bfd *)ibfd, ".text"))) {
  91. Oops_bfd_perror("get_section");
  92. return(0);
  93.     }
  94.     if (!bfd_set_start_address(obfd, 0)) {
  95. Oops_bfd_perror("set_start_address");
  96. return(0);
  97.     }
  98.     if (!(osec = bfd_make_section(obfd, ".text"))) {
  99. Oops_bfd_perror("make_section");
  100. return(0);
  101.     }
  102.     if (!bfd_set_section_flags(obfd, osec,
  103. bfd_get_section_flags(ibfd, isec))) {
  104. Oops_bfd_perror("set_section_flags");
  105. return(0);
  106.     }
  107.     if (!bfd_set_section_alignment(obfd, osec,
  108. bfd_get_section_alignment(ibfd, isec))) {
  109. Oops_bfd_perror("set_section_alignment");
  110. return(0);
  111.     }
  112.     osec->output_section = osec;
  113.     if (!(osym = bfd_make_empty_symbol(obfd))) {
  114. Oops_bfd_perror("make_empty_symbol");
  115. return(0);
  116.     }
  117.     osym->name = "_XXX";
  118.     osym->section = osec;
  119.     osym->flags = BSF_GLOBAL;
  120.     osym->value = 0;
  121.     if (!bfd_set_symtab(obfd, &osym, 1)) {
  122. Oops_bfd_perror("set_symtab");
  123. return(0);
  124.     }
  125.     if (!bfd_set_section_size(obfd, osec, size)) {
  126. Oops_bfd_perror("set_section_size");
  127. return(0);
  128.     }
  129.     if (!bfd_set_section_vma(obfd, osec, 0)) {
  130. Oops_bfd_perror("set_section_vma");
  131. return(0);
  132.     }
  133.     if (!bfd_set_section_contents(obfd, osec, (PTR) code, 0, size)) {
  134. Oops_bfd_perror("set_section_contents");
  135. return(0);
  136.     }
  137.     if (!bfd_close(obfd)) {
  138. Oops_bfd_perror("close(obfd)");
  139. return(0);
  140.     }
  141.     return 1;
  142. }
  143. /* Write the Oops code to a temporary file with suitable header and trailer. */
  144. static char *Oops_code_to_file(const char *code, int size, const bfd *ibfd,
  145.        OPTIONS *options)
  146. {
  147.     char *file, *tmpdir;
  148.     int fd;
  149.     bfd *obfd;
  150.     const bfd_arch_info_type *bai;
  151.     static const char temp_suffix[] = "/ksymoops.XXXXXX";
  152.     static char const procname[] = "Oops_code_to_file";
  153.     /* Security fix, use mkstemp and honour TMPDIR */
  154.     if (!(tmpdir = getenv("TMPDIR")) || !*tmpdir) {
  155. #ifdef P_tmpdir
  156. tmpdir = P_tmpdir;
  157. #else
  158. tmpdir = "/tmp";
  159. #endif
  160.     }
  161.     file = malloc(strlen(tmpdir) + sizeof(temp_suffix));
  162.     if (!file)
  163. malloc_error(procname);
  164.     strcpy(file, tmpdir);
  165.     strcat(file, temp_suffix);
  166.     if ((fd = mkstemp(file)) < 0) {
  167. ERROR("Unable to open mkstemp file '%s'n", file);
  168. perror(prefix);
  169. return(NULL);
  170.     }
  171.     close(fd);
  172.     /* Set the target on the output file */
  173.     if (!(obfd = bfd_openw(file, options->target))) {
  174. Oops_bfd_perror(file);
  175. if (bfd_get_error() == bfd_error_wrong_format)
  176.     printf("Sorry, looks like your binutils cannot "
  177.    "handle target %sn", options->target);
  178. return(NULL);
  179.     }
  180.     bfd_set_format(obfd, bfd_object);
  181.     /* Set the architecture on the output file */
  182.     if (!(bai = bfd_scan_arch(options->architecture))) {
  183. Oops_bfd_perror("scan_arch for specified architecture");
  184. if (bfd_get_error() == bfd_error_wrong_format)
  185.     printf("Sorry, looks like your binutils cannot "
  186. "handle the specified architecturen");
  187. return(NULL);
  188.     }
  189.     bfd_set_arch_info(obfd, bai);
  190.     options->address_bits = bfd_arch_bits_per_address(obfd);
  191.     if (!Oops_write_bfd_data(ibfd, obfd, code, size))
  192. return(NULL);
  193.     return(file);
  194. }
  195. /* Run objdump against the binary Oops code */
  196. static FILE *Oops_objdump(const char *file, const OPTIONS *options)
  197. {
  198.     char *cmd;
  199.     FILE *f;
  200.     static char const objdump_options[] = "-dhf ";
  201.     static char const procname[] = "Oops_objdump";
  202.     cmd = malloc(strlen(path_objdump)+1+strlen(objdump_options)+strlen(file)+1);
  203.     if (!cmd)
  204. malloc_error(procname);
  205.     strcpy(cmd, path_objdump);
  206.     strcat(cmd, " ");
  207.     strcat(cmd, objdump_options);
  208.     strcat(cmd, file);
  209.     DEBUG(2, "command '%s'", cmd);
  210.     f = popen_local(cmd, procname);
  211.     free(cmd);
  212.     return(f);
  213. }
  214. /* Forward references. */
  215. static const char *Oops_arch_to_eip(const OPTIONS *options);
  216. static void Oops_decode_one_add(SYMBOL_SET *ss, const addr_t address,
  217. const char *line1, const char type, const OPTIONS *options);
  218. static addr_t Oops_truncate_address(addr_t address, const OPTIONS *options);
  219. /* Process one code line from objdump, ignore everything else */
  220. static void Oops_decode_one(SYMBOL_SET *ss, const char *line, addr_t eip,
  221.     int adjust, const char type, const OPTIONS *options)
  222. {
  223.     int i;
  224.     addr_t address, eip_relative;
  225.     char *line2, *map, **string = NULL;
  226.     static regex_t     re_Oops_objdump;
  227.     static regmatch_t *re_Oops_objdump_pmatch;
  228.     static char const procname[] = "Oops_decode_one";
  229.     /* objdump output.  Optional whitespace, hex digits, optional
  230.      * ' <_XXX+offset>', ':'.  The '+offset' after _XXX is also optional.
  231.      * Older binutils output 'xxxxxxxx <_XXX+offset>:', newer versions do
  232.      * '00000000 <_XXX>:' first followed by '      xx:' lines.
  233.      *
  234.      * Just to complicate things even more, objdump recognises jmp, call,
  235.      * etc., converts the code to something like this :-
  236.      * "   f: e8 32 34 00 00  call   3446 <_XXX+0x3446>"
  237.      * Recognise this and append the eip adjusted address, followed by the
  238.      * map_address text for that address.
  239.      *
  240.      * With any luck, objdump will take care of all such references which
  241.      * makes this routine architecture insensitive.  No need to test for
  242.      * i386 jmp, call or m68k swl etc.
  243.      */
  244.     RE_COMPILE(&re_Oops_objdump,
  245.     "^ *"
  246.     "([0-9a-fA-F]+)" /* 1 */
  247.     "( <_XXX[^>]*>)?" /* 2 */
  248.     ":"
  249.     "(" /* 3 */
  250.     ".* +<_XXX\+0?x?([0-9a-fA-F]+)> *$" /* 4 */
  251.     ")?"
  252.     ".*"
  253.     ,
  254. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  255. &re_Oops_objdump_pmatch);
  256.     i = regexec(&re_Oops_objdump, line, re_Oops_objdump.re_nsub+1,
  257. re_Oops_objdump_pmatch, 0);
  258.     DEBUG(4, "regexec %d", i);
  259.     if (i != 0)
  260. return;
  261.     re_strings(&re_Oops_objdump, line, re_Oops_objdump_pmatch, &string);
  262.     address = hexstring(string[1]);
  263.     if (errno) {
  264. ERROR("Invalid hex value in objdump line, treated as zero - '%s'n"
  265.     "  objdump line '%s'",
  266.     string[1], line);
  267. perror(prefix);
  268. address = 0;
  269.     }
  270.     address = Oops_truncate_address(address + eip + adjust, options);
  271.     if (string[4]) {
  272. /* EIP relative data to be adjusted. */
  273. eip_relative = hexstring(string[4]);
  274. if (errno) {
  275.     ERROR("Invalid hex value in objdump line, treated as zero - '%s'n"
  276.   "objdump line '%s'", string[4], line);
  277.     perror(prefix);
  278.     eip_relative = 0;
  279. }
  280. eip_relative = Oops_truncate_address(eip_relative + eip + adjust,
  281. options);
  282. map = map_address(&ss_merged, eip_relative, options);
  283. /* new text is original line, eip_relative in hex, map text */
  284. i = strlen(line)+1+2*sizeof(eip_relative)+1+strlen(map)+1;
  285. line2 = malloc(i);
  286. if (!line2)
  287.     malloc_error(procname);
  288. snprintf(line2, i, "%s %s %s",
  289.     line, format_address(eip_relative, options), map);
  290. Oops_decode_one_add(ss, address, line2, type, options);
  291. free(line2);
  292.     }
  293.     else
  294. Oops_decode_one_add(ss, address, line, type, options);  /* as is */
  295.     re_strings_free(&re_Oops_objdump, &string);
  296. }
  297. /* Maximum number of code bytes to process.  It needs to be a multiple of 2 for
  298.  * endianess swapping (-e).  Sparc and alpha dump 36 bytes so use 64.
  299.  */
  300. #define CODE_SIZE 64
  301. /* Extract the hex values from the Code: line and convert to binary.
  302.  * Strange as it seems, this is actually architecture independent, nothing in
  303.  * this proc cares who created the Code: line.
  304.  */
  305. static int Oops_code_values(const unsigned char* code_text, unsigned char *code,
  306.     int *adjust, const OPTIONS *options)
  307. {
  308.     int byte = 0, byte_prev, len, ret = 1;
  309.     U16 u16;
  310.     U32 u32;
  311.     U64 u64, value;
  312.     char **string = NULL;
  313.     const char *p;
  314.     static regex_t     re_Oops_code_value;
  315.     static regmatch_t *re_Oops_code_value_pmatch;
  316.     static const char procname[] = "Oops_code_values";
  317.     /* Given by re_Oops_code: code_text is a message (e.g. "general protection")
  318.      * or one or more hex fields separated by spaces.  Some architectures
  319.      * bracket the current instruction with '<' and '>', others use '(' and ')'.
  320.      * The first character is nonblank.
  321.      */
  322.     if (!isxdigit(*code_text)) {
  323. WARNING("%s", "Code looks like message, not hex digits.  "
  324.     "No disassembly attempted.");
  325. return(0);
  326.     }
  327.     memset(code, '', CODE_SIZE);
  328.     p = code_text;
  329.     *adjust = 0;    /* EIP points to code byte 0 */
  330.     /* Code values.  Hex values separated by white space.  On some systems, the
  331.      * current instruction is bracketed in '<' and '>' or '(' and ')'.
  332.      */
  333.     RE_COMPILE(&re_Oops_code_value,
  334.     "^"
  335.     "(" /* 1 */
  336.       "([<(]?)" /* 2 */
  337.       "([0-9a-fA-F]+)" /* 3 */
  338.       "[)>]?"
  339.       " *"
  340.     ")"
  341.     "|(Bad .*)" /* 4 */
  342.     ,
  343. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  344. &re_Oops_code_value_pmatch);
  345.     while (regexec(&re_Oops_code_value, p, re_Oops_code_value.re_nsub+1,
  346.     re_Oops_code_value_pmatch, 0) == 0) {
  347. re_strings(&re_Oops_code_value, p,
  348.     re_Oops_code_value_pmatch, &string);
  349. if (string[4] && *(string[4])) {
  350.     ret = 0;
  351.     break; /* Bad EIP value, no code bytes */
  352. }
  353. if (byte >= CODE_SIZE)
  354.     break;
  355. value = hexstring(string[3]);
  356. if (errno) {
  357.     ERROR("Invalid hex value in code_value line, treated as zero - "
  358.   "'%s'ncode_value line '%s'", string[3], code_text);
  359.     perror(prefix);
  360.     value = 0;
  361. }
  362. if (string[2] && *(string[2]))
  363.     *adjust = -byte;    /* this byte is EIP */
  364. /* On some architectures Code: is a stream of bytes, on some it is a
  365.  * stream of shorts, on some it is a stream of ints.  Consistent we're
  366.  * not!
  367.  */
  368. len = strlen(string[3]);
  369. byte_prev = byte;
  370. if (byte+len/2 > CODE_SIZE) {
  371.     WARNING("extra values in Code line, ignored - '%s'", string[3]);
  372.     break;
  373. }
  374. switch (len) {
  375.     case 2:
  376. code[byte++] = value;
  377. break;
  378.     case 4:
  379. u16 = value;
  380. memcpy(code+byte, &u16, sizeof(u16));
  381. byte += sizeof(u16);
  382. break;
  383.     case 8:
  384. u32 = value;
  385. memcpy(code+byte, &u32, sizeof(u32));
  386. byte += sizeof(u32);
  387. break;
  388.     case 16:
  389. u64 = value;
  390. memcpy(code+byte, &u64, sizeof(u64));
  391. byte += sizeof(u64);
  392. break;
  393.     default:
  394. ERROR("invalid value 0x%s in Code line, must be 2, 4, 8 or 16 "
  395.       "digits, value ignored", string[3]);
  396. break;
  397. }
  398. if (options->endianess && len != 2) {
  399.     /* Reverse the endianess of the bytes just stored */
  400.     char c;
  401.     len /= 2;
  402.     while (len) {
  403. c = code[byte_prev];
  404. code[byte_prev] = code[byte_prev+len-1];
  405. code[byte_prev+len-1] = c;
  406. ++byte_prev;
  407. len -= 2;
  408.     }
  409. }
  410. p += re_Oops_code_value_pmatch[0].rm_eo;
  411.     }
  412.     if (ret && *p)
  413. WARNING("garbage '%s' at end of code line ignored", p);
  414.     re_strings_free(&re_Oops_code_value, &string);
  415.     return(ret);
  416. }
  417. /* Add an objdump line to the symbol table.  Just to keep the non-ix86 users
  418.  * happy, replace XXX with an target specific string.
  419.  */
  420. static void Oops_decode_one_add(SYMBOL_SET *ss, const addr_t address,
  421. const char *line1, const char type, const OPTIONS *options)
  422. {
  423.     int i;
  424.     const char *p1;
  425.     char *line2, *p2, *p3;
  426.     static char const procname[] = "Oops_decode_one_add";
  427.     i = strlen(line1)+1;
  428.     line2 = malloc(i);
  429.     if (!line2)
  430. malloc_error(procname);
  431.     memset(line2, '', i);
  432.     p1 = line1;
  433.     p2 = line2;
  434.     while (1) {
  435. if ((p3 = strstr(p1, "_XXX"))) {
  436.     memcpy(p2, p1, p3-p1+1);
  437.     p2 += p3 - p1 + 1;
  438.     p1 = p3 + 4;
  439.     strcpy(p2, Oops_arch_to_eip(options));
  440.     while (*p2)
  441. ++p2;
  442. }
  443. else {
  444.     strcpy(p2, p1);
  445.     break;
  446. }
  447.     }
  448.     if (strlen(line2) > strlen(line1))
  449. ERROR("line2 overrun, should never happen line1='%s'nline2='%s'",
  450.     line1, line2);
  451.     add_symbol_n(ss, address, type, 1, line2);
  452.     free(line2);
  453. }
  454. /* Set the eip from the EIP line */
  455. static void Oops_set_eip(const char *value, addr_t *eip, SYMBOL_SET *ss,
  456.  const char *me, const bfd *ibfd,
  457.  OPTIONS *options)
  458. {
  459.     static const char procname[] = "Oops_set_eip";
  460.     char eip_name[10], *p;
  461.     /* Ensure target is set so EIP text is correct */
  462.     Oops_set_default_ta(me, ibfd, options);
  463.     *eip = hexstring(value);
  464.     if (errno) {
  465. ERROR("Invalid hex value in %s line, ignored - '%s'",
  466.     Oops_arch_to_eip(options), value);
  467. perror(prefix);
  468. *eip = 0;
  469.     }
  470.     snprintf(eip_name, sizeof(eip_name), ">>%-3s;",
  471.  Oops_arch_to_eip(options));
  472.     while ((p = strstr(eip_name, " ;")))
  473. strncpy(p, "; ", 2);
  474.     *eip = Oops_truncate_address(*eip, options);
  475.     add_symbol_n(ss, *eip, 'E', 1, eip_name);
  476. }
  477. /* Look for the sysrq-t (show_task) process line and extract the command name */
  478. static int Oops_set_task_name(const char *line, char ***string, int string_max, SYMBOL_SET *ss)
  479. {
  480.     int i;
  481.     char id[64];
  482.     static regex_t     re_Oops_set_task_name;
  483.     static regmatch_t *re_Oops_set_task_name_pmatch;
  484.     static const char procname[] = "Oops_set_task_name";
  485.     /* Task header from show_task contains (L-TLB) or (NOTLB), the first field
  486.      * is the command name.
  487.      */
  488.     RE_COMPILE(&re_Oops_set_task_name,
  489.     "^([^ ]+) +[^ ] *([^ ]+).*\((L-TLB|NOTLB)\)",
  490. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  491. &re_Oops_set_task_name_pmatch);
  492.     i = regexec(&re_Oops_set_task_name, line, re_Oops_set_task_name.re_nsub+1,
  493. re_Oops_set_task_name_pmatch, 0);
  494.     DEBUG(4, "regexec %d", i);
  495.     if (i)
  496. return(0);
  497.     re_string_check(re_Oops_set_task_name.re_nsub+1, string_max, procname);
  498.     re_strings(&re_Oops_set_task_name, line, re_Oops_set_task_name_pmatch, string);
  499.     snprintf(id, sizeof(id), "Proc;  %s", (*string)[1]);
  500.     add_symbol_n(ss, 0, 'I', 1, id);
  501.     return(1);
  502. }
  503. static regex_t     re_Oops_regs;
  504. static regmatch_t *re_Oops_regs_pmatch;
  505. /* Decide if the line contains registers.  Returns first register name. */
  506. static const char *Oops_regs(const char *line)
  507. {
  508.     int i;
  509.     const char *p;
  510.     static const char procname[] = "Oops_regs";
  511.     RE_COMPILE(&re_Oops_regs,
  512.     "^(" /* 1 */
  513.     "(GP|o)?r[0-9]{1,2}" /* 2 */
  514.     "|[goli][0-9]{1,2}"
  515.     "|[eR][ABCD]X"
  516.     "|[eR][DS]I"
  517.     "|RBP"
  518.     "|e[bs]p"
  519.     "|[fsi]p"
  520.     "|IRP"
  521.     "|SRP"
  522.     "|D?CCR"
  523.     "|USP"
  524.     "|MOF"
  525.     "|ret_pc"
  526.     ")"
  527.     " *[:=] *"
  528.     UNBRACKETED_ADDRESS /* 3 */
  529.     " *"
  530.     ,
  531. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  532. &re_Oops_regs_pmatch);
  533.     i = regexec(&re_Oops_regs, line, re_Oops_regs.re_nsub+1,
  534. re_Oops_regs_pmatch, 0);
  535.     DEBUG(4, "regexec %d", i);
  536.     if (i)
  537. return(NULL);
  538.     /* Some lines just have one register at the start followed by a set of
  539.      * values, those lines are handled as special cases because I have to
  540.      * generate the register numbers.  This code only routines lines that
  541.      * contain exactly one value or each value is preceded by ':' or '='.
  542.      * Lazy check, any ':' or '=' in the rest of the line will do.
  543.      */
  544.     p = line + re_Oops_regs_pmatch[0].rm_eo;
  545.     if (*p && !index(p, ':') && !index(p, '='))
  546. return(NULL);
  547.     return(line + re_Oops_regs_pmatch[0].rm_so);
  548. }
  549. /* Process a register line, extract addresses */
  550. static void Oops_set_regs(const char *line, const char *p,
  551.        SYMBOL_SET *ss, const OPTIONS *options)
  552. {
  553.     addr_t reg;
  554.     char regname[20];
  555.     char **string = NULL;
  556.     static const char procname[] = "Oops_set_regs";
  557.     /* Loop over register names and unbracketed addresses */
  558.     while (1) {
  559. if (regexec(&re_Oops_regs, p, re_Oops_regs.re_nsub+1,
  560.     re_Oops_regs_pmatch, 0) == 0) {
  561.     re_strings(&re_Oops_regs, p, re_Oops_regs_pmatch, &string);
  562.     reg = hexstring(string[3]); /* contents */
  563.     if (errno) {
  564. ERROR(" Invalid hex value in register line, ignored - '%s'",
  565.       string[3]);
  566. perror(prefix);
  567. reg = 0;
  568.     }
  569.     reg = Oops_truncate_address(reg, options);
  570.     strcpy(regname, ">>");
  571.     strncpy(regname+2, string[1], sizeof(regname)-2);
  572.     if (strlen(regname) < sizeof(regname)-1)
  573. strcat(regname, ";");
  574.     add_symbol_n(ss, reg, 'R', 1, regname);
  575.     p += re_Oops_regs_pmatch[0].rm_eo;
  576. }
  577. else
  578.     break;
  579.     }
  580.     if (*p)
  581. WARNING("garbage '%s' at end of register line ignored", p);
  582.     re_strings_free(&re_Oops_regs, &string);
  583. }
  584. /******************************************************************************/
  585. /*                     Start architecture sensitive code                      */
  586. /******************************************************************************/
  587. static regex_t     re_Oops_cris_regs;
  588. static regmatch_t *re_Oops_cris_regs_pmatch;
  589. static int         s390_reg_num = -1;
  590. /* All address arithmetic is done in 64 bit mode, truncate to the result to
  591.  * a valid range for the target.
  592.  */
  593. static addr_t Oops_truncate_address(addr_t address, const OPTIONS *options)
  594. {
  595.     if (options->address_bits == 32 ||
  596. (options->target && (
  597.  strstr(options->target, "i370") ||
  598.  strstr(options->target, "s390")))) {
  599. U32 u32 = address;
  600. if (strstr(options->target, "i370") ||
  601.     strstr(options->target, "s390"))
  602.     u32 &= 0x7fffffff;  /* Really 31 bit addressing on i370/s390 */
  603. address = u32;
  604.     }
  605.     address &= truncate_mask;
  606.     return(address);
  607. }
  608. /* Return a string to represent the eip, depending on the target. */
  609. static const char *Oops_arch_to_eip(const OPTIONS *options)
  610. {
  611.     if (!options->target)
  612. return("???");
  613.     if (strstr(options->target, "i386"))
  614. return("EIP");
  615.     if (strstr(options->target, "alpha") ||
  616. strstr(options->target, "arm")   ||
  617. strstr(options->target, "cris")  ||
  618. strstr(options->target, "m68k")  ||
  619. strstr(options->target, "mips"))
  620.     return("PC");
  621.     if (strstr(options->target, "sparc")) {
  622. if (strstr(options->target, "64"))
  623.     return("TPC");
  624. else
  625.     return("PC");
  626.     }
  627.     if (strstr(options->target, "powerpc"))
  628. return("NIP");
  629.     if (strstr(options->target, "i370") ||
  630. strstr(options->target, "s390"))
  631. return("PSW");
  632.     if (strstr(options->target, "ia64"))
  633. return("IP");
  634.     if (strstr(options->target, "x86_64") ||
  635. strstr(options->target, "x86-64") ||
  636. strstr(options->target, "x8664"))
  637.     return("RIP");
  638.     return("???");
  639. }
  640. /* Look for the EIP: line, returns start of the relevant hex value */
  641. static char *Oops_eip(const char *line, char ***string, int string_max,
  642.       const bfd *ibfd, OPTIONS *options)
  643. {
  644.     int i;
  645.     static regex_t     re_Oops_eip_sparc;
  646.     static regmatch_t *re_Oops_eip_sparc_pmatch;
  647.     static regex_t     re_Oops_eip_sparc64;
  648.     static regmatch_t *re_Oops_eip_sparc64_pmatch;
  649.     static regex_t     re_Oops_eip_ppc;
  650.     static regmatch_t *re_Oops_eip_ppc_pmatch;
  651.     static regex_t     re_Oops_eip_mips;
  652.     static regmatch_t *re_Oops_eip_mips_pmatch;
  653.     static regex_t     re_Oops_eip_kdb;
  654.     static regmatch_t *re_Oops_eip_kdb_pmatch;
  655.     static regex_t     re_Oops_eip_ia64;
  656.     static regmatch_t *re_Oops_eip_ia64_pmatch;
  657.     static regex_t     re_Oops_mca_ip_ia64;
  658.     static regmatch_t *re_Oops_mca_ip_ia64_pmatch;
  659.     static regex_t     re_Oops_eip_cris;
  660.     static regmatch_t *re_Oops_eip_cris_pmatch;
  661.     static regex_t     re_Oops_eip_other;
  662.     static regmatch_t *re_Oops_eip_other_pmatch;
  663.     static const char procname[] = "Oops_eip";
  664.     /* Oops 'EIP:' line for sparc, actually PSR followed by PC */
  665.     RE_COMPILE(&re_Oops_eip_sparc,
  666.     "^PSR: [0-9a-fA-F]+ PC: " UNBRACKETED_ADDRESS,
  667. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  668. &re_Oops_eip_sparc_pmatch);
  669.     i = regexec(&re_Oops_eip_sparc, line, re_Oops_eip_sparc.re_nsub+1,
  670. re_Oops_eip_sparc_pmatch, 0);
  671.     DEBUG(4, "regexec sparc %d", i);
  672.     if (i == 0) {
  673. re_string_check(re_Oops_eip_sparc.re_nsub+1, string_max,
  674.     procname);
  675. re_strings(&re_Oops_eip_sparc, line, re_Oops_eip_sparc_pmatch,
  676.     string);
  677. return((*string)[re_Oops_eip_sparc.re_nsub]);
  678.     }
  679.     /* Oops 'EIP:' line for sparc64, actually TSTATE followed by TPC */
  680.     RE_COMPILE(&re_Oops_eip_sparc64,
  681.     "^TSTATE: [0-9a-fA-F]{16} TPC: " UNBRACKETED_ADDRESS,
  682. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  683. &re_Oops_eip_sparc64_pmatch);
  684.     re_string_check(re_Oops_eip_sparc64.re_nsub+1, string_max, procname);
  685.     i = regexec(&re_Oops_eip_sparc64, line, re_Oops_eip_sparc64.re_nsub+1,
  686. re_Oops_eip_sparc64_pmatch, 0);
  687.     DEBUG(4, "regexec sparc64 %d", i);
  688.     if (i == 0) {
  689. /* Special case for sparc64.  If the output target is defaulting to the
  690.  * same format as ksymoops then the default is wrong, kernel is 64 bit,
  691.  * ksymoops is 32 bit.  When we see an EIP from sparc64, set the correct
  692.  * default.
  693.  */
  694. if (!options->target && !options->architecture &&
  695.     strcmp(bfd_get_target(ibfd), "elf32-sparc")) {
  696.     options->target = "elf64-sparc";
  697.     options->architecture = "sparc:v9a";
  698. }
  699. re_strings(&re_Oops_eip_sparc64, line, re_Oops_eip_sparc64_pmatch,
  700.     string);
  701. return((*string)[re_Oops_eip_sparc64.re_nsub]);
  702.     }
  703.     /* Oops 'EIP:' line for PPC, all over the place */
  704.     RE_COMPILE(&re_Oops_eip_ppc,
  705.     "("
  706.       "kernel pc "
  707.       "|trap at PC: "
  708.       "|bad area pc "
  709.       "|NIP: "
  710.     ")"
  711.     UNBRACKETED_ADDRESS,
  712. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  713. &re_Oops_eip_ppc_pmatch);
  714.     i = regexec(&re_Oops_eip_ppc, line, re_Oops_eip_ppc.re_nsub+1,
  715. re_Oops_eip_ppc_pmatch, 0);
  716.     DEBUG(4, "regexec ppc %d", i);
  717.     if (i == 0) {
  718. re_string_check(re_Oops_eip_ppc.re_nsub+1, string_max,
  719.     procname);
  720. re_strings(&re_Oops_eip_ppc, line, re_Oops_eip_ppc_pmatch,
  721.     string);
  722. return((*string)[re_Oops_eip_ppc.re_nsub]);
  723.     }
  724.     /* Oops 'EIP:' line for mips, epc, optional white space, ':',
  725.      * optional white space, unbracketed address.
  726.      */
  727.     RE_COMPILE(&re_Oops_eip_mips,
  728.     "^epc *:+ *"
  729.     UNBRACKETED_ADDRESS,
  730. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  731. &re_Oops_eip_mips_pmatch);
  732.     i = regexec(&re_Oops_eip_mips, line, re_Oops_eip_mips.re_nsub+1,
  733. re_Oops_eip_mips_pmatch, 0);
  734.     DEBUG(4, "regexec mips %d", i);
  735.     if (i == 0) {
  736. re_string_check(re_Oops_eip_mips.re_nsub+1, string_max,
  737.     procname);
  738. re_strings(&re_Oops_eip_mips, line, re_Oops_eip_mips_pmatch,
  739.     string);
  740. return((*string)[re_Oops_eip_mips.re_nsub]);
  741.     }
  742.     /* Oops 'IP' line for ia64, space, ip, optional white space, ':',
  743.      * optional white space, bracketed address.
  744.      */
  745.     RE_COMPILE(&re_Oops_eip_ia64,
  746.     " ip *:+ *"
  747.     BRACKETED_ADDRESS,
  748. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  749. &re_Oops_eip_ia64_pmatch);
  750.     i = regexec(&re_Oops_eip_ia64, line, re_Oops_eip_ia64.re_nsub+1,
  751. re_Oops_eip_ia64_pmatch, 0);
  752.     DEBUG(4, "regexec eip_ia64 %d", i);
  753.     if (i == 0) {
  754. re_string_check(re_Oops_eip_ia64.re_nsub+1, string_max,
  755.     procname);
  756. re_strings(&re_Oops_eip_ia64, line, re_Oops_eip_ia64_pmatch,
  757.     string);
  758. return((*string)[re_Oops_eip_ia64.re_nsub]);
  759.     }
  760.     /* MCA 'IP' line for ia64.  [x]ip at start of line, space, '('regname'),
  761.      * spaces, :, space, 0x, UNBRACKETED_ADDRESS.
  762.      */
  763.     RE_COMPILE(&re_Oops_mca_ip_ia64,
  764.     "[xi]ip *\([^)]*\) *: *"
  765.     "0x" UNBRACKETED_ADDRESS,
  766. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  767. &re_Oops_mca_ip_ia64_pmatch);
  768.     i = regexec(&re_Oops_mca_ip_ia64, line, re_Oops_mca_ip_ia64.re_nsub+1,
  769. re_Oops_mca_ip_ia64_pmatch, 0);
  770.     DEBUG(4, "regexec mca_ip_ia64 %d", i);
  771.     if (i == 0) {
  772. re_string_check(re_Oops_mca_ip_ia64.re_nsub+1, string_max,
  773.     procname);
  774. re_strings(&re_Oops_mca_ip_ia64, line, re_Oops_mca_ip_ia64_pmatch,
  775.     string);
  776. return((*string)[re_Oops_mca_ip_ia64.re_nsub]);
  777.     }
  778.     /* SGI kdb backtrace EIP.  At start of line, 0x unbracketed
  779.      * address, 0x unbracketed address, anything, '+0x'.  The second
  780.      * unbracketed address is the EIP.
  781.      * The initial kdb reports has lines like
  782.      * Entering kdb on processor 2 due to panic @ 0x5005f426
  783.      */
  784.     RE_COMPILE(&re_Oops_eip_kdb,
  785.     "(" /* 1 */
  786.       "^0x" UNBRACKETED_ADDRESS /* 2 */
  787.       "0x" UNBRACKETED_ADDRESS /* 3 */
  788.       ".*+0x"
  789.     ")"
  790.     "|(" /* 4 */
  791.       "^Entering kdb on processor.*0x"
  792.       UNBRACKETED_ADDRESS /* 5 */
  793.     ")",
  794. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  795. &re_Oops_eip_kdb_pmatch);
  796.     i = regexec(&re_Oops_eip_kdb, line, re_Oops_eip_kdb.re_nsub+1,
  797. re_Oops_eip_kdb_pmatch, 0);
  798.     DEBUG(4, "regexec kdb %d", i);
  799.     if (i == 0) {
  800. re_string_check(re_Oops_eip_kdb.re_nsub+1, string_max,
  801.     procname);
  802. re_strings(&re_Oops_eip_kdb, line, re_Oops_eip_kdb_pmatch,
  803.     string);
  804. if ((*string)[3] && *((*string)[3]))
  805.     return((*string)[3]);
  806. if ((*string)[5] && *((*string)[5]))
  807.     return((*string)[5]);
  808.     }
  809.     /* Oops 'IRP' line for CRIS: "^IRP: " unbracketed address.
  810.      * Keep spacing optional.
  811.      */
  812.     RE_COMPILE(&re_Oops_eip_cris,
  813.     "^ *IRP *: *"
  814.     UNBRACKETED_ADDRESS,
  815. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  816. &re_Oops_eip_cris_pmatch);
  817.     i = regexec(&re_Oops_eip_cris, line, re_Oops_eip_cris.re_nsub+1,
  818. re_Oops_eip_cris_pmatch, 0);
  819.     DEBUG(4, "regexec cris %d", i);
  820.     if (i == 0) {
  821. re_string_check(re_Oops_eip_cris.re_nsub+1, string_max,
  822.     procname);
  823. re_strings(&re_Oops_eip_cris, line, re_Oops_eip_cris_pmatch,
  824.     string);
  825. return((*string)[re_Oops_eip_cris.re_nsub]);
  826.     }
  827.     /* Oops 'EIP:' line for other architectures */
  828.     RE_COMPILE(&re_Oops_eip_other,
  829. "^("
  830.   "EIP: +.*" /* i386 */
  831.   "|RIP: +.*" /* x86_64 */
  832.   "|PC *= *" /* m68k, alpha */
  833.   "|pc *: *" /* arm */
  834. ")"
  835. BRACKETED_ADDRESS
  836. ,
  837. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  838. &re_Oops_eip_other_pmatch);
  839.     i = regexec(&re_Oops_eip_other, line, re_Oops_eip_other.re_nsub+1,
  840. re_Oops_eip_other_pmatch, 0);
  841.     DEBUG(4, "regexec other %d", i);
  842.     if (i == 0) {
  843. re_string_check(re_Oops_eip_other.re_nsub+1, string_max,
  844.     procname);
  845. re_strings(&re_Oops_eip_other, line, re_Oops_eip_other_pmatch,
  846.     string);
  847. return((*string)[re_Oops_eip_other.re_nsub]);
  848.     }
  849.     return(NULL);
  850. }
  851. /* Look for the arm lr line, returns start of the relevant hex value */
  852. static char *Oops_arm_lr(const char *line, char ***string, int string_max)
  853. {
  854.     int i;
  855.     static regex_t     re_Oops_arm_lr;
  856.     static regmatch_t *re_Oops_arm_lr_pmatch;
  857.     static const char procname[] = "Oops_arm_lr";
  858.     RE_COMPILE(&re_Oops_arm_lr,
  859.     "pc *: *" BRACKETED_ADDRESS /* 1 */
  860.     " *lr *: *" BRACKETED_ADDRESS, /* 2 */
  861. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  862. &re_Oops_arm_lr_pmatch);
  863.     i = regexec(&re_Oops_arm_lr, line, re_Oops_arm_lr.re_nsub+1,
  864. re_Oops_arm_lr_pmatch, 0);
  865.     DEBUG(4, "regexec %d", i);
  866.     if (i == 0) {
  867. re_string_check(re_Oops_arm_lr.re_nsub+1, string_max, procname);
  868. re_strings(&re_Oops_arm_lr, line, re_Oops_arm_lr_pmatch,
  869.     string);
  870. return((*string)[re_Oops_arm_lr.re_nsub]);
  871.     }
  872.     return(NULL);
  873. }
  874. /* Set the arm lr from the lr line */
  875. static void Oops_set_arm_lr(const char *value, SYMBOL_SET *ss)
  876. {
  877.     static const char procname[] = "Oops_set_arm_lr";
  878.     addr_t ra;
  879.     ra = hexstring(value);
  880.     if (errno) {
  881. ERROR(" Invalid hex value in ra line, ignored - '%s'", value);
  882. perror(prefix);
  883. ra = 0;
  884.     }
  885.     add_symbol_n(ss, ra, 'R', 1, ">>LR; ");
  886. }
  887. /* Look for the alpha ra line, returns start of the relevant hex value */
  888. static char *Oops_alpha_ra(const char *line, char ***string, int string_max)
  889. {
  890.     int i;
  891.     static regex_t     re_Oops_alpha_ra;
  892.     static regmatch_t *re_Oops_alpha_ra_pmatch;
  893.     static const char procname[] = "Oops_alpha_ra";
  894.     RE_COMPILE(&re_Oops_alpha_ra,
  895.     "pc *= *" BRACKETED_ADDRESS /* 1 */
  896.     " *ra *= *" BRACKETED_ADDRESS, /* 2 */
  897. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  898. &re_Oops_alpha_ra_pmatch);
  899.     i = regexec(&re_Oops_alpha_ra, line, re_Oops_alpha_ra.re_nsub+1,
  900. re_Oops_alpha_ra_pmatch, 0);
  901.     DEBUG(4, "regexec %d", i);
  902.     if (i == 0) {
  903. re_string_check(re_Oops_alpha_ra.re_nsub+1, string_max, procname);
  904. re_strings(&re_Oops_alpha_ra, line, re_Oops_alpha_ra_pmatch,
  905.     string);
  906. return((*string)[re_Oops_alpha_ra.re_nsub]);
  907.     }
  908.     return(NULL);
  909. }
  910. /* Set the alpha ra from the ra line */
  911. static void Oops_set_alpha_ra(const char *value, SYMBOL_SET *ss)
  912. {
  913.     static const char procname[] = "Oops_set_alpha_ra";
  914.     addr_t ra;
  915.     ra = hexstring(value);
  916.     if (errno) {
  917. ERROR(" Invalid hex value in ra line, ignored - '%s'", value);
  918. perror(prefix);
  919. ra = 0;
  920.     }
  921.     add_symbol_n(ss, ra, 'R', 1, ">>RA; ");
  922. }
  923. /* Look for the alpha spinlock stuck line, returns TRUE with string[1]
  924.  * containing the PC, string[2] containing the previous PC.
  925.  */
  926. static int Oops_eip_alpha_spinlock(const char *line, char ***string,
  927.    int string_max, OPTIONS *options)
  928. {
  929.     int i;
  930.     static regex_t     re_Oops_eip_alpha_spinlock;
  931.     static regmatch_t *re_Oops_eip_alpha_spinlock_pmatch;
  932.     static const char procname[] = "Oops_eip_alpha_spinlock";
  933.     RE_COMPILE(&re_Oops_eip_alpha_spinlock,
  934.     "^spinlock stuck at " UNBRACKETED_ADDRESS
  935.     ".*owner.*at " UNBRACKETED_ADDRESS,
  936. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  937. &re_Oops_eip_alpha_spinlock_pmatch);
  938.     i = regexec(&re_Oops_eip_alpha_spinlock, line,
  939. re_Oops_eip_alpha_spinlock.re_nsub+1,
  940. re_Oops_eip_alpha_spinlock_pmatch, 0);
  941.     DEBUG(4, "regexec %d", i);
  942.     if (i == 0) {
  943. re_string_check(re_Oops_eip_alpha_spinlock.re_nsub+1, string_max,
  944.     procname);
  945. re_strings(&re_Oops_eip_alpha_spinlock, line,
  946.     re_Oops_eip_alpha_spinlock_pmatch, string);
  947. return(1);
  948.     }
  949.     return(0);
  950. }
  951. /* Look for the sparc spinlock stuck line, returns TRUE with string[1]
  952.  * containing the lock address, string[2] containing the caller PC,
  953.  * string[3] containing the owning PC.
  954.  */
  955. static int Oops_eip_sparc_spinlock(const char *line, char ***string,
  956.    int string_max, OPTIONS *options)
  957. {
  958.     int i;
  959.     static regex_t     re_Oops_eip_sparc_spinlock;
  960.     static regmatch_t *re_Oops_eip_sparc_spinlock_pmatch;
  961.     static const char procname[] = "Oops_eip_sparc_spinlock";
  962.     RE_COMPILE(&re_Oops_eip_sparc_spinlock,
  963.     "^spin_lock[^ ]*\(" UNBRACKETED_ADDRESS
  964.     ".*stuck at *" UNBRACKETED_ADDRESS
  965.     ".*PC\(" UNBRACKETED_ADDRESS,
  966. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  967. &re_Oops_eip_sparc_spinlock_pmatch);
  968.     i = regexec(&re_Oops_eip_sparc_spinlock, line,
  969. re_Oops_eip_sparc_spinlock.re_nsub+1,
  970. re_Oops_eip_sparc_spinlock_pmatch, 0);
  971.     DEBUG(4, "regexec %d", i);
  972.     if (i == 0) {
  973. re_string_check(re_Oops_eip_sparc_spinlock.re_nsub+1, string_max,
  974.     procname);
  975. re_strings(&re_Oops_eip_sparc_spinlock, line,
  976.     re_Oops_eip_sparc_spinlock_pmatch, string);
  977. return(1);
  978.     }
  979.     return(0);
  980. }
  981. /* Look for the mips ra line, returns start of the relevant hex value */
  982. static char *Oops_mips_ra(const char *line, char ***string, int string_max)
  983. {
  984.     int i;
  985.     static regex_t     re_Oops_mips_ra;
  986.     static regmatch_t *re_Oops_mips_ra_pmatch;
  987.     static const char procname[] = "Oops_mips_ra";
  988.     /* Oops 'ra:' line for mips, ra, optional white space, one or
  989.      * more '=', optional white space, unbracketed address.
  990.      */
  991.     RE_COMPILE(&re_Oops_mips_ra,
  992.     "ra *=+ *"
  993.     UNBRACKETED_ADDRESS,
  994. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  995. &re_Oops_mips_ra_pmatch);
  996.     i = regexec(&re_Oops_mips_ra, line, re_Oops_mips_ra.re_nsub+1,
  997. re_Oops_mips_ra_pmatch, 0);
  998.     DEBUG(4, "regexec %d", i);
  999.     if (i == 0) {
  1000. re_string_check(re_Oops_mips_ra.re_nsub+1, string_max, procname);
  1001. re_strings(&re_Oops_mips_ra, line, re_Oops_mips_ra_pmatch,
  1002.     string);
  1003. return((*string)[re_Oops_mips_ra.re_nsub]);
  1004.     }
  1005.     return(NULL);
  1006. }
  1007. /* Set the mips ra from the ra line */
  1008. static void Oops_set_mips_ra(const char *value, SYMBOL_SET *ss)
  1009. {
  1010.     static const char procname[] = "Oops_set_mips_ra";
  1011.     addr_t ra;
  1012.     ra = hexstring(value);
  1013.     if (errno) {
  1014. ERROR(" Invalid hex value in ra line, ignored - '%s'", value);
  1015. perror(prefix);
  1016. ra = 0;
  1017.     }
  1018.     add_symbol_n(ss, ra, 'R', 1, ">>RA; ");
  1019. }
  1020. /* Extract mips registers. */
  1021. static void Oops_mips_regs(const char *line, SYMBOL_SET *ss, const OPTIONS *options)
  1022. {
  1023.     int i, reg_num;
  1024.     addr_t reg;
  1025.     char regname[7];
  1026.     char **string = NULL;
  1027.     const char *p;
  1028.     static regex_t     re_Oops_mips_regs;
  1029.     static regmatch_t *re_Oops_mips_regs_pmatch;
  1030.     static const char procname[] = "Oops_mips_regs";
  1031.     RE_COMPILE(&re_Oops_mips_regs,
  1032.     "^(\$[0-9]{1,2}) *: *" /* 1 */
  1033.     UNBRACKETED_ADDRESS /* 2 */
  1034.     ,
  1035. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1036. &re_Oops_mips_regs_pmatch);
  1037.     i = regexec(&re_Oops_mips_regs, line, re_Oops_mips_regs.re_nsub+1,
  1038. re_Oops_mips_regs_pmatch, 0);
  1039.     DEBUG(4, "regexec %d", i);
  1040.     if (i)
  1041. return;
  1042.     p = line + re_Oops_mips_regs_pmatch[0].rm_so + 1;
  1043.     reg_num = strtoul(p, NULL, 10);
  1044.     p = line + re_Oops_mips_regs_pmatch[2].rm_so;
  1045.     /* Loop over unbracketed addresses */
  1046.     while (1) {
  1047. if (regexec(&re_unbracketed_address, p, re_unbracketed_address.re_nsub+1,
  1048.     re_unbracketed_address_pmatch, 0) == 0) {
  1049.     re_strings(&re_unbracketed_address, p, re_unbracketed_address_pmatch, &string);
  1050.     reg = hexstring(string[1]); /* contents */
  1051.     if (errno) {
  1052. ERROR(" Invalid hex value in register line, ignored - '%s'",
  1053.       string[1]);
  1054. perror(prefix);
  1055. break;
  1056.     }
  1057.     reg = Oops_truncate_address(reg, options);
  1058.     snprintf(regname, sizeof(regname), ">>$%d;", reg_num);
  1059.     add_symbol_n(ss, reg, 'R', 1, regname);
  1060.     p += re_unbracketed_address_pmatch[0].rm_eo;
  1061.     ++reg_num;
  1062.     if (reg_num == 26)
  1063. reg_num += 2; /* skip k0, k1 */
  1064. }
  1065. else
  1066.     break;
  1067.     }
  1068.     if (*p)
  1069. WARNING("garbage '%s' at end of mips register line ignored", p);
  1070.     re_strings_free(&re_unbracketed_address, &string);
  1071. }
  1072. /* Look for the ia64 b0 line and set all the values */
  1073. static void Oops_set_ia64_b0(const char *line, char ***string, int string_max, SYMBOL_SET *ss)
  1074. {
  1075.     int i;
  1076.     addr_t b;
  1077.     char label[6];
  1078.     static regex_t     re_Oops_ia64_b0;
  1079.     static regmatch_t *re_Oops_ia64_b0_pmatch;
  1080.     static const char procname[] = "Oops_ia64_b0";
  1081.     /* Oops 'b0' line for ia64, b0 : unbracketed address, may be
  1082.      * repeated for b6, b7.  MCA has b0 '('regname')' : 0x unbracketed address.
  1083.      */
  1084.     RE_COMPILE(&re_Oops_ia64_b0,
  1085.     "^b[0-7] *(\([^)]*\) *)?: *(0x)?"
  1086.     UNBRACKETED_ADDRESS,
  1087. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1088. &re_Oops_ia64_b0_pmatch);
  1089.     /* Scan entire line for b0, b6, b7 */
  1090.     while(1) {
  1091. i = regexec(&re_Oops_ia64_b0, line, re_Oops_ia64_b0.re_nsub+1,
  1092.     re_Oops_ia64_b0_pmatch, 0);
  1093. DEBUG(4, "regexec %d", i);
  1094. if (i)
  1095.     break;
  1096. re_string_check(re_Oops_ia64_b0.re_nsub+1, string_max, procname);
  1097. re_strings(&re_Oops_ia64_b0, line, re_Oops_ia64_b0_pmatch, string);
  1098. strcpy(label, ">>bx; ");
  1099. label[3] = line[1]; /* register number */
  1100. b = hexstring((*string)[re_Oops_ia64_b0.re_nsub]);
  1101. if (errno) {
  1102.     ERROR(" Invalid hex value in b%c line, ignored - '%s'",
  1103. line[1], (*string)[re_Oops_ia64_b0.re_nsub]);
  1104.     perror(prefix);
  1105.     b = 0;
  1106. }
  1107. add_symbol_n(ss, b, 'R', 1, label);
  1108. line += re_Oops_ia64_b0_pmatch[0].rm_eo;
  1109.     }
  1110. }
  1111. /* Look for the sparc register dump lines end */
  1112. static int Oops_sparc_regdump(const char *line, char ***string)
  1113. {
  1114.     int i;
  1115.     static regex_t     re_Oops_sparc_regdump;
  1116.     static regmatch_t *re_Oops_sparc_regdump_pmatch;
  1117.     static const char procname[] = "Oops_sparc_regdump";
  1118.     RE_COMPILE(&re_Oops_sparc_regdump,
  1119.     "^("
  1120. "i[04]: "
  1121. "|Instruction DUMP: "
  1122. "|Caller\["
  1123.     ")",
  1124. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1125. &re_Oops_sparc_regdump_pmatch);
  1126.     i = regexec(&re_Oops_sparc_regdump, line, re_Oops_sparc_regdump.re_nsub+1,
  1127. re_Oops_sparc_regdump_pmatch, 0);
  1128.     DEBUG(4, "regexec %d", i);
  1129.     if (i == 0)
  1130. return 1;
  1131.     return 0;
  1132. }
  1133. /* Look for the i370 PSW line, returns start of the relevant hex value */
  1134. static char *Oops_i370_psw(const char *line, char ***string, int string_max)
  1135. {
  1136.     int i;
  1137.     static regex_t     re_Oops_i370_psw;
  1138.     static regmatch_t *re_Oops_i370_psw_pmatch;
  1139.     static const char procname[] = "Oops_i370_psw";
  1140.     /* Oops 'PSW:' line for i370, PSW at start of line, value is second
  1141.      * address.
  1142.      */
  1143.     RE_COMPILE(&re_Oops_i370_psw,
  1144.     "^PSW *flags: *"
  1145.     UNBRACKETED_ADDRESS /* flags */
  1146.     " *PSW addr: *"
  1147.     UNBRACKETED_ADDRESS,
  1148. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1149. &re_Oops_i370_psw_pmatch);
  1150.     i = regexec(&re_Oops_i370_psw, line, re_Oops_i370_psw.re_nsub+1,
  1151. re_Oops_i370_psw_pmatch, 0);
  1152.     DEBUG(4, "regexec %d", i);
  1153.     if (i == 0) {
  1154. re_string_check(re_Oops_i370_psw.re_nsub+1, string_max, procname);
  1155. re_strings(&re_Oops_i370_psw, line, re_Oops_i370_psw_pmatch,
  1156.     string);
  1157. return((*string)[re_Oops_i370_psw.re_nsub]);
  1158.     }
  1159.     return(NULL);
  1160. }
  1161. /* Set the i370 PSW from the PSW line */
  1162. static void Oops_set_i370_psw(const char *value, SYMBOL_SET *ss,
  1163.       const char *me, const bfd *ibfd,
  1164.       OPTIONS *options)
  1165. {
  1166.     static const char procname[] = "Oops_set_i370_psw";
  1167.     addr_t PSW;
  1168.     /* Ensure target is set so EIP text is correct */
  1169.     Oops_set_default_ta(me, ibfd, options);
  1170.     PSW = hexstring(value);
  1171.     if (errno) {
  1172. ERROR(" Invalid hex value in PSW line, ignored - '%s'", value);
  1173. perror(prefix);
  1174. PSW = 0;
  1175.     }
  1176.     PSW = Oops_truncate_address(PSW, options);
  1177.     add_symbol_n(ss, PSW, 'E', 1, ">>PSW;");
  1178. }
  1179. /* Look for the s390 PSW line, returns start of the relevant hex value */
  1180. static char *Oops_s390_psw(const char *line, char ***string, int string_max)
  1181. {
  1182.     int i;
  1183.     static regex_t     re_Oops_s390_psw;
  1184.     static regmatch_t *re_Oops_s390_psw_pmatch;
  1185.     static const char procname[] = "Oops_s390_psw";
  1186.     /* Oops 'Kernel PSW:' line for s390, PSW at start of line, value is
  1187.      * second address.
  1188.      */
  1189.     RE_COMPILE(&re_Oops_s390_psw,
  1190.     "^Kernel PSW: *"
  1191.     UNBRACKETED_ADDRESS /* flags */
  1192.     UNBRACKETED_ADDRESS,
  1193. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1194. &re_Oops_s390_psw_pmatch);
  1195.     i = regexec(&re_Oops_s390_psw, line, re_Oops_s390_psw.re_nsub+1,
  1196. re_Oops_s390_psw_pmatch, 0);
  1197.     DEBUG(4, "regexec %d", i);
  1198.     if (i == 0) {
  1199. re_string_check(re_Oops_s390_psw.re_nsub+1, string_max, procname);
  1200. re_strings(&re_Oops_s390_psw, line, re_Oops_s390_psw_pmatch,
  1201.     string);
  1202. return((*string)[re_Oops_s390_psw.re_nsub]);
  1203.     }
  1204.     return(NULL);
  1205. }
  1206. /* No need for Oops_set_s390_psw, can use Oops_set_i370_psw for both */
  1207. #define Oops_set_s390_psw(line, string, me, ibfd, options) 
  1208. Oops_set_i370_psw(line, string, me, ibfd, options)
  1209. /* Extract ppc registers. */
  1210. static void Oops_ppc_regs(const char *line, SYMBOL_SET *ss, const OPTIONS *options)
  1211. {
  1212.     int i, reg_num;
  1213.     addr_t reg;
  1214.     char regname[9];
  1215.     char **string = NULL;
  1216.     const char *p;
  1217.     static regex_t     re_Oops_ppc_regs;
  1218.     static regmatch_t *re_Oops_ppc_regs_pmatch;
  1219.     static const char procname[] = "Oops_ppc_regs";
  1220.     RE_COMPILE(&re_Oops_ppc_regs,
  1221.     "^(GPR[0-9]{1,2}) *: *" /* 1 */
  1222.     UNBRACKETED_ADDRESS /* 2 */
  1223.     ,
  1224. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1225. &re_Oops_ppc_regs_pmatch);
  1226.     i = regexec(&re_Oops_ppc_regs, line, re_Oops_ppc_regs.re_nsub+1,
  1227. re_Oops_ppc_regs_pmatch, 0);
  1228.     DEBUG(4, "regexec %d", i);
  1229.     if (i)
  1230. return;
  1231.     p = line + re_Oops_ppc_regs_pmatch[0].rm_so + 3;
  1232.     reg_num = strtoul(p, NULL, 10);
  1233.     p = line + re_Oops_ppc_regs_pmatch[2].rm_so;
  1234.     /* Loop over unbracketed addresses */
  1235.     while (1) {
  1236. if (regexec(&re_unbracketed_address, p, re_unbracketed_address.re_nsub+1,
  1237.     re_unbracketed_address_pmatch, 0) == 0) {
  1238.     re_strings(&re_unbracketed_address, p, re_unbracketed_address_pmatch, &string);
  1239.     reg = hexstring(string[1]); /* contents */
  1240.     if (errno) {
  1241. ERROR(" Invalid hex value in register line, ignored - '%s'",
  1242.       string[1]);
  1243. perror(prefix);
  1244. break;
  1245.     }
  1246.     reg = Oops_truncate_address(reg, options);
  1247.     snprintf(regname, sizeof(regname), ">>GPR%d;", reg_num);
  1248.     add_symbol_n(ss, reg, 'R', 1, regname);
  1249.     p += re_unbracketed_address_pmatch[0].rm_eo;
  1250.     ++reg_num;
  1251. }
  1252. else
  1253.     break;
  1254.     }
  1255.     if (*p)
  1256. WARNING("garbage '%s' at end of ppc register line ignored", p);
  1257.     re_strings_free(&re_unbracketed_address, &string);
  1258. }
  1259. /* Look for the Trace multilines :(.  Returns start of addresses. */
  1260. static const char *Oops_trace(const char *line)
  1261. {
  1262.     int i;
  1263.     const char *start = NULL;
  1264.     static int trace_line = 0;
  1265.     static regex_t     re_Oops_trace;
  1266.     static regmatch_t *re_Oops_trace_pmatch;
  1267.     static const char procname[] = "Oops_trace";
  1268.     /* Oops 'Trace' lines.  The ikd patch adds "(nn)" for the stack frame size
  1269.      * after each trace entry, it should appear on the same line as the
  1270.      * bracketed address.  Alas users have been known to split lines so "(nn)"
  1271.      * appears at the start of the continuation line, look for that as well.
  1272.      * Life would be so much easier without users.
  1273.      * The person who did the s390 trace obviously did not like any of the ways
  1274.      * that other Linux kernels report problems so they invented a system all on
  1275.      * their own.  It is different from the i370 trace and even more ambiguous
  1276.      * than the other trace formats.  That is what happens when code is written
  1277.      * in secret!
  1278.      */
  1279.     RE_COMPILE(&re_Oops_trace,
  1280.     "^("      /* 1 */
  1281.     "(Call Trace: *)"      /* 2 */
  1282.     /* alpha */     "|(Trace:)"      /* 3 */
  1283.     /* various */   "|(" BRACKETED_ADDRESS ")"      /* 4,5 */
  1284.     /* ppc */     "|(Call backtrace:)"      /* 6 */
  1285.     /* ppc, s390 */ "|" UNBRACKETED_ADDRESS      /* 7 */
  1286.     /* arm */     "|Function entered at (" BRACKETED_ADDRESS ")"   /* 8,9 */
  1287.     /* sparc64 */   "|Caller\[" UNBRACKETED_ADDRESS "\]"      /* 10 */
  1288.     /* i386 */     "|(" REVBRACKETED_ADDRESS ")"      /* 11,12 */
  1289.     /* ikd patch */ "|(\([0-9]+\) *(" BRACKETED_ADDRESS "))"      /* 13,14,15 */
  1290.     /* i370 */     "|([0-9]+ +base=0x" UNBRACKETED_ADDRESS ")"      /* 16,17 */
  1291.     /* s390 */     "|(Kernel BackChain.*)"                          /* 18    */
  1292.     ")",
  1293. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1294. &re_Oops_trace_pmatch);
  1295.     i = regexec(&re_Oops_trace, line, re_Oops_trace.re_nsub+1,
  1296. re_Oops_trace_pmatch, 0);
  1297.     DEBUG(4, "regexec %d", i);
  1298.     if (i == 0) {
  1299. #undef MATCHED
  1300. #define MATCHED(n) (re_Oops_trace_pmatch[n].rm_so != -1)
  1301. if (MATCHED(2) || MATCHED(3)) {
  1302.     /* Most start lines */
  1303.     trace_line = 1;
  1304.     start = line + re_Oops_trace_pmatch[0].rm_eo;
  1305. }
  1306. else if (MATCHED(6)) {
  1307.     /* ppc start line, not a bracketed address, just an address */
  1308.     trace_line = 2;     /* ppc */
  1309.     start = line + re_Oops_trace_pmatch[0].rm_eo;
  1310. }
  1311. else if (MATCHED(8)) {
  1312.     /* arm only line, two bracketed addresses on each line */
  1313.     trace_line = 3;
  1314.     start = line + re_Oops_trace_pmatch[8].rm_so;
  1315. }
  1316. else if (MATCHED(10)) {
  1317.     /* sparc64 only line, one unbracketed address */
  1318.     trace_line = 3;
  1319.     start = line + re_Oops_trace_pmatch[10].rm_so;
  1320. }
  1321. else if (MATCHED(17)) {
  1322.     /* i370 only line, one unbracketed address */
  1323.     trace_line = 3;
  1324.     start = line + re_Oops_trace_pmatch[17].rm_so;
  1325. }
  1326. else if (MATCHED(18)) {
  1327.     /* s390 only line, no addresses on this line */
  1328.     trace_line = 4;
  1329.     start = line + re_Oops_trace_pmatch[18].rm_eo;
  1330. }
  1331. else if (MATCHED(11)) {
  1332.     /* Reversed addresses for spinloops :( */
  1333.     trace_line = 1;
  1334.     start = line + re_Oops_trace_pmatch[11].rm_so;
  1335. }
  1336. else if (trace_line == 1 && MATCHED(4))
  1337.     /* Most continuation lines */
  1338.     start = line + re_Oops_trace_pmatch[4].rm_so;
  1339. else if (trace_line == 1 && MATCHED(14))
  1340.     /* incorrectly split trace lines from ikd patch */
  1341.     start = line + re_Oops_trace_pmatch[14].rm_so;
  1342. else if ((trace_line == 2 || trace_line == 4) && MATCHED(7))
  1343.     /* ppc/s390 continuation line */
  1344.     start = line + re_Oops_trace_pmatch[7].rm_so;
  1345. else
  1346.     trace_line = 0;
  1347.     }
  1348.     else
  1349. trace_line = 0;
  1350.     if (trace_line) {
  1351. if (trace_line == 3)
  1352.     trace_line = 0; /* no continuation lines */
  1353. return(start);
  1354.     }
  1355.     return(NULL);
  1356. }
  1357. /* Process a trace call line, extract addresses */
  1358. static void Oops_trace_line(const char *line, const char *p, SYMBOL_SET *ss,
  1359.     const OPTIONS *options)
  1360. {
  1361.     char **string = NULL;
  1362.     regex_t *pregex;
  1363.     regmatch_t *pregmatch;
  1364.     static regex_t     re_ikd;
  1365.     static regmatch_t *re_ikd_pmatch;
  1366.     static const char procname[] = "Oops_trace_line";
  1367.     /* ikd adds "(nn)" for stack frame size after each 'Trace' field. */
  1368.     RE_COMPILE(&re_ikd,
  1369.     "^(\([0-9]+\) *)",
  1370. REG_NEWLINE|REG_EXTENDED,
  1371. &re_ikd_pmatch);
  1372.     /* ppc/s390 does not bracket its addresses */
  1373.     if (isxdigit(*p)) {
  1374. pregex = &re_unbracketed_address;
  1375. pregmatch = re_unbracketed_address_pmatch;
  1376.     }
  1377.     else if (strncmp(p, "<[", 2) == 0) {
  1378. /* I hate special cases! */
  1379. pregex = &re_revbracketed_address;
  1380. pregmatch = re_revbracketed_address_pmatch;
  1381.     }
  1382.     else {
  1383. pregex = &re_bracketed_address;
  1384. pregmatch = re_bracketed_address_pmatch;
  1385.     }
  1386.     /* Loop over (un|rev)?bracketed addresses */
  1387.     while (1) {
  1388. if (regexec(pregex, p, pregex->re_nsub+1, pregmatch, 0) == 0) {
  1389.     addr_t addr;
  1390.     re_strings(pregex, p, pregmatch, &string);
  1391.     addr = hexstring(string[1]);
  1392.     addr = Oops_truncate_address(addr, options);
  1393.     add_symbol_n(ss, addr, 'T', 1, "Trace;");
  1394.     p += pregmatch[0].rm_eo;
  1395. }
  1396. else if (strncmp(p, "from ", 5) == 0)
  1397.     p += 5;     /* arm does "address from address" */
  1398. else if (regexec(&re_ikd, p, re_ikd.re_nsub+1, re_ikd_pmatch, 0) == 0)
  1399.     p += re_ikd_pmatch[0].rm_eo;  /* step over ikd stack frame size */
  1400. else
  1401.     break;
  1402.     }
  1403.     if (*p && !strcmp(p, "..."))
  1404. WARNING("garbage '%s' at end of trace line ignored", p);
  1405.     re_strings_free(pregex, &string);
  1406. }
  1407. /* Decide if the line contains CRIS registers.  Returns first register name. */
  1408. static const char *Oops_cris_regs(const char *line)
  1409. {
  1410.     int i;
  1411.     static const char procname[] = "Oops_cris_regs";
  1412.     /* Note that most of the register dump, the r0: to oR10: lines, are
  1413.        handled by Oops_regs.  */
  1414.     RE_COMPILE(&re_Oops_cris_regs,
  1415.     "^(IRP|SRP|D?CCR|USP|MOF): *" UNBRACKETED_ADDRESS,
  1416. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1417. &re_Oops_cris_regs_pmatch);
  1418.     i = regexec(&re_Oops_cris_regs, line, re_Oops_cris_regs.re_nsub+1,
  1419. re_Oops_cris_regs_pmatch, 0);
  1420.     DEBUG(4, "regexec %d", i);
  1421.     if (i == 0)
  1422. return(line + re_Oops_cris_regs_pmatch[0].rm_so);
  1423.     return(NULL);
  1424. }
  1425. /* Process a CRIS register line, extract addresses */
  1426. static void Oops_set_cris_regs(const char *line, const char *p,
  1427.        SYMBOL_SET *ss, const OPTIONS *options)
  1428. {
  1429.     addr_t reg;
  1430.     char regname[7];
  1431.     char **string = NULL;
  1432.     static const char procname[] = "Oops_set_cris_regs";
  1433.     /* Loop over CRIS register names and unbracketed addresses.  */
  1434.     while (1) {
  1435. if (regexec(&re_Oops_cris_regs, p, re_Oops_cris_regs.re_nsub+1,
  1436.     re_Oops_cris_regs_pmatch, 0) == 0) {
  1437.     re_strings(&re_Oops_cris_regs, p, re_Oops_cris_regs_pmatch, &string);
  1438.     reg = hexstring(string[2]); /* contents */
  1439.     if (errno) {
  1440. ERROR(" Invalid hex value in CRIS register line, ignored - '%s'",
  1441.       string[2]);
  1442. perror(prefix);
  1443. reg = 0;
  1444.     }
  1445.     else {
  1446.       reg = Oops_truncate_address(reg, options);
  1447.       strcpy(regname, ">>");
  1448.       strncpy(regname+2, string[1], sizeof(regname)-3);
  1449.       strcat(regname, ";");
  1450.       add_symbol_n(ss, reg, 'R', 1, regname);
  1451.     }
  1452.     p += re_Oops_cris_regs_pmatch[0].rm_eo;
  1453. }
  1454. else
  1455.     break;
  1456.     }
  1457.     if (*p)
  1458. WARNING("garbage '%s' at end of CRIS register line ignored", p);
  1459.     re_strings_free(&re_Oops_cris_regs, &string);
  1460. }
  1461. /* Decide if the line contains s390 registers.  Returns first register value.
  1462.  * This is messier than the trace lines.  The heading is on one line followed by
  1463.  * the registers with *NO* keywords.  Fine for a dedicated JESMSG file, very
  1464.  * poor design for a multi-user log system.
  1465.  */
  1466. static const char *Oops_s390_regs(const char *line)
  1467. {
  1468.     int i;
  1469.     static regex_t     re_Oops_s390_regs;
  1470.     static regmatch_t *re_Oops_s390_regs_pmatch;
  1471.     static const char procname[] = "Oops_s390_regs";
  1472.     RE_COMPILE(&re_Oops_s390_regs,
  1473.     "^(Kernel GPRS.*)",
  1474. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1475. &re_Oops_s390_regs_pmatch);
  1476.     i = regexec(&re_Oops_s390_regs, line, re_Oops_s390_regs.re_nsub+1,
  1477. re_Oops_s390_regs_pmatch, 0);
  1478.     DEBUG(4, "regexec %d", i);
  1479.     if (i == 0) {
  1480. s390_reg_num = 0;  /* Start with R0 */
  1481. return(line + re_Oops_s390_regs_pmatch[0].rm_eo);
  1482.     }
  1483.     else if (s390_reg_num >= 0) /* Header already seen */ {
  1484. i = regexec(&re_unbracketed_address, line,
  1485.     re_unbracketed_address.re_nsub+1,
  1486.     re_unbracketed_address_pmatch, 0);
  1487. DEBUG(4, "regexec %d", i);
  1488. if (i == 0)
  1489.     return(line + re_unbracketed_address_pmatch[0].rm_so);
  1490.     }
  1491.     s390_reg_num = -1;  /* Not processing s390 registers */
  1492.     return(NULL);
  1493. }
  1494. /* Process a s390 register line, extract addresses */
  1495. static void Oops_set_s390_regs(const char *line, const char *p,
  1496.        SYMBOL_SET *ss, const OPTIONS *options)
  1497. {
  1498.     addr_t reg;
  1499.     char regname[7];
  1500.     char **string = NULL;
  1501.     static const char procname[] = "Oops_set_s390_regs";
  1502.     /* Loop over s390 unbracketed register values.  No keywords so we have to
  1503.      * synthesize the register numbers ourselves, yuck!
  1504.      */
  1505.     while (1) {
  1506. if (regexec(&re_unbracketed_address, p,
  1507.     re_unbracketed_address.re_nsub+1,
  1508.     re_unbracketed_address_pmatch, 0) == 0) {
  1509.     re_strings(&re_unbracketed_address, p,
  1510. re_unbracketed_address_pmatch, &string);
  1511.     reg = hexstring(string[1]); /* contents */
  1512.     if (errno) {
  1513. ERROR(" Invalid hex value in s390 register line, ignored - '%s'",
  1514.       string[1]);
  1515. perror(prefix);
  1516. reg = 0;
  1517.     }
  1518.     reg = Oops_truncate_address(reg, options);
  1519.     strcpy(regname, ">>");
  1520.     snprintf(regname, sizeof(regname), "r%-2d;  ", s390_reg_num);
  1521.     add_symbol_n(ss, reg, 'R', 1, regname);
  1522.     p += re_unbracketed_address_pmatch[0].rm_eo;
  1523.     ++s390_reg_num;
  1524. }
  1525. else
  1526.     break;
  1527.     }
  1528.     if (*p)
  1529. WARNING("garbage '%s' at end of s390 register line ignored", p);
  1530.     re_strings_free(&re_unbracketed_address, &string);
  1531. }
  1532. /* Do pattern matching to decide if the line should be printed.  When reading a
  1533.  * syslog containing multiple Oops, you need the intermediate data (registers,
  1534.  * tss etc.) to go with the decoded text.  Sets text to the start of the useful
  1535.  * text, after any prefix.  Note that any leading white space is treated as part
  1536.  * of the prefix, later routines do not see any indentation.
  1537.  *
  1538.  * Note: If a line is not printed, it will not be scanned for any other text.
  1539.  */
  1540. #ifdef TIME_RE
  1541. /* time the re code */
  1542. #include <sys/time.h>
  1543. struct timeval before, after;
  1544. long long diff[30];
  1545. int count[30];
  1546. #define START gettimeofday(&before, NULL);
  1547. #define DIFF(n) gettimeofday(&after, NULL); 
  1548. ++count[n]; 
  1549. diff[n] += (after.tv_sec - before.tv_sec)*1000001 + (after.tv_usec - before.tv_usec); 
  1550. before = after;
  1551. #else
  1552. #define START
  1553. #define DIFF(n)
  1554. #endif
  1555. static int Oops_print(const char *line, const char **text, char ***string,
  1556.       int string_max)
  1557. {
  1558.     int i, print = 0;
  1559.     static int stack_line = 0, trace_line = 0;
  1560.     static regex_t     re_Oops_prefix;
  1561.     static regmatch_t *re_Oops_prefix_pmatch;
  1562.     static regex_t     re_Oops_print_s;
  1563.     static regmatch_t *re_Oops_print_s_pmatch;
  1564.     static regex_t     re_Oops_print_a;
  1565.     static regmatch_t *re_Oops_print_a_pmatch;
  1566.     static const char procname[] = "Oops_print";
  1567.     START
  1568.     *text = line;
  1569.     /* Lines to be ignored.  For some reason the "amuse the user" print in
  1570.      * some die_if_kernel routines causes regexec to run very slowly.
  1571.      */
  1572.     if (strstr(*text, "\|/ ____ \|/")  ||
  1573. strstr(*text, ""@'/ ,. \`@"") ||
  1574. strstr(*text, ""@'/ .. \`@"") ||
  1575. strstr(*text, "/_| \__/ |_\")  ||
  1576. strstr(*text, "   \__U_/"))
  1577. return(1);  /* print but avoid regexec */
  1578.     DIFF(1);
  1579.     /* Trial and error with regex leads me to the following conclusions.
  1580.      *
  1581.      * regex does not like a lot of sub patterns that start with "^".  So split
  1582.      * the patterns into two groups, one set must appear at the start of the
  1583.      * line, the other set can appear anywhere.
  1584.      *
  1585.      * Lots of bracketed subexpressions really slows regex down.  Only use
  1586.      * brackets where absolutely necessary.  Examples are where you want to
  1587.      * extract matching substrings such as stack, call trace etc.  Or where
  1588.      * you have suboptions within a string, like the sparc die_if_kernel text.
  1589.      * Otherwise omit brackets, except that every re should have at least one
  1590.      * bracketed expression, that is how RE_COMPILE tells if the expression
  1591.      * has already been compiled.
  1592.      */
  1593.     /* Prefixes to be ignored.  These prefixes were originally done as
  1594.      * ^((pattern1)|(pattern2)|(pattern3))+  but that caused pathological
  1595.      * behaviour in regexec when faced with lines like
  1596.      *                     : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to)
  1597.      * Would you believe 11 seconds just to resolve that one line :(.  So just
  1598.      * look for one prefix at a time and loop until all prefixes are stripped.
  1599.      */
  1600.     RE_COMPILE(&re_Oops_prefix,
  1601.     "^(" /* start of line */
  1602.     " +" /* leading spaces */
  1603.     "|[^ ]{3} [ 0-9][0-9] [0-9]{2}:[0-9]{2}:[0-9]{2} "
  1604.       "[^ ]+ kernel: +" /* syslogd */
  1605.     "|<[0-9]+>" /* kmsg */
  1606.     "|[0-9]+\|[^|]+\|[^|]+\|[^|]+\|" /* syslog-ng */
  1607.     "|[0-9][AC] [0-9]{3} [0-9]{3}[cir][0-9]{2}:" /* SNIA */
  1608.     "\+" /* leading '+' */
  1609.     ")",
  1610. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1611. &re_Oops_prefix_pmatch);
  1612.     do {
  1613. i = regexec(&re_Oops_prefix, *text, re_Oops_prefix.re_nsub+1,
  1614.     re_Oops_prefix_pmatch, 0);
  1615. DEBUG(4, "regexec prefix %d", i);
  1616. if (i == 0)
  1617.     *text += re_Oops_prefix_pmatch[0].rm_eo;  /* step over prefix */
  1618.     } while (i == 0);
  1619.     DIFF(2);
  1620.     /* Lots of possibilities.  Expand as required for all architectures. */
  1621.     /* These patterns must appear at the start of the line, after stripping
  1622.      * the prefix above.
  1623.      *
  1624.      * The order below is required to handle multiline outupt.
  1625.      * string 2 is defined if the text is 'Stack from '.
  1626.      * string 3 is defined if the text is 'Stack: '.
  1627.      * string 4 is defined if the text might be a stack continuation.
  1628.      * string 5 is defined if the text is 'Call Trace: *'.
  1629.      * string 6 is defined if the text might be a trace continuation.
  1630.      * string 7 is the address part of the BRACKETED_ADDRESS.
  1631.      *
  1632.      * string 8 is defined if the text contains a version number.  No Oops
  1633.      * report contains this as of 2.1.125 but IMHO it should be added.  If
  1634.      * anybody wants to print a VERSION_nnnn line in their Oops, this code
  1635.      * is ready.
  1636.      *
  1637.      * string 9 is defined if the text is 'Trace:' (alpha).
  1638.      * string 10 is defined if the text is 'Call backtrace:' (ppc, i370).
  1639.      * string 11 is defined if the text is 'bh:' (i386).  Stack addresses are
  1640.      * on the next line.  In our typical inconsistent manner, the bh: stack
  1641.      * addresses are different from every other address, they are <[...]>
  1642.      * instead of [<...>] so define yet another re, string 12.  Sigh.
  1643.      *
  1644.      * The ikd patch adds "(nn)" for the stack frame size after each trace
  1645.      * entry, it should appear on the same line as the bracketed address.  Alas
  1646.      * users have been known to split lines so "(nn)" appears at the start of
  1647.      * the continuation line, look for that as well.  Life would be so much
  1648.      * easier without users.  Andi Kleen's multi cpu traceback patch adds the
  1649.      * module name as "(name)" after addresses.  Strings 13 and 14 are
  1650.      * a special case of strings 6 and 7 to handle "(nn)" and "(name)",
  1651.      * in fact anything in "()" between addresses is ignored.
  1652.      *
  1653.      * Both ppc and i370 use 'Call backtrace:' but the i370 data is completely
  1654.      * different from anything else.  It starts on a separate line and consists
  1655.      * of multiple lines, each containing a number (trace depth), base=, link=,
  1656.      * stack=.
  1657.      *
  1658.      * s390 decided to do their own thing instead of using the same format as
  1659.      * i370.  A bad case of "not invented here".  s390 data starts on a separate
  1660.      * line and consists of multiple addresses.
  1661.      *
  1662.      * The SGI kdb backtrace for ix86 prints EBP and EIP, one per line after the
  1663.      * header.
  1664.      *
  1665.      * Some strings indicate stack data (S), some indicate trace data (T).
  1666.      */
  1667.     RE_COMPILE(&re_Oops_print_s,
  1668.     /* arch type */ /* Required order */
  1669. "^(" /*  1 */
  1670.     /* i386 */     "(Stack: )" /*  2  S */
  1671.     /* m68k */     "|(Stack from )" /*  3  S */
  1672.     /* various */   "|([0-9a-fA-F]{4,})" /*  4  S,T */
  1673.     /* various */   "|(Call Trace: *)" /*  5  T */
  1674.     /* various */   "|(" BRACKETED_ADDRESS ")" /* 6,7 T */
  1675.     /* various */   "|(Version_[0-9]+)" /*  8 */
  1676.     /* alpha */     "|(Trace:)" /*  9  T */
  1677.     /* ppc, i370 */ "|(Call backtrace:)" /* 10  T */
  1678.     /* i386 */     "|(bh:)" /* 11  T */
  1679.     /* i386 */     "|" REVBRACKETED_ADDRESS /* 12  T */
  1680.     /* ikd/AK */    "|(\([^ ]+\) *" /* 13  T */
  1681.       BRACKETED_ADDRESS ")" /* 14    */
  1682.     /* i370 */     "|([0-9]+ +base=)" /* 15  T */
  1683.     /* s390 */     "|(Kernel BackChain)" /* 16  T */
  1684.     /* kdb ix86 */  "|EBP *EIP" /* 17  T */
  1685.     /* kdb ix86 */  "|0x" UNBRACKETED_ADDRESS "0x" UNBRACKETED_ADDRESS /* 18, 19 T */
  1686.     /* order does not matter from here on */
  1687.     /* various */   "|Process .*stackpage="
  1688.     /* various */   "|Code *: "
  1689.     /* various */   "|Kernel panic"
  1690.     /* various */   "|In swapper task"
  1691.     /* various */   "|kmem_free"
  1692.     /* various */   "|swapper"
  1693.     /* various */   "|Pid:"
  1694.     /* various */   "|r[0-9]{1,2} *[:=]" /* generic register dump */
  1695.     /* i386 2.0 */  "|Corrupted stack page"
  1696.     /* i386 */     "|invalid operand: "
  1697.     /* i386 */     "|Oops: "
  1698.     /* i386 */     "|Cpu:* +[0-9]"
  1699.     /* i386 */     "|current->tss"
  1700.     /* i386 */     "|\*pde +="
  1701.     /* i386 */     "|EIP: "
  1702.     /* i386 */     "|EFLAGS: "
  1703.     /* i386 */     "|eax: "
  1704.     /* i386 */     "|esi: "
  1705.     /* i386 */     "|ds: "
  1706.     /* i386 */     "|CR0: "
  1707.     /* i386 */     "|wait_on_"
  1708.     /* i386 */     "|irq: "
  1709.     /* i386 */     "|Stack dumps:"
  1710.     /* x86_64 */    "|RAX: "
  1711.     /* x86_64 */    "|RSP: "
  1712.     /* x86_64 */    "|RIP: "
  1713.     /* x86_64 */    "|RDX: "
  1714.     /* x86_64 */    "|RBP: "
  1715.     /* x86_64 */    "|FS: "
  1716.     /* x86_64 */    "|CS: "
  1717.     /* x86_64 */    "|CR2: "
  1718.     /* x86_64 */    "|PML4"
  1719.     /* m68k */     "|pc[:=]"
  1720.     /* m68k */     "|68060 access"
  1721.     /* m68k */     "|Exception at "
  1722.     /* m68k */     "|d[04]: "
  1723.     /* m68k */     "|Frame format="
  1724.     /* m68k */     "|wb [0-9] stat"
  1725.     /* m68k */     "|push data: "
  1726.     /* m68k */     "|baddr="
  1727.     /* any other m68K lines to print? */
  1728.     /* alpha */     "|Arithmetic fault"
  1729.     /* alpha */     "|Instruction fault"
  1730.     /* alpha */     "|Bad unaligned kernel"
  1731.     /* alpha */     "|Forwarding unaligned exception"
  1732.     /* alpha */     "|: unhandled unaligned exception"
  1733.     /* alpha */     "|pc *="
  1734.     /* alpha */     "|[rvtsa][0-9]+ *=" /* Changed from r to [vtsa] in 2.2.14 */
  1735.     /* alpha */     "|gp *="
  1736.     /* alpha */     "|spinlock stuck"
  1737.     /* any other alpha lines to print? */
  1738.     /* sparc */     "|tsk->"
  1739.     /* sparc */     "|PSR: "
  1740.     /* sparc */     "|[goli]0: "
  1741.     /* sparc */     "|Instruction DUMP: "
  1742.     /* sparc */     "|spin_lock"
  1743.     /* any other sparc lines to print? */
  1744.     /* sparc64 */   "|TSTATE: "
  1745.     /* sparc64 */   "|[goli]4: "
  1746.     /* sparc64 */   "|Caller\["
  1747.     /* sparc64 */   "|CPU\["
  1748.     /* any other sparc64 lines to print? */
  1749.     /* ppc */     "|MSR: "
  1750.     /* ppc */     "|TASK = "
  1751.     /* ppc */     "|last math "
  1752.     /* ppc */     "|GPR[0-9]+: "
  1753.     /* any other ppc lines to print? */
  1754.     /* mips */     "|.* in .*\.[ch]:.*, line [0-9]+:"
  1755.     /* mips */     "|\$[0-9 ]+:"
  1756.     /* mips */     "|Hi *:"
  1757.     /* mips */     "|Lo *:"
  1758.     /* mips */     "|epc *:"
  1759.     /* mips */     "|badvaddr *:"
  1760.     /* mips */     "|Status *:"
  1761.     /* mips */     "|Cause *:"
  1762.     /* any other mips lines to print? */
  1763.     /* arm */     "|Backtrace:"
  1764.     /* arm */     "|Function entered at"
  1765.     /* arm */     "|\*pgd ="
  1766.     /* arm */     "|Internal error"
  1767.     /* arm */     "|pc :"
  1768.     /* arm */     "|sp :"
  1769.     /* arm */     "|Flags:"
  1770.     /* arm */     "|Control:"
  1771.     /* any other arm lines to print? */
  1772.     /* ikd patch */ "|WARNING:"
  1773.     /* ikd patch */ "|this_stack:"
  1774.     /* ikd patch */ "|i:"
  1775.     /* any other ikd lines to print? */
  1776.     /* i370 */     "|PSW"
  1777.     /* i370 */     "|cr[0-9]+:"
  1778.     /* i370 */     "|machine check"
  1779.     /* i370 */     "|Exception in "
  1780.     /* i370 */     "|Program Check "
  1781.     /* i370 */     "|System restart "
  1782.     /* i370 */     "|IUCV "
  1783.     /* i370 */     "|unexpected external "
  1784.     /* i370 */     "|Kernel stack "
  1785.     /* any other i370 lines to print? */
  1786.     /* s390 */     "|User process fault:"
  1787.     /* s390 */     "|failing address"
  1788.     /* s390 */     "|User PSW"
  1789.     /* s390 */     "|User GPRS"
  1790.     /* s390 */     "|User ACRS"
  1791.     /* s390 */     "|Kernel PSW"
  1792.     /* s390 */     "|Kernel GPRS"
  1793.     /* s390 */     "|Kernel ACRS"
  1794.     /* s390 */     "|illegal operation"
  1795.     /* s390 */     "|task:"
  1796.     /* any other s390 lines to print? */
  1797.     /* SGI kdb */ "|Entering kdb"
  1798.     /* SGI kdb */ "|eax *="
  1799.     /* SGI kdb */ "|esi *="
  1800.     /* SGI kdb */ "|ebp *="
  1801.     /* SGI kdb */ "|ds *="
  1802.     /* any other SGI kdb lines to print? */
  1803.     /* ia64 */     "|psr "
  1804.     /* ia64 */     "|unat  "
  1805.     /* ia64 */     "|rnat "
  1806.     /* ia64 */     "|ldrs "
  1807.     /* ia64 */     "|xip "
  1808.     /* ia64 */     "|iip "
  1809.     /* ia64 */     "|ipsr "
  1810.     /* ia64 */     "|ifa "
  1811.     /* ia64 */     "|pr "
  1812.     /* ia64 */     "|itc "
  1813.     /* ia64 */     "|ifs "
  1814.     /* ia64 */     "|bsp "
  1815.     /* ia64 */     "|[bfr][0-9]+ "
  1816.     /* ia64 */     "|irr[0-9] "
  1817.     /* ia64 */     "|General Exception"
  1818.     /* ia64 */     "|MCA"
  1819.     /* ia64 */     "|SAL"
  1820.     /* ia64 */     "|Processor State"
  1821.     /* ia64 */     "|Bank [0-9]+"
  1822.     /* ia64 */     "|Register Stack"
  1823.     /* ia64 */     "|Processor Error Info"
  1824.     /* ia64 */     "|proc err map"
  1825.     /* ia64 */     "|proc state param"
  1826.     /* ia64 */     "|proc lid"
  1827.     /* ia64 */     "|processor structure"
  1828.     /* ia64 */     "|check info"
  1829.     /* ia64 */     "|target identifier"
  1830.     /* any other ia64 lines to print? */
  1831.     /* CRIS */     "|IRP *: "
  1832.     /* any other cris lines to print? */
  1833. ")",
  1834. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1835. &re_Oops_print_s_pmatch);
  1836.     i = regexec(&re_Oops_print_s, *text, re_Oops_print_s.re_nsub+1,
  1837. re_Oops_print_s_pmatch, 0);
  1838.     DEBUG(4, "regexec start %d", i);
  1839.     DIFF(3);
  1840.     print = 0;
  1841. #undef MATCHED
  1842. #define MATCHED(n) (re_Oops_print_s_pmatch[n].rm_so != -1)
  1843.     DIFF(4);
  1844.     /* Handle multiline messages, messy.  Only treat strings that look like
  1845.      * addresses as useful when they immediately follow a definite stack or
  1846.      * trace header or a previously valid stack or trace line.
  1847.      * Because of the horribly ambiguous s390 register dump, unbracketed
  1848.      * addresses (string 4) can now be either stack or trace.  How not to design
  1849.      * dump output.
  1850.      */
  1851.     /* Stack lines */
  1852.     if (!MATCHED(2) && !MATCHED(3) && !MATCHED(4))
  1853. stack_line = 0;
  1854.     else if (MATCHED(2) || MATCHED(3))
  1855. stack_line = 1;
  1856.     else if (stack_line && !MATCHED(4))
  1857. stack_line = 0;
  1858.     /* Trace lines */
  1859.     if (!MATCHED(4) && !MATCHED(5) && !MATCHED(6) && !MATCHED(9) &&
  1860. !MATCHED(10) && !MATCHED(11) && !MATCHED(12) && !MATCHED(13) &&
  1861. !MATCHED(15) && !MATCHED(16) && !MATCHED(17) && !MATCHED(19))
  1862. trace_line = 0;
  1863.     else if (MATCHED(4) || MATCHED(5) || MATCHED(9) || MATCHED(10) ||
  1864. MATCHED(11) || MATCHED(15) || MATCHED(16) || MATCHED(17))
  1865. trace_line = 1;
  1866.     else if (trace_line && !MATCHED(4) && !MATCHED(6) && !MATCHED(12) &&
  1867. !MATCHED(13) && !MATCHED(19))
  1868. trace_line = 0;
  1869.     if (i == 0) {
  1870. print = 1;
  1871. if (MATCHED(4) && !stack_line && !trace_line) {
  1872.     print = 0;
  1873.     DEBUG(4, "%s", "ambiguous stack/trace line ignored");
  1874. }
  1875. if ((MATCHED(6) || MATCHED(12) || MATCHED(13)) && !trace_line) {
  1876.     print = 0;
  1877.     DEBUG(4, "%s", "ambiguous trace line ignored");
  1878. }
  1879.     }
  1880.     if (print && MATCHED(4)) {
  1881. /* Ambiguity with 3Com messages, a line like 3c503.c:v1.10 9/23/93
  1882.  * starts with 4 or more hex digits but is not an error message, instead
  1883.  * it is a filename.  Look for '.c:' before the first space and ignore
  1884.  * if found.  Also ad1848, look for '/' before first space.  Do not look
  1885.  * for ':' on its own, arm does "address: stack values" :(.
  1886.  *
  1887.  * Ambiguity of ambiguities, saith the preacher; all is ambiguity.
  1888.  */
  1889. const char *p1, *p2;
  1890. p2 = strstr(*text, " ");
  1891. if (p2) {
  1892.     if ((p1 = strstr(*text, ".c:")) && p1 < p2)
  1893. print = 0;  /* ignore ambiguous match */
  1894.     else if ((p1 = strstr(*text, "/")) && p1 < p2)
  1895. print = 0;  /* ignore ambiguous match */
  1896. }
  1897. if (!print)
  1898.     DEBUG(4, "%s", "ambiguous start ignored");
  1899.     }
  1900.     /* delay splitting into strings until we really them */
  1901.     if (print && MATCHED(8)) {
  1902. re_string_check(re_Oops_print_s.re_nsub+1, string_max,
  1903.     procname);
  1904. re_strings(&re_Oops_print_s, *text,
  1905.     re_Oops_print_s_pmatch,
  1906.     string);
  1907. add_Version((*string)[8]+8, "Oops");
  1908.     }
  1909.     DIFF(5);
  1910.     /* These patterns can appear anywhere in the line, after stripping
  1911.      * the prefix above.
  1912.      */
  1913.     RE_COMPILE(&re_Oops_print_a,
  1914.    /* arch type */
  1915.     /* various */   "Unable to handle kernel"
  1916.     /* various */   "|Aiee"      /* anywhere in text is a bad sign (TM) */
  1917.     /* various */   "|die_if_kernel"  /* ditto */
  1918.     /* various */   "|NMI "
  1919.     /* various */   "|BUG "
  1920.     /* various */   "|\(L-TLB\)"
  1921.     /* various */   "|\(NOTLB\)"
  1922.     /* alpha */     "|\([0-9]\): Oops "
  1923.     /* alpha */     "|: memory violation"
  1924.     /* alpha */     "|: Exception at"
  1925.     /* alpha */     "|: Arithmetic fault"
  1926.     /* alpha */     "|: Instruction fault"
  1927.     /* alpha */     "|: arithmetic trap"
  1928.     /* alpha */     "|: unaligned trap"
  1929.     /* sparc      die_if_kernel has no fixed text, identify by (pid): text.
  1930.      *            Somebody has been playful with the texts.
  1931.      *
  1932.      *            Alas adding this next pattern increases run time by 15% on
  1933.      *            its own!  It would be considerably faster if sparc had
  1934.      *            consistent error texts.
  1935.      */
  1936.     /* sparc */     "|\([0-9]+\): "
  1937. "("
  1938.     "Whee"
  1939.     "|Oops"
  1940.     "|Kernel"
  1941.     "|.*Penguin"
  1942.     "|BOGUS"
  1943. ")"
  1944.     /* ppc */       "|kernel pc "
  1945.     /* ppc */       "|trap at PC: "
  1946.     /* ppc */       "|bad area pc "
  1947.     /* ppc */       "|NIP: "
  1948.     /* mips */      "| ra *=="
  1949. ,
  1950. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1951. &re_Oops_print_a_pmatch);
  1952.     if (!print) {
  1953. i = regexec(&re_Oops_print_a, *text, re_Oops_print_a.re_nsub+1,
  1954.     re_Oops_print_a_pmatch, 0);
  1955. DEBUG(4, "regexec anywhere %d", i);
  1956. if (i == 0)
  1957.     print = 1;
  1958.     }
  1959.     DIFF(6);
  1960.     return(print);
  1961. }
  1962. /* Look for the Code: line.  Returns start of the code bytes. */
  1963. static const char *Oops_code(const char *line, char ***string, int string_max)
  1964. {
  1965.     int i;
  1966.     char *p;
  1967.     static regex_t     re_Oops_code;
  1968.     static regmatch_t *re_Oops_code_pmatch;
  1969.     static const char procname[] = "Oops_code";
  1970.     /* Oops 'Code: ' hopefully followed by at least one hex code.  sparc
  1971.      * brackets the PC in '<' and '>'.  arm brackets the PC in '(' and ')'.
  1972.      */
  1973.     RE_COMPILE(&re_Oops_code,
  1974. "^(" /*  1 */
  1975.     /* various */ "(Instruction DUMP)" /*  2 */
  1976.     /* various */ "|(Code:? *)" /*  3 */
  1977. ")"
  1978. ": +"
  1979. "(" /*  4 */
  1980.   "(general protection.*)"
  1981.   "|(Bad E?IP value.*)"
  1982.   "|(<[0-9]+>)"
  1983.   "|(([<(]?[0-9a-fA-F]+[>)]? +)+[<(]?[0-9a-fA-F]+[>)]?)"
  1984. ")"
  1985. "(.*)$" /* trailing garbage */
  1986. ,
  1987. REG_NEWLINE|REG_EXTENDED|REG_ICASE,
  1988. &re_Oops_code_pmatch);
  1989.     i = regexec(&re_Oops_code, line, re_Oops_code.re_nsub+1,
  1990. re_Oops_code_pmatch, 0);
  1991.     DEBUG(4, "regexec %d", i);
  1992.     if (i == 0) {
  1993. re_string_check(re_Oops_code.re_nsub+1, string_max, procname);
  1994. re_strings(&re_Oops_code, line, re_Oops_code_pmatch,
  1995.     string);
  1996. if ((*string)[re_Oops_code.re_nsub] &&
  1997.     *((*string)[re_Oops_code.re_nsub])) {
  1998.     /* Performance fix to Code: re means that trailing space is no
  1999.      * longer part of the Code: text.  No point in complaining about
  2000.      * trailing space.
  2001.      */
  2002.     for (p = (*string)[re_Oops_code.re_nsub]; isspace(*p); ++p)
  2003. /* skip white space */ ;
  2004.     if (*p) {
  2005. WARNING("trailing garbage ignored on Code: linen"
  2006.     "  Text: '%s'n"
  2007.     "  Garbage: '%s'",
  2008.     line, (*string)[re_Oops_code.re_nsub]);
  2009.     }
  2010. }
  2011. return((*string)[4]);
  2012.     }
  2013.     return(NULL);
  2014. }
  2015. /******************************************************************************/
  2016. /*                      End architecture sensitive code                       */
  2017. /******************************************************************************/
  2018. /* Decode part or all of the Oops Code: via objdump. */
  2019. static void Oops_decode_part(const char* code, int code_size,
  2020.      addr_t eip, int adjust,
  2021.      const char type, SYMBOL_SET *ss,
  2022.      char ***string, int string_max,
  2023.      const bfd *ibfd, OPTIONS *options)
  2024. {
  2025.     FILE *f;
  2026.     char *file, *line = NULL;
  2027.     int size = 0, lines = 0;
  2028.     static char const procname[] = "Oops_decode_part";
  2029.     DEBUG(1, "%s", "");
  2030.     /* binary to same format as ksymoops */
  2031.     if (!(file = Oops_code_to_file(code, code_size, ibfd, options)))
  2032. return;
  2033.     /* objdump the pseudo object */
  2034.     if (!(f = Oops_objdump(file, options)))
  2035. return;
  2036.     while (fgets_local(&line, &size, f, procname)) {
  2037. DEBUG(2, "%s", line);
  2038. ++lines;
  2039. Oops_decode_one(ss, line, eip, adjust, type, options);
  2040.     }
  2041.     pclose_local(f, procname);  /* opened in Oops_objdump */
  2042.     free(line);
  2043.     if (!lines)
  2044. ERROR("no objdump lines read for %s", file);
  2045.     else if (unlink(file)) {
  2046. ERROR("could not unlink %s", file);
  2047. perror(prefix);
  2048.     }
  2049. }
  2050. /* Decode the Oops Code: via objdump. */
  2051. static void Oops_decode(const unsigned char* code_text, addr_t eip,
  2052. SYMBOL_SET *ss, char ***string, int string_max,
  2053. const bfd *ibfd, OPTIONS *options)
  2054. {
  2055.     char code[CODE_SIZE];
  2056.     int adjust;
  2057.     static char const procname[] = "Oops_decode";
  2058.     DEBUG(1, "%s", "");
  2059.     /* text to binary */
  2060.     if (!Oops_code_values(code_text, code, &adjust, options))
  2061. return;
  2062.     /* adjust is -ve number of bytes before eip */
  2063.     if (adjust && options->vli) {
  2064.     Oops_decode_part(code, -adjust, eip, adjust, 'U', ss, string, string_max, ibfd, options);
  2065.     Oops_decode_part(code-adjust, CODE_SIZE+adjust, eip, 0, 'C', ss, string, string_max, ibfd, options);
  2066.     } else {
  2067.     Oops_decode_part(code, CODE_SIZE, eip, adjust, 'C', ss, string, string_max, ibfd, options);
  2068.     }
  2069. }
  2070. /* Reached the end of an Oops report, format the extracted data. */
  2071. static void Oops_format(const SYMBOL_SET *ss_format, OPTIONS *options)
  2072. {
  2073.     int i;
  2074.     SYMBOL *s;
  2075.     addr_t eip = 0;
  2076.     char *eye_catcher, prev_type = '';
  2077.     static const char procname[] = "Oops_format";
  2078.     DEBUG(1, "%s", "");
  2079.     compare_Version();  /* Oops might have a version one day */
  2080.     printf("n");
  2081.     for (s = ss_format->symbol, i = 0; i < ss_format->used; ++i, ++s) {
  2082. /* For type C and U data, print Code:, address, map, "name" (actually
  2083.  * the text of an objdump line).  For type I (id) print the string.
  2084.  * For other types print name, address, map.
  2085.  */
  2086. if (s->type == 'C' || s->type == 'U') {
  2087.     if (prev_type != s->type) {
  2088. printf("n");
  2089. if (s->type == 'U')
  2090.     printf("This architecture has variable length instructions, decoding before eipn"
  2091.    "is unreliable, take these instructions with a pinch of salt.nn");
  2092. else if (prev_type == 'U')
  2093.     printf("This decode from eip onwards should be reliablenn");
  2094.     }
  2095.     eye_catcher = "";
  2096.     if (eip && i < ss_format->used-1 && (s+1)->type == s->type &&
  2097. eip >= s->address && eip < (s+1)->address)
  2098. eye_catcher = "   <=====";
  2099.     if (options->short_lines)
  2100. printf("Code;  %s %s%sn%s%sn",
  2101.     format_address(s->address, options),
  2102.     map_address(&ss_merged, s->address, options), eye_catcher,
  2103.     s->name, eye_catcher);
  2104.     else
  2105. printf("Code;  %s %-30s %s%sn",
  2106.     format_address(s->address, options),
  2107.     map_address(&ss_merged, s->address, options),
  2108.     s->name, eye_catcher);
  2109. }
  2110. else if (s->type == 'I') {
  2111.     printf("%sn", s->name);
  2112. }
  2113. else {
  2114.     /* Suppress registers that do not resolve to symbols */
  2115.     char *map = map_address(&ss_merged, s->address, options);
  2116.     if (s->type == 'R') {
  2117. if (index(map, '+') == NULL || strncmp(map, "<END_OF_CODE+", 13) == 0) {
  2118.     continue;
  2119. }
  2120.     }
  2121.     if (prev_type != s->type)
  2122. printf("n");
  2123.     printf("%s %s %s",
  2124. s->name, format_address(s->address, options), map);
  2125.     if (s->type == 'E') {
  2126. eip = s->address;
  2127. if (eip)
  2128.     printf("   <=====");
  2129.     }
  2130.     printf("n");
  2131. }
  2132. prev_type = s->type;
  2133.     }
  2134.     printf("n");
  2135. }
  2136. /* Select next Oops input file */
  2137. static FILE *Oops_next_file(OPTIONS *options)
  2138. {
  2139.     static FILE *f = NULL;
  2140.     static int first_file = 1;
  2141.     static const char procname[] = "Oops_next_file";
  2142.     if (first_file) {
  2143. f = stdin;
  2144. first_file = 0;
  2145.     }
  2146.     while (options->filecount) {
  2147. if (f)
  2148.     fclose_local(f, procname);
  2149. f = NULL;
  2150. if (strcmp(*(options->filename), "/dev/null") == 0 ||
  2151.     regular_file(*(options->filename), procname))
  2152.     f = fopen_local(*(options->filename), "r", procname);
  2153. if (f)
  2154.     DEBUG(1, "reading Oops report from %s", *(options->filename));
  2155. ++options->filename;
  2156. --options->filecount;
  2157. if (f)
  2158.     return(f);
  2159.     }
  2160.     return(f);
  2161. }
  2162. /* Read the Oops report */
  2163. #define MAX_STRINGS 300 /* Maximum strings in any Oops re */
  2164. int Oops_read(OPTIONS *options)
  2165. {
  2166.     char *line = NULL, **string = NULL, *me;
  2167.     const char *start, *text;
  2168.     int i, size = 0, lineno = 0, lastprint = 0, print;
  2169.     addr_t eip = 0;
  2170.     int sparc_regdump = 0;
  2171.     FILE *f;
  2172.     SYMBOL_SET ss_format;
  2173.     bfd *ibfd = NULL;
  2174.     static const char procname[] = "Oops_read";
  2175.     ss_init(&ss_format, "Oops log data");
  2176.     Oops_open_input_bfd(&me, &ibfd, options);
  2177.     if (options->adhoc_addresses) {
  2178. char **adhoc;
  2179. for (adhoc = options->adhoc_addresses; *adhoc; ++adhoc) {
  2180.     add_symbol(&ss_format, *adhoc, 'A', 1, "Adhoc");
  2181. }
  2182.     }
  2183.     if (!options->filecount && isatty(0))
  2184. printf("Reading Oops report from the terminaln");
  2185.     string = malloc(MAX_STRINGS*sizeof(*string));
  2186.     if (!string)
  2187. malloc_error(procname);
  2188.     memset(string, '', MAX_STRINGS*sizeof(*string));
  2189.     do {
  2190. if (!(f = Oops_next_file(options)))
  2191.     continue;
  2192. while (fgets_local(&line, &size, f, procname)) {
  2193.     DEBUG(3, "%s", line);
  2194.     ++lineno;
  2195.     print = Oops_print(line, &text, &string, MAX_STRINGS);
  2196.     if (print && Oops_sparc_regdump(text, &string)) {
  2197. sparc_regdump = 1;
  2198.     } else {
  2199. if (options->target &&
  2200.     strstr(options->target, "sparc") &&
  2201.     sparc_regdump &&
  2202.     ss_format.used) {
  2203.     Oops_format(&ss_format, options);
  2204.     ss_free(&ss_format);
  2205. }
  2206. sparc_regdump = 0;
  2207.     }
  2208.     if (print) {
  2209. if (options->one_shot && lastprint == 0)
  2210.     read_symbol_sources(options);
  2211. puts(line);
  2212. lastprint = lineno;
  2213. if ((start = Oops_eip(text, &string, MAX_STRINGS, ibfd,
  2214.       options))) {
  2215.     const char *ret_addr;
  2216.     if ((ret_addr = Oops_arm_lr(text, &string, MAX_STRINGS)))
  2217. Oops_set_arm_lr(ret_addr, &ss_format);
  2218.     if ((ret_addr = Oops_alpha_ra(text, &string, MAX_STRINGS)))
  2219. Oops_set_alpha_ra(ret_addr, &ss_format);
  2220.     Oops_set_eip(start, &eip, &ss_format, me, ibfd, options);
  2221.     options->vli = strstr(line, " VLI") != NULL;
  2222. }
  2223. if (Oops_eip_alpha_spinlock(text, &string, MAX_STRINGS,
  2224.     options)) {
  2225.     /* Set the eip and previous user from the alpha spinlock
  2226.      * stuck line.  YASC, this line contains both the eip and
  2227.      * the equivalent of a trace entry.
  2228.      */
  2229.     Oops_set_eip(string[1], &eip, &ss_format, me, ibfd, options);
  2230.     Oops_trace_line(line, string[2], &ss_format, options);
  2231. }
  2232. if (Oops_eip_sparc_spinlock(text, &string, MAX_STRINGS,
  2233.     options)) {
  2234.     /* Set the eip and previous user from the sparc spinlock
  2235.      * stuck line.  YASC, this line contains the lock and two
  2236.      * PC entries.
  2237.      */
  2238.     Oops_set_eip(string[2], &eip, &ss_format, me, ibfd, options);
  2239.     Oops_set_eip(string[3], &eip, &ss_format, me, ibfd, options);
  2240.     Oops_trace_line(line, string[1], &ss_format, options);
  2241. }
  2242. if ((start = Oops_mips_ra(text, &string, MAX_STRINGS)))
  2243.     Oops_set_mips_ra(start, &ss_format);
  2244. Oops_mips_regs(text, &ss_format, options);
  2245. Oops_ppc_regs(text, &ss_format, options);
  2246. if ((start = Oops_i370_psw(text, &string, MAX_STRINGS)))
  2247.     Oops_set_i370_psw(start, &ss_format, me, ibfd, options);
  2248. if ((start = Oops_s390_psw(text, &string, MAX_STRINGS)))
  2249.     Oops_set_s390_psw(start, &ss_format, me, ibfd, options);
  2250. if ((start = Oops_trace(text)))
  2251.     Oops_trace_line(text, start, &ss_format, options);
  2252. if ((start = Oops_regs(text)))
  2253.     Oops_set_regs(text, start, &ss_format, options);
  2254. if ((start = Oops_s390_regs(text)))
  2255.     Oops_set_s390_regs(text, start, &ss_format, options);
  2256. if ((start = Oops_cris_regs(text)))
  2257.     Oops_set_cris_regs(text, start, &ss_format, options);
  2258. Oops_set_ia64_b0(text, &string, MAX_STRINGS, &ss_format);
  2259. if (Oops_set_task_name(text, &string, MAX_STRINGS, &ss_format))
  2260.     Oops_set_eip(string[2], &eip, &ss_format, me, ibfd, options);
  2261. if ((start = Oops_code(text, &string, MAX_STRINGS))) {
  2262.     /* In case no EIP line was seen */
  2263.     Oops_set_default_ta(me, ibfd, options);
  2264.     Oops_decode(start, eip, &ss_format, &string, MAX_STRINGS,
  2265. ibfd, options);
  2266.     Oops_format(&ss_format, options);
  2267.     ss_free(&ss_format);
  2268.     if (options->one_shot)
  2269. return(0);
  2270. }
  2271.     }
  2272.     /* More than 5 (arbitrary) lines which were not printed
  2273.      * and there is some saved data, assume we missed the
  2274.      * Code: line.
  2275.      */
  2276.     if (ss_format.used && lineno > lastprint+5) {
  2277. WARNING("%s", "Code line not seen, dumping what data is available");
  2278. Oops_format(&ss_format, options);
  2279. ss_free(&ss_format);
  2280. if (options->one_shot)
  2281.     return(0);
  2282.     }
  2283. }
  2284. if (ss_format.used) {
  2285.     if (options->target &&
  2286. strstr(options->target, "sparc") == 0 &&
  2287. sparc_regdump)
  2288. ; /* sparc regdump comes *after* code, ignore :( */
  2289.     else if (!options->adhoc_addresses)
  2290. WARNING("%s", "Code line not seen, dumping what data is available");
  2291.     Oops_format(&ss_format, options);
  2292.     ss_free(&ss_format);
  2293.     if (options->one_shot)
  2294. return(0);
  2295. }
  2296.     } while (options->filecount != 0);
  2297. #ifdef TIME_RE
  2298.     for (i = 0; i < sizeof(diff)/sizeof(diff[0]); ++i)
  2299. printf("diff %d %d %lld %lldn", i, count[i], diff[i], count[i] ? diff[i]/count[i] : 0);
  2300. #endif
  2301.     if (ibfd && !bfd_close(ibfd)) {
  2302. Oops_bfd_perror("close(ibfd)");
  2303. return(0);
  2304.     }
  2305.     for (i = 0; i < sizeof(string); ++i) {
  2306. free(string[i]);
  2307. string[i] = NULL;
  2308.     }
  2309.     free(line);
  2310.     if (options->one_shot)
  2311. return(3);  /* one shot mode, end of input, no data */
  2312.     return(0);
  2313. }