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>
21
#include "drizzled/charset_info.h"
22
#include "drizzled/internal/my_sys.h"
23
#include "drizzled/internal/m_string.h"
25
#include "drizzled/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
34
extern "C" bool get_one_option(int optid, const struct my_option *, char *);
36
typedef struct sym_entry
38
char symbol[MAX_SYM_SIZE];
43
static char* dump_fname = 0, *sym_fname = 0;
44
static DYNAMIC_ARRAY sym_table; /* how do you like this , static DYNAMIC ? */
45
static FILE* fp_dump, *fp_sym = 0, *fp_out;
47
static struct my_option my_long_options[] =
49
{"help", 'h', "Display this help and exit.",
50
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
51
{"version", 'V', "Output version information and exit.",
52
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
53
{"symbols-file", 's', "Use specified symbols file.", (char**) &sym_fname,
54
(char**) &sym_fname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
55
{"numeric-dump-file", 'n', "Read the dump from specified file.",
56
(char**) &dump_fname, (char**) &dump_fname, 0, GET_STR, REQUIRED_ARG,
58
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
62
static void verify_sort(void);
64
static void print_version(void)
66
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",my_progname,DUMP_VERSION,
67
VERSION,HOST_VENDOR,HOST_OS,HOST_CPU);
71
static void usage(void)
74
printf("MySQL AB, by Sasha Pachev\n");
75
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
76
printf("Resolve numeric stack strace dump into symbols.\n\n");
77
printf("Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n",
79
my_print_help(my_long_options);
80
my_print_variables(my_long_options);
82
The symbols-file should include the output from: 'nm --numeric-sort drizzled'.\n\
83
The numeric-dump-file should contain a numeric stack trace from drizzled.\n\
84
If the numeric-dump-file is not given, the stack trace is read from stdin.\n");
87
static void die(const char* fmt, ...)
91
fprintf(stderr, "%s: ", my_progname);
92
vfprintf(stderr, fmt, args);
93
fprintf(stderr, "\n");
99
bool get_one_option(int optid, const struct my_option *, char *)
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= fopen(dump_fname, "r")))
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= fopen(sym_fname, "r")))
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);