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>
25
#include "drizzled/charset_info.h"
26
#include "drizzled/internal/my_sys.h"
27
#include "drizzled/internal/m_string.h"
28
#include "drizzled/option.h"
30
using namespace drizzled;
32
#define INIT_SYM_TABLE 4096
33
#define INC_SYM_TABLE 4096
34
#define MAX_SYM_SIZE 128
35
#define DUMP_VERSION "1.4"
36
#define HEX_INVALID (unsigned char)255
38
typedef struct sym_entry
40
char symbol[MAX_SYM_SIZE];
45
static char* dump_fname = 0, *sym_fname = 0;
46
static DYNAMIC_ARRAY sym_table; /* how do you like this , static DYNAMIC ? */
47
static FILE* fp_dump, *fp_sym = 0, *fp_out;
49
static struct 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.", (char**) &sym_fname,
56
(char**) &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
(char**) &dump_fname, (char**) &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(void);
66
static void print_version(void)
68
printf("%s Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,DUMP_VERSION,
69
VERSION,HOST_VENDOR,HOST_OS,HOST_CPU);
73
static void usage(void)
76
printf("MySQL AB, by Sasha Pachev\n");
77
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
78
printf("Resolve numeric stack strace dump into symbols.\n\n");
79
printf("Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n",
80
internal::my_progname);
81
my_print_help(my_long_options);
82
my_print_variables(my_long_options);
84
The symbols-file should include the output from: 'nm --numeric-sort drizzled'.\n\
85
The numeric-dump-file should contain a numeric stack trace from drizzled.\n\
86
If the numeric-dump-file is not given, the stack trace is read from stdin.\n");
89
static void die(const char* fmt, ...)
93
fprintf(stderr, "%s: ", internal::my_progname);
94
vfprintf(stderr, fmt, args);
95
fprintf(stderr, "\n");
101
static int get_one_option(int optid, const struct option *, char *)
115
static int parse_args(int argc, char **argv)
119
if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option)))
123
The following code is to make the command compatible with the old
124
version that required one to use the -n and -s options
136
else if (!dump_fname)
137
dump_fname = argv[0];
144
else if (argc != 0 || !sym_fname)
153
static void open_files(void)
158
if (dump_fname && !(fp_dump= fopen(dump_fname, "r")))
159
die("Could not open %s", dump_fname);
160
/* if name not given, assume stdin*/
163
die("Please run nm --numeric-sort on drizzled binary that produced stack \
164
trace dump and specify the path to it with -s or --symbols-file");
165
if (!(fp_sym= fopen(sym_fname, "r")))
166
die("Could not open %s", sym_fname);
170
static unsigned char hex_val(char c)
173
if (my_isdigit(&my_charset_utf8_general_ci,c))
175
l = my_tolower(&my_charset_utf8_general_ci,c);
176
if (l < 'a' || l > 'f')
178
return (unsigned char)10 + ((unsigned char)c - (unsigned char)'a');
181
static unsigned long read_addr(char** buf)
185
unsigned long addr = 0;
187
while((c = hex_val(*p++)) != HEX_INVALID)
188
addr = (addr << 4) + c;
194
static int init_sym_entry(SYM_ENTRY* se, char* buf)
197
se->addr = (unsigned char*)read_addr(&buf);
201
while (my_isspace(&my_charset_utf8_general_ci,*buf++))
204
while (my_isspace(&my_charset_utf8_general_ci,*buf++))
205
/* empty - skip more space */;
207
/* now we are on the symbol */
208
for (p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
209
*buf != '\n' && *buf && p < p_end; ++buf,++p)
212
if (!strcmp(se->symbol, "gcc2_compiled."))
217
static void init_sym_table(void)
220
if (my_init_dynamic_array(&sym_table, sizeof(SYM_ENTRY), INIT_SYM_TABLE,
222
die("Failed in my_init_dynamic_array() -- looks like out of memory problem");
224
while (fgets(buf, sizeof(buf), fp_sym))
227
if (init_sym_entry(&se, buf))
229
if (insert_dynamic(&sym_table, (unsigned char*)&se))
230
die("insert_dynamic() failed - looks like we are out of memory");
236
static void clean_up(void)
238
delete_dynamic(&sym_table);
241
static void verify_sort()
244
unsigned char* last = 0;
246
for (i = 0; i < sym_table.elements; i++)
249
get_dynamic(&sym_table, (unsigned char*)&se, i);
251
die("sym table does not appear to be sorted, did you forget \
252
--numeric-sort arg to nm? trouble addr = %p, last = %p", se.addr, last);
258
static SYM_ENTRY* resolve_addr(unsigned char* addr, SYM_ENTRY* se)
261
get_dynamic(&sym_table, (unsigned char*)se, 0);
265
for (i = 1; i < sym_table.elements; i++)
267
get_dynamic(&sym_table, (unsigned char*)se, i);
270
get_dynamic(&sym_table, (unsigned char*)se, i - 1);
279
static void do_resolve(void)
282
while (fgets(buf, sizeof(buf), fp_dump))
286
while (my_isspace(&my_charset_utf8_general_ci,*p))
289
if (*p++ == '0' && *p++ == 'x')
292
unsigned char* addr = (unsigned char*)read_addr(&p);
293
if (resolve_addr(addr, &se))
294
fprintf(fp_out, "%p %s + %d\n", addr, se.symbol,
295
(int) (addr - se.addr));
297
fprintf(fp_out, "%p (?)\n", addr);
309
int main(int argc, char** argv)
312
parse_args(argc, argv);