1
/* Copyright (C) 2000 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/* Resolve numeric stack dump produced by drizzled 3.23.30 and later
17
versions into symbolic names. By Sasha Pachev <sasha@mysql.com>
20
#include <drizzled/global.h>
21
#include <mystrings/m_ctype.h>
22
#include <mysys/my_sys.h>
23
#include <mystrings/m_string.h>
25
#include <mysys/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 (unsigned char)255
35
typedef struct sym_entry
37
char symbol[MAX_SYM_SIZE];
42
static char* dump_fname = 0, *sym_fname = 0;
43
static DYNAMIC_ARRAY sym_table; /* how do you like this , static DYNAMIC ? */
44
static FILE* fp_dump, *fp_sym = 0, *fp_out;
46
static struct my_option my_long_options[] =
48
{"help", 'h', "Display this help and exit.",
49
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
50
{"version", 'V', "Output version information and exit.",
51
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
52
{"symbols-file", 's', "Use specified symbols file.", (char**) &sym_fname,
53
(char**) &sym_fname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
54
{"numeric-dump-file", 'n', "Read the dump from specified file.",
55
(char**) &dump_fname, (char**) &dump_fname, 0, GET_STR, REQUIRED_ARG,
57
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
61
static void verify_sort(void);
63
static void print_version(void)
65
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
66
VERSION,SYSTEM_TYPE,MACHINE_TYPE);
70
static void usage(void)
73
printf("MySQL AB, by Sasha Pachev\n");
74
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
75
printf("Resolve numeric stack strace dump into symbols.\n\n");
76
printf("Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n",
78
my_print_help(my_long_options);
79
my_print_variables(my_long_options);
81
The symbols-file should include the output from: 'nm --numeric-sort drizzled'.\n\
82
The numeric-dump-file should contain a numeric stack trace from drizzled.\n\
83
If the numeric-dump-file is not given, the stack trace is read from stdin.\n");
86
static void die(const char* fmt, ...)
90
fprintf(stderr, "%s: ", my_progname);
91
vfprintf(stderr, fmt, args);
92
fprintf(stderr, "\n");
99
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
100
char *argument __attribute__((unused)))
114
static int parse_args(int argc, char **argv)
118
if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option)))
122
The following code is to make the command compatible with the old
123
version that required one to use the -n and -s options
135
else if (!dump_fname)
136
dump_fname = argv[0];
143
else if (argc != 0 || !sym_fname)
152
static void open_files(void)
157
if (dump_fname && !(fp_dump = my_fopen(dump_fname, O_RDONLY, MYF(MY_WME))))
158
die("Could not open %s", dump_fname);
159
/* if name not given, assume stdin*/
162
die("Please run nm --numeric-sort on drizzled binary that produced stack \
163
trace dump and specify the path to it with -s or --symbols-file");
164
if (!(fp_sym = my_fopen(sym_fname, O_RDONLY, MYF(MY_WME))))
165
die("Could not open %s", sym_fname);
169
static unsigned char hex_val(char c)
172
if (my_isdigit(&my_charset_utf8_general_ci,c))
174
l = my_tolower(&my_charset_utf8_general_ci,c);
175
if (l < 'a' || l > 'f')
177
return (unsigned char)10 + ((unsigned char)c - (unsigned char)'a');
180
static unsigned long read_addr(char** buf)
184
unsigned long addr = 0;
186
while((c = hex_val(*p++)) != HEX_INVALID)
187
addr = (addr << 4) + c;
193
static int init_sym_entry(SYM_ENTRY* se, char* buf)
196
se->addr = (unsigned char*)read_addr(&buf);
200
while (my_isspace(&my_charset_utf8_general_ci,*buf++))
203
while (my_isspace(&my_charset_utf8_general_ci,*buf++))
204
/* empty - skip more space */;
206
/* now we are on the symbol */
207
for (p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
208
*buf != '\n' && *buf && p < p_end; ++buf,++p)
211
if (!strcmp(se->symbol, "gcc2_compiled."))
216
static void init_sym_table(void)
219
if (my_init_dynamic_array(&sym_table, sizeof(SYM_ENTRY), INIT_SYM_TABLE,
221
die("Failed in my_init_dynamic_array() -- looks like out of memory problem");
223
while (fgets(buf, sizeof(buf), fp_sym))
226
if (init_sym_entry(&se, buf))
228
if (insert_dynamic(&sym_table, (unsigned char*)&se))
229
die("insert_dynamic() failed - looks like we are out of memory");
235
static void clean_up(void)
237
delete_dynamic(&sym_table);
240
static void verify_sort()
243
unsigned char* last = 0;
245
for (i = 0; i < sym_table.elements; i++)
248
get_dynamic(&sym_table, (unsigned char*)&se, i);
250
die("sym table does not appear to be sorted, did you forget \
251
--numeric-sort arg to nm? trouble addr = %p, last = %p", se.addr, last);
257
static SYM_ENTRY* resolve_addr(unsigned char* addr, SYM_ENTRY* se)
260
get_dynamic(&sym_table, (unsigned char*)se, 0);
264
for (i = 1; i < sym_table.elements; i++)
266
get_dynamic(&sym_table, (unsigned char*)se, i);
269
get_dynamic(&sym_table, (unsigned char*)se, i - 1);
278
static void do_resolve(void)
281
while (fgets(buf, sizeof(buf), fp_dump))
285
while (my_isspace(&my_charset_utf8_general_ci,*p))
288
if (*p++ == '0' && *p++ == 'x')
291
unsigned char* addr = (unsigned char*)read_addr(&p);
292
if (resolve_addr(addr, &se))
293
fprintf(fp_out, "%p %s + %d\n", addr, se.symbol,
294
(int) (addr - se.addr));
296
fprintf(fp_out, "%p (?)\n", addr);
308
int main(int argc, char** argv)
311
parse_args(argc, argv);