resolve_stack_dump.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:7k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17. /* Resolve numeric stack dump produced by mysqld 3.23.30 and later
  18.    versions into symbolic names. By Sasha Pachev <sasha@mysql.com>
  19.  */
  20. #define DONT_USE_RAID
  21. #include <global.h>
  22. #include <m_ctype.h>
  23. #include <my_sys.h>
  24. #include <m_string.h>
  25. #include <mysql_version.h>
  26. #include <errno.h>
  27. #include <getopt.h>
  28. #define INIT_SYM_TABLE  4096
  29. #define INC_SYM_TABLE  4096
  30. #define MAX_SYM_SIZE   128
  31. #define DUMP_VERSION "1.1"
  32. #define HEX_INVALID  (uchar)255
  33. typedef ulong my_long_addr_t ; /* at some point, we need to fix configure
  34. * to define this for us  
  35. */
  36. typedef struct sym_entry
  37. {
  38.   char symbol[MAX_SYM_SIZE];
  39.   uchar* addr;
  40. } SYM_ENTRY;
  41. static char* dump_fname = 0, *sym_fname = 0;
  42. static DYNAMIC_ARRAY sym_table; /* how do you like this , static DYNAMIC ? */
  43. static FILE* fp_dump, *fp_sym = 0, *fp_out; 
  44. struct option long_options[] =
  45. {
  46.   {"help", no_argument, 0, 'h'},
  47.   {"version", no_argument, 0, 'V'},
  48.   {"symbols-file", required_argument, 0, 's'},
  49.   {"numeric-dump-file", required_argument, 0, 'n'},
  50.   {0, 0,0,0}
  51. };
  52. static void verify_sort();
  53. static void print_version(void)
  54. {
  55.   printf("%s  Ver %s Distrib %s, for %s (%s)n",my_progname,DUMP_VERSION,
  56.  MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
  57. }
  58. static void usage()
  59. {
  60.   print_version();
  61.   printf("MySQL AB, by Sasha Pachevn");
  62.   printf("This software comes with ABSOLUTELY NO WARRANTYnn");
  63.   printf("Resolve numeric stack strace dump into symbols.nn");
  64.   printf("Usage: %s [OPTIONS]n", my_progname);
  65.   printf("n
  66.   -?, --help               Display this help and exit.n
  67.   -h, --host=...           Connect to host.n
  68.   -V, --version            Output version information and exit.n
  69.   -n, --numeric-dump-file  File containing the numeric stack dump.n
  70.   -s, --symbols-file=...   File containting the output of
  71.  nm --numeric-sort mysqld    .nn");
  72. }
  73. static void die(const char* fmt, ...)
  74. {
  75.   va_list args;
  76.   va_start(args, fmt);
  77.   fprintf(stderr, "%s: ", my_progname);
  78.   vfprintf(stderr, fmt, args);
  79.   fprintf(stderr, "n");
  80.   va_end(args);
  81.   exit(1);
  82. }
  83. static int parse_args(int argc, char **argv)
  84. {
  85.   int c, option_index = 0;
  86.   while((c = getopt_long(argc, argv, "?Vn:s:",
  87.  long_options, &option_index)) != EOF)
  88.     {
  89.       switch(c)
  90. {
  91. case 'n':
  92.   dump_fname = optarg;
  93.   break;
  94. case 's':
  95.   sym_fname = optarg;
  96.   break;
  97. case 'V':
  98.   print_version();
  99.   exit(0);
  100. case '?':
  101.   usage();
  102.   exit(0);
  103. default:
  104.   usage();
  105.   exit(1);
  106. }
  107.     }
  108.   argc-=optind;
  109.   argv+=optind;
  110.   if (argc > 0)
  111.   {
  112.     usage();
  113.     exit(1);
  114.   }
  115.   return 0;
  116. }
  117. static void open_files()
  118. {
  119.   fp_out = stdout;
  120.   fp_dump = stdin;
  121.   
  122.   if(dump_fname && !(fp_dump = my_fopen(dump_fname, O_RDONLY, MYF(MY_WME))))
  123.       die("Could not open %s", dump_fname);
  124.   /* if name not given, assume stdin*/
  125.   if(!sym_fname)
  126.     die("Please run nm --numeric-sort on mysqld binary that produced stack 
  127. trace dump and specify the path to it with -s or --symbols-file");
  128.   if(!(fp_sym = my_fopen(sym_fname, O_RDONLY, MYF(MY_WME))))
  129.     die("Could not open %s", sym_fname);
  130.     
  131. }
  132. static uchar hex_val(char c)
  133. {
  134.   uchar l;
  135.   if(isdigit(c))
  136.     return c - '0';
  137.   l = tolower(c);
  138.   if(l < 'a' || l > 'f')
  139.     return HEX_INVALID; 
  140.   return (uchar)10 + ((uchar)c - (uchar)'a');
  141. }
  142. static my_long_addr_t read_addr(char** buf)
  143. {
  144.   uchar c;
  145.   char* p = *buf;
  146.   my_long_addr_t addr = 0;
  147.   
  148.   while((c = hex_val(*p++)) != HEX_INVALID)
  149.       addr = (addr << 4) + c;
  150.   
  151.   *buf = p; 
  152.   return addr;
  153. }
  154. static int init_sym_entry(SYM_ENTRY* se, char* buf)
  155. {
  156.   char* p, *p_end;
  157.   se->addr = (uchar*)read_addr(&buf);
  158.   if(!se->addr)
  159.     return -1;
  160.   while(isspace(*buf++))
  161.     /* empty */;
  162.   
  163.   while(isspace(*buf++))
  164.     /* empty - skip more space */;
  165.   --buf;
  166.   /* now we are on the symbol */
  167.   for(p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
  168.       *buf != 'n' && *buf; ++buf,++p )
  169.     {
  170.       if(p < p_end)
  171. *p = *buf;
  172.       else
  173. break;
  174.     }
  175.   *p = 0;
  176.   if(!strcmp(se->symbol, "gcc2_compiled."))
  177.     return -1;
  178.   return 0;
  179. }
  180. static void init_sym_table()
  181. {
  182.   char buf[512];
  183.   if(init_dynamic_array(&sym_table, sizeof(SYM_ENTRY), INIT_SYM_TABLE,
  184.      INC_SYM_TABLE))
  185.     die("Failed in init_dynamic_array() -- looks like out of memory problem");
  186.   while(fgets(buf, sizeof(buf), fp_sym))
  187.     {
  188.       SYM_ENTRY se;
  189.       if(init_sym_entry(&se, buf))
  190. continue;
  191.       if(insert_dynamic(&sym_table, (gptr)&se))
  192. die("insert_dynamic() failed - looks like we are out of memory");
  193.     }
  194.   verify_sort();
  195. }
  196. static void clean_up()
  197. {
  198.   delete_dynamic(&sym_table);
  199. }
  200. static void verify_sort()
  201. {
  202.   uint i;
  203.   uchar* last = 0;
  204.   
  205.   for(i = 0; i < sym_table.elements; i++)
  206.     {
  207.       SYM_ENTRY se;
  208.       get_dynamic(&sym_table, (gptr)&se, i);
  209.       if(se.addr < last)
  210. die("sym table does not appear to be sorted, did you forget 
  211. --numeric-sort arg to nm? trouble addr = %p, last = %p", se.addr, last);
  212.       last = se.addr;
  213.     }
  214. }
  215. static SYM_ENTRY* resolve_addr(uchar* addr, SYM_ENTRY* se)
  216. {
  217.   uint i;
  218.   get_dynamic(&sym_table, (gptr)se, 0);
  219.   if(addr < se->addr)
  220.     return 0;
  221.   
  222.   for(i = 1; i < sym_table.elements; i++)
  223.     {
  224.       get_dynamic(&sym_table, (gptr)se, i);
  225.       if(addr < se->addr)
  226. {
  227.   get_dynamic(&sym_table, (gptr)se, i - 1);
  228.   return se;
  229. }
  230.     }
  231.   return se;
  232. }
  233. static void do_resolve()
  234. {
  235.   char buf[1024], *p;
  236.   while(fgets(buf, sizeof(buf), fp_dump))
  237.     {
  238.       p = buf;
  239.       while(isspace(*p))
  240. ++p;
  241. /* skip space */;
  242.       
  243.       if(*p++ == '0' && *p++ == 'x')
  244. {
  245.   SYM_ENTRY se ;
  246.   uchar* addr = (uchar*)read_addr(&p);
  247.   if(resolve_addr(addr, &se))
  248.     fprintf(fp_out, "%p %s + %dn", addr, se.symbol,
  249.     addr - se.addr);
  250.   else
  251.     fprintf(fp_out, "%p (?)n", addr);
  252.     
  253. }
  254.       else
  255. {
  256.   fputs(buf, fp_out);
  257.   continue;
  258. }
  259.     }
  260. }
  261. int main(int argc, char** argv)
  262. {
  263.   MY_INIT(argv[0]);
  264.   parse_args(argc, argv);
  265.   open_files();
  266.   init_sym_table();
  267.   do_resolve();
  268.   clean_up();
  269.   return 0;
  270. }
  271.