20 #include <my_global.h>
24 #include <mysql_version.h>
26 #include <my_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.4"
32 #define HEX_INVALID (uchar)255
34 typedef ulong my_long_addr_t ;
40 char symbol[MAX_SYM_SIZE];
45 static char* dump_fname = 0, *sym_fname = 0;
47 static FILE* fp_dump, *fp_sym = 0, *fp_out;
49 static struct my_option my_long_options[] =
51 {
"help",
'h',
"Display this help and exit.",
52 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
53 {
"version",
'V',
"Output version information and exit.",
54 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
55 {
"symbols-file",
's',
"Use specified symbols file.", &sym_fname,
56 &sym_fname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
57 {
"numeric-dump-file",
'n',
"Read the dump from specified file.",
58 &dump_fname, &dump_fname, 0, GET_STR, REQUIRED_ARG,
60 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
64 static void verify_sort();
67 static void print_version(
void)
69 printf(
"%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
70 MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
77 printf(
"MySQL AB, by Sasha Pachev\n");
78 printf(
"This software comes with ABSOLUTELY NO WARRANTY\n\n");
79 printf(
"Resolve numeric stack strace dump into symbols.\n\n");
80 printf(
"Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n",
82 my_print_help(my_long_options);
83 my_print_variables(my_long_options);
85 The symbols-file should include the output from: 'nm --numeric-sort mysqld'.\n\
86 The numeric-dump-file should contain a numeric stack trace from mysqld.\n\
87 If the numeric-dump-file is not given, the stack trace is read from stdin.\n");
91 static void die(
const char*
fmt, ...)
95 fprintf(stderr,
"%s: ", my_progname);
96 vfprintf(stderr, fmt, args);
97 fprintf(stderr,
"\n");
104 get_one_option(
int optid,
const struct my_option *opt __attribute__((unused)),
105 char *argument __attribute__((unused)))
119 static int parse_args(
int argc,
char **argv)
123 if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
140 else if (!dump_fname)
141 dump_fname = argv[0];
148 else if (argc != 0 || !sym_fname)
157 static void open_files()
162 if (dump_fname && !(fp_dump = my_fopen(dump_fname, O_RDONLY, MYF(MY_WME))))
163 die(
"Could not open %s", dump_fname);
167 die(
"Please run nm --numeric-sort on mysqld binary that produced stack \
168 trace dump and specify the path to it with -s or --symbols-file");
169 if (!(fp_sym = my_fopen(sym_fname, O_RDONLY, MYF(MY_WME))))
170 die(
"Could not open %s", sym_fname);
174 static uchar hex_val(
char c)
177 if (my_isdigit(&my_charset_latin1,c))
179 l = my_tolower(&my_charset_latin1,c);
180 if (l < 'a' || l >
'f')
182 return (uchar)10 + ((uchar)c - (uchar)
'a');
185 static my_long_addr_t read_addr(
char**
buf)
189 my_long_addr_t addr = 0;
191 while((c = hex_val(*p++)) != HEX_INVALID)
192 addr = (addr << 4) + c;
198 static int init_sym_entry(
SYM_ENTRY* se,
char* buf)
201 se->addr = (uchar*)read_addr(&buf);
205 while (my_isspace(&my_charset_latin1,*buf++))
208 while (my_isspace(&my_charset_latin1,*buf++))
212 for (p = se->symbol, p_end = se->symbol +
sizeof(se->symbol) - 1;
213 *buf !=
'\n' && *buf && p < p_end; ++
buf,++p)
216 if (!strcmp(se->symbol,
"gcc2_compiled."))
221 static void init_sym_table()
224 if (my_init_dynamic_array(&sym_table,
sizeof(
SYM_ENTRY), INIT_SYM_TABLE,
226 die(
"Failed in my_init_dynamic_array() -- looks like out of memory problem");
228 while (fgets(buf,
sizeof(buf), fp_sym))
231 if (init_sym_entry(&se, buf))
233 if (insert_dynamic(&sym_table, &se))
234 die(
"insert_dynamic() failed - looks like we are out of memory");
240 static void clean_up()
242 delete_dynamic(&sym_table);
245 static void verify_sort()
250 for (i = 0; i < sym_table.elements; i++)
253 get_dynamic(&sym_table, (uchar*)&se, i);
255 die(
"sym table does not appear to be sorted, did you forget \
256 --numeric-sort arg to nm? trouble addr = %p, last = %p", se.addr, last);
265 get_dynamic(&sym_table, (uchar*)se, 0);
269 for (i = 1; i < sym_table.elements; i++)
271 get_dynamic(&sym_table, (uchar*)se, i);
274 get_dynamic(&sym_table, (uchar*)se, i - 1);
283 static void do_resolve()
286 while (fgets(buf,
sizeof(buf), fp_dump))
289 p= (p= strchr(buf,
'[')) ? p+1 : buf;
291 while (my_isspace(&my_charset_latin1,*p))
294 if (*p++ ==
'0' && *p++ ==
'x')
297 uchar* addr = (uchar*)read_addr(&p);
298 if (resolve_addr(addr, &se))
299 fprintf(fp_out,
"%p %s + %d\n", addr, se.symbol,
300 (
int) (addr - se.addr));
302 fprintf(fp_out,
"%p (?)\n", addr);
314 int main(
int argc,
char** argv)
317 parse_args(argc, argv);