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>
27
#define INIT_SYM_TABLE 4096
28
#define INC_SYM_TABLE 4096
29
#define MAX_SYM_SIZE 128
30
#define DUMP_VERSION "1.4"
31
#define HEX_INVALID (unsigned char)255
34
typedef struct sym_entry
36
char symbol[MAX_SYM_SIZE];
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;
45
static struct my_option my_long_options[] =
47
{"help", 'h', "Display this help and exit.",
48
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
49
{"version", 'V', "Output version information and exit.",
50
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
51
{"symbols-file", 's', "Use specified symbols file.", (char**) &sym_fname,
52
(char**) &sym_fname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
53
{"numeric-dump-file", 'n', "Read the dump from specified file.",
54
(char**) &dump_fname, (char**) &dump_fname, 0, GET_STR, REQUIRED_ARG,
56
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
60
static void verify_sort(void);
62
static void print_version(void)
64
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
65
VERSION,SYSTEM_TYPE,MACHINE_TYPE);
69
static void usage(void)
72
printf("MySQL AB, by Sasha Pachev\n");
73
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
74
printf("Resolve numeric stack strace dump into symbols.\n\n");
75
printf("Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n",
77
my_print_help(my_long_options);
78
my_print_variables(my_long_options);
80
The symbols-file should include the output from: 'nm --numeric-sort drizzled'.\n\
81
The numeric-dump-file should contain a numeric stack trace from drizzled.\n\
82
If the numeric-dump-file is not given, the stack trace is read from stdin.\n");
85
static void die(const char* fmt, ...)
89
fprintf(stderr, "%s: ", my_progname);
90
vfprintf(stderr, fmt, args);
91
fprintf(stderr, "\n");
98
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
99
char *argument __attribute__((unused)))
113
static int parse_args(int argc, char **argv)
117
if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option)))
121
The following code is to make the command compatible with the old
122
version that required one to use the -n and -s options
134
else if (!dump_fname)
135
dump_fname = argv[0];
142
else if (argc != 0 || !sym_fname)
151
static void open_files(void)
156
if (dump_fname && !(fp_dump = my_fopen(dump_fname, O_RDONLY, MYF(MY_WME))))
157
die("Could not open %s", dump_fname);
158
/* if name not given, assume stdin*/
161
die("Please run nm --numeric-sort on drizzled binary that produced stack \
162
trace dump and specify the path to it with -s or --symbols-file");
163
if (!(fp_sym = my_fopen(sym_fname, O_RDONLY, MYF(MY_WME))))
164
die("Could not open %s", sym_fname);
168
static unsigned char hex_val(char c)
171
if (my_isdigit(&my_charset_utf8_general_ci,c))
173
l = my_tolower(&my_charset_utf8_general_ci,c);
174
if (l < 'a' || l > 'f')
176
return (unsigned char)10 + ((unsigned char)c - (unsigned char)'a');
179
static unsigned long read_addr(char** buf)
183
unsigned long addr = 0;
185
while((c = hex_val(*p++)) != HEX_INVALID)
186
addr = (addr << 4) + c;
192
static int init_sym_entry(SYM_ENTRY* se, char* buf)
195
se->addr = (unsigned char*)read_addr(&buf);
199
while (my_isspace(&my_charset_utf8_general_ci,*buf++))
202
while (my_isspace(&my_charset_utf8_general_ci,*buf++))
203
/* empty - skip more space */;
205
/* now we are on the symbol */
206
for (p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
207
*buf != '\n' && *buf && p < p_end; ++buf,++p)
210
if (!strcmp(se->symbol, "gcc2_compiled."))
215
static void init_sym_table(void)
218
if (my_init_dynamic_array(&sym_table, sizeof(SYM_ENTRY), INIT_SYM_TABLE,
220
die("Failed in my_init_dynamic_array() -- looks like out of memory problem");
222
while (fgets(buf, sizeof(buf), fp_sym))
225
if (init_sym_entry(&se, buf))
227
if (insert_dynamic(&sym_table, (unsigned char*)&se))
228
die("insert_dynamic() failed - looks like we are out of memory");
234
static void clean_up(void)
236
delete_dynamic(&sym_table);
239
static void verify_sort()
242
unsigned char* last = 0;
244
for (i = 0; i < sym_table.elements; i++)
247
get_dynamic(&sym_table, (unsigned char*)&se, i);
249
die("sym table does not appear to be sorted, did you forget \
250
--numeric-sort arg to nm? trouble addr = %p, last = %p", se.addr, last);
256
static SYM_ENTRY* resolve_addr(unsigned char* addr, SYM_ENTRY* se)
259
get_dynamic(&sym_table, (unsigned char*)se, 0);
263
for (i = 1; i < sym_table.elements; i++)
265
get_dynamic(&sym_table, (unsigned char*)se, i);
268
get_dynamic(&sym_table, (unsigned char*)se, i - 1);
277
static void do_resolve(void)
280
while (fgets(buf, sizeof(buf), fp_dump))
284
while (my_isspace(&my_charset_utf8_general_ci,*p))
287
if (*p++ == '0' && *p++ == 'x')
290
unsigned char* addr = (unsigned char*)read_addr(&p);
291
if (resolve_addr(addr, &se))
292
fprintf(fp_out, "%p %s + %d\n", addr, se.symbol,
293
(int) (addr - se.addr));
295
fprintf(fp_out, "%p (?)\n", addr);
307
int main(int argc, char** argv)
310
parse_args(argc, argv);