diff options
author | unknown <sasha@mysql.sashanet.com> | 2001-01-05 15:04:15 -0700 |
---|---|---|
committer | unknown <sasha@mysql.sashanet.com> | 2001-01-05 15:04:15 -0700 |
commit | de51fa0c2530e22fef21a72d92e88029e7f33b8f (patch) | |
tree | 0abf5b6dd1e009c76be4ef5a0118c3f782598faf | |
parent | 1cf31b8537ae262fc8f1c327741afe20925361bc (diff) | |
download | mariadb-git-de51fa0c2530e22fef21a72d92e88029e7f33b8f.tar.gz |
Added resovle_stack_dump
BitKeeper/etc/config:
fixed up an option
BitKeeper/etc/ignore:
Added extra/resolve_stack_dump to the ignore list
extra/Makefile.am:
addition of resolve_stack_dump
-rw-r--r-- | .bzrignore | 1 | ||||
-rw-r--r-- | BitKeeper/etc/config | 1 | ||||
-rw-r--r-- | extra/Makefile.am | 3 | ||||
-rw-r--r-- | extra/resolve_stack_dump.c | 303 |
4 files changed, 307 insertions, 1 deletions
diff --git a/.bzrignore b/.bzrignore index 76eb5cdbc76..18f8b8d8f42 100644 --- a/.bzrignore +++ b/.bzrignore @@ -186,3 +186,4 @@ sql-bench/output/* sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686 Docs/my_sys.doc tmp/* +extra/resolve_stack_dump diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index 7579786b819..9e5a4507023 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -67,3 +67,4 @@ pager: # Business Hours when we can contact you if you left a phone number. # hours: +checkout:edit diff --git a/extra/Makefile.am b/extra/Makefile.am index fc5348dee55..ee6c2ba92f2 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -17,7 +17,8 @@ INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I.. LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \ ../dbug/libdbug.a ../strings/libmystrings.a -bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults +bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \ +resolve_stack_dump OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\ __math.h time.h __time.h unistd.h __unistd.h types.h \ diff --git a/extra/resolve_stack_dump.c b/extra/resolve_stack_dump.c new file mode 100644 index 00000000000..798c9618c66 --- /dev/null +++ b/extra/resolve_stack_dump.c @@ -0,0 +1,303 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA */ + +/* Resolve numeric stack dump produced by mysqld 3.23.30 and later + versions into symbolic names. By Sasha Pachev <sasha@mysql.com> + */ + +#define DONT_USE_RAID +#include <global.h> +#include <m_ctype.h> +#include <my_sys.h> +#include <m_string.h> +#include <mysql_version.h> +#include <errno.h> +#include <getopt.h> + +#define INIT_SYM_TABLE 4096 +#define INC_SYM_TABLE 4096 +#define MAX_SYM_SIZE 128 +#define DUMP_VERSION "1.0" +#define HEX_INVALID (uchar)255 + +typedef ulong my_long_addr_t ; /* at some point, we need to fix configure + * to define this for us + */ + +typedef struct sym_entry +{ + char symbol[MAX_SYM_SIZE]; + uchar* addr; +} SYM_ENTRY; + + +static char* dump_fname = 0, *sym_fname = 0; +static DYNAMIC_ARRAY sym_table; /* how do you like this , static DYNAMIC ? */ +static FILE* fp_dump, *fp_sym = 0, *fp_out; + +struct option long_options[] = +{ + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"symbols-file", required_argument, 0, 's'}, + {"numeric-dump-file", required_argument, 0, 'n'}, + {0, 0,0,0} +}; + +static void verify_sort(); + +static void print_version(void) +{ + printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION, + MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} + +static void usage() +{ + print_version(); + printf("MySQL AB, by Sasha Pachev\n"); + printf("This software comes with ABSOLUTELY NO WARRANTY\n\n"); + printf("Resolve numeric stack strace dump into symbols.\n\n"); + printf("Usage: %s [OPTIONS]\n", my_progname); + printf("\n\ + -?, --help Display this help and exit.\n\ + -h, --host=... Connect to host.\n\ + -V, --version Output version information and exit.\n\ + -n, --numeric-dump-file File containing the numeric stack dump.\n\ + -s, --symbols-file=... File containting the output of\ + nm --numeric-sort mysqld .\n\n"); +} + + + +static void die(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + fprintf(stderr, "%s: ", my_progname); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + exit(1); +} + + +static int parse_args(int argc, char **argv) +{ + int c, option_index = 0; + + while((c = getopt_long(argc, argv, "?Vn:s:", + long_options, &option_index)) != EOF) + { + switch(c) + { + case 'n': + dump_fname = optarg; + break; + case 's': + sym_fname = optarg; + break; + case 'V': + print_version(); + exit(0); + case '?': + usage(); + exit(0); + default: + usage(); + exit(1); + } + } + + argc-=optind; + argv+=optind; + if (argc > 0) + { + usage(); + exit(1); + } + + return 0; +} + +static void open_files() +{ + fp_out = stdout; + fp_dump = stdin; + + if(dump_fname && !(fp_dump = my_fopen(dump_fname, O_RDONLY, MYF(MY_WME)))) + die("Could not open %s", dump_fname); + /* if name not given, assume stdin*/ + + if(!sym_fname) + die("Please run nm --numeric-sort on mysqld binary that produced stack \ +trace dump and specify the path to it with -s or --symbols-file"); + if(!(fp_sym = my_fopen(sym_fname, O_RDONLY, MYF(MY_WME)))) + die("Could not open %s", sym_fname); + +} + +static uchar hex_val(char c) +{ + uchar l; + if(isdigit(c)) + return c - '0'; + l = tolower(c); + if(l < 'a' || l > 'f') + return HEX_INVALID; + return 10 + c - 'a'; +} + +static my_long_addr_t read_addr(char** buf) +{ + uchar c; + char* p = *buf; + my_long_addr_t addr = 0; + + while((c = hex_val(*p++)) != HEX_INVALID) + addr = (addr << 4) + c; + + *buf = p; + return addr; +} + +static int init_sym_entry(SYM_ENTRY* se, char* buf) +{ + char* p, *p_end; + se->addr = (uchar*)read_addr(&buf); + + if(!se->addr) + return -1; + while(isspace(*buf++)) + /* empty */; + + while(isspace(*buf++)) + /* empty - skip more space */; + --buf; + /* now we are on the symbol */ + for(p = se->symbol, p_end = se->symbol + sizeof(se->symbol); + *buf != '\n' && *buf; ++buf,++p ) + { + if(p < p_end) + *p = *buf; + else + break; + } + *p = 0; + return 0; +} + +static void init_sym_table() +{ + char buf[256]; + if(init_dynamic_array(&sym_table, sizeof(SYM_ENTRY), INIT_SYM_TABLE, + INC_SYM_TABLE)) + die("Failed in init_dynamic_array() -- looks like out of memory problem"); + + while(fgets(buf, sizeof(buf), fp_sym)) + { + SYM_ENTRY se; + if(init_sym_entry(&se, buf)) + continue; + if(insert_dynamic(&sym_table, (gptr)&se)) + die("insert_dynamic() failed - looks like we are out of memory"); + } + + verify_sort(); +} + +static void clean_up() +{ + delete_dynamic(&sym_table); +} + +static void verify_sort() +{ + uint i; + uchar* last = 0; + + for(i = 0; i < sym_table.elements; i++) + { + SYM_ENTRY se; + get_dynamic(&sym_table, (gptr)&se, i); + if(se.addr < last) + die("sym table does not appear to be sorted, did you forget \ +--numeric-sort arg to nm"); + last = se.addr; + } +} + +static SYM_ENTRY* resolve_addr(uchar* addr, SYM_ENTRY* se) +{ + uint i; + get_dynamic(&sym_table, (gptr)se, 0); + if(addr < se->addr) + return 0; + + for(i = 1; i < sym_table.elements; i++) + { + get_dynamic(&sym_table, (gptr)se, i); + if(addr < se->addr) + { + get_dynamic(&sym_table, (gptr)se, i - 1); + return se; + } + } + + return se; +} + +static void do_resolve() +{ + char buf[1024], *p; + while(fgets(buf, sizeof(buf), fp_dump)) + { + p = buf; + while(isspace(*p)) + ++p; + /* skip space */; + + if(*p++ == '0' && *p++ == 'x') + { + SYM_ENTRY se ; + uchar* addr = (uchar*)read_addr(&p); + if(resolve_addr(addr, &se)) + fprintf(fp_out, "%p %s + %d\n", addr, se.symbol, + addr - se.addr); + else + fprintf(fp_out, "%p (?)\n", addr); + + } + else + { + fputs(buf, fp_out); + continue; + } + } +} + +int main(int argc, char** argv) +{ + MY_INIT(argv[0]); + parse_args(argc, argv); + open_files(); + init_sym_table(); + do_resolve(); + clean_up(); + return 0; +} + |