~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
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.
6
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.
11
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 */
15
77.1.39 by Monty Taylor
More mysql->drizzle renaming.
16
/* Resolve numeric stack dump produced by drizzled 3.23.30 and later
1 by brian
clean slate
17
   versions into symbolic names. By Sasha Pachev <sasha@mysql.com>
18
 */
19
20
#include <my_global.h>
21
#include <m_ctype.h>
22
#include <my_sys.h>
23
#include <m_string.h>
77.1.39 by Monty Taylor
More mysql->drizzle renaming.
24
#include <drizzle_version.h>
1 by brian
clean slate
25
#include <errno.h>
26
#include <my_getopt.h>
27
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
33
34
typedef ulong my_long_addr_t ; /* at some point, we need to fix configure
35
				* to define this for us  
36
				*/
37
38
typedef struct sym_entry
39
{
40
  char symbol[MAX_SYM_SIZE];
41
  uchar* addr;
42
} SYM_ENTRY;
43
44
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; 
48
49
static struct my_option my_long_options[] =
50
{
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},
77.1.78 by Monty Taylor
One last bunch of warnings edits.
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},
1 by brian
clean slate
57
  {"numeric-dump-file", 'n', "Read the dump from specified file.",
77.1.78 by Monty Taylor
One last bunch of warnings edits.
58
   (char**) &dump_fname, (char**) &dump_fname, 0, GET_STR, REQUIRED_ARG,
1 by brian
clean slate
59
   0, 0, 0, 0, 0, 0},
60
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
61
};
62
63
77.1.44 by Monty Taylor
Fixed warnings in test
64
static void verify_sort(void);
1 by brian
clean slate
65
66
67
#include <help_start.h>
68
69
static void print_version(void)
70
{
71
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
72
	 MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
73
}
74
75
77.1.44 by Monty Taylor
Fixed warnings in test
76
static void usage(void)
1 by brian
clean slate
77
{
78
  print_version();
79
  printf("MySQL AB, by Sasha Pachev\n");
80
  printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
81
  printf("Resolve numeric stack strace dump into symbols.\n\n");
82
  printf("Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n",
83
	 my_progname);
84
  my_print_help(my_long_options);
85
  my_print_variables(my_long_options);
86
  printf("\n\
77.1.39 by Monty Taylor
More mysql->drizzle renaming.
87
The symbols-file should include the output from:  'nm --numeric-sort drizzled'.\n\
88
The numeric-dump-file should contain a numeric stack trace from drizzled.\n\
1 by brian
clean slate
89
If the numeric-dump-file is not given, the stack trace is read from stdin.\n");
90
}
91
92
#include <help_end.h>
93
94
95
static void die(const char* fmt, ...)
96
{
97
  va_list args;
98
  va_start(args, fmt);
99
  fprintf(stderr, "%s: ", my_progname);
100
  vfprintf(stderr, fmt, args);
101
  fprintf(stderr, "\n");
102
  va_end(args);
103
  exit(1);
104
}
105
106
146 by Brian Aker
my_bool cleanup.
107
static bool
1 by brian
clean slate
108
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
109
	       char *argument __attribute__((unused)))
110
{
111
  switch(optid) {
112
  case 'V':
113
    print_version();
114
    exit(0);
115
  case '?':
116
    usage();
117
    exit(0);
118
  }
119
  return 0;
120
}
121
122
123
static int parse_args(int argc, char **argv)
124
{
125
  int ho_error;
126
146 by Brian Aker
my_bool cleanup.
127
  if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option)))
1 by brian
clean slate
128
    exit(ho_error);
129
130
  /*
131
    The following code is to make the command compatible with the old
132
    version that required one to use the -n and -s options
133
  */
134
135
  if (argc == 2)
136
  {
137
    sym_fname= argv[0];
138
    dump_fname= argv[1];
139
  }
140
  else if (argc == 1)
141
  {
142
    if (!sym_fname)
143
      sym_fname = argv[0];
144
    else if (!dump_fname)
145
      dump_fname = argv[0];
146
    else
147
    {
148
      usage();
149
      exit(1);
150
    }
151
  }
152
  else if (argc != 0 || !sym_fname)
153
  {
154
    usage();
155
    exit(1);
156
  }
157
  return 0;
158
}
159
160
77.1.44 by Monty Taylor
Fixed warnings in test
161
static void open_files(void)
1 by brian
clean slate
162
{
163
  fp_out = stdout;
164
  fp_dump = stdin;
165
166
  if (dump_fname && !(fp_dump = my_fopen(dump_fname, O_RDONLY, MYF(MY_WME))))
167
      die("Could not open %s", dump_fname);
168
  /* if name not given, assume stdin*/
169
170
  if (!sym_fname)
77.1.39 by Monty Taylor
More mysql->drizzle renaming.
171
    die("Please run nm --numeric-sort on drizzled binary that produced stack \
1 by brian
clean slate
172
trace dump and specify the path to it with -s or --symbols-file");
173
  if (!(fp_sym = my_fopen(sym_fname, O_RDONLY, MYF(MY_WME))))
174
    die("Could not open %s", sym_fname);
175
176
}
177
178
static uchar hex_val(char c)
179
{
180
  uchar l;
181
  if (my_isdigit(&my_charset_latin1,c))
182
    return c - '0';
183
  l = my_tolower(&my_charset_latin1,c);
184
  if (l < 'a' || l > 'f')
185
    return HEX_INVALID; 
186
  return (uchar)10 + ((uchar)c - (uchar)'a');
187
}
188
189
static my_long_addr_t read_addr(char** buf)
190
{
191
  uchar c;
192
  char* p = *buf;
193
  my_long_addr_t addr = 0;
194
195
  while((c = hex_val(*p++)) != HEX_INVALID)
196
      addr = (addr << 4) + c;
197
198
  *buf = p; 
199
  return addr;
200
}
201
202
static int init_sym_entry(SYM_ENTRY* se, char* buf)
203
{
204
  char* p, *p_end;
205
  se->addr = (uchar*)read_addr(&buf);
206
207
  if (!se->addr)
208
    return -1;
209
  while (my_isspace(&my_charset_latin1,*buf++))
210
    /* empty */;
211
212
  while (my_isspace(&my_charset_latin1,*buf++))
213
    /* empty - skip more space */;
214
  --buf;
215
  /* now we are on the symbol */
216
  for (p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
217
       *buf != '\n' && *buf && p < p_end; ++buf,++p)
218
    *p = *buf;
219
  *p = 0;
220
  if (!strcmp(se->symbol, "gcc2_compiled."))
221
    return -1;
222
  return 0;
223
}
224
77.1.44 by Monty Taylor
Fixed warnings in test
225
static void init_sym_table(void)
1 by brian
clean slate
226
{
227
  char buf[512];
228
  if (my_init_dynamic_array(&sym_table, sizeof(SYM_ENTRY), INIT_SYM_TABLE,
229
			    INC_SYM_TABLE))
230
    die("Failed in my_init_dynamic_array() -- looks like out of memory problem");
231
232
  while (fgets(buf, sizeof(buf), fp_sym))
233
  {
234
    SYM_ENTRY se;
235
    if (init_sym_entry(&se, buf))
236
      continue;
237
    if (insert_dynamic(&sym_table, (uchar*)&se))
238
      die("insert_dynamic() failed - looks like we are out of memory");
239
  }
240
241
  verify_sort();
242
}
243
77.1.44 by Monty Taylor
Fixed warnings in test
244
static void clean_up(void)
1 by brian
clean slate
245
{
246
  delete_dynamic(&sym_table);
247
}
248
249
static void verify_sort()
250
{
251
  uint i;
252
  uchar* last = 0;
253
254
  for (i = 0; i < sym_table.elements; i++)
255
  {
256
    SYM_ENTRY se;
257
    get_dynamic(&sym_table, (uchar*)&se, i);
258
    if (se.addr < last)
259
      die("sym table does not appear to be sorted, did you forget \
260
--numeric-sort arg to nm? trouble addr = %p, last = %p", se.addr, last);
261
    last = se.addr;
262
  }
263
}
264
265
266
static SYM_ENTRY* resolve_addr(uchar* addr, SYM_ENTRY* se)
267
{
268
  uint i;
269
  get_dynamic(&sym_table, (uchar*)se, 0);
270
  if (addr < se->addr)
271
    return 0;
272
273
  for (i = 1; i < sym_table.elements; i++)
274
  {
275
    get_dynamic(&sym_table, (uchar*)se, i);
276
    if (addr < se->addr)
277
    {
278
      get_dynamic(&sym_table, (uchar*)se, i - 1);
279
      return se;
280
    }
281
  }
282
283
  return se;
284
}
285
286
77.1.44 by Monty Taylor
Fixed warnings in test
287
static void do_resolve(void)
1 by brian
clean slate
288
{
289
  char buf[1024], *p;
290
  while (fgets(buf, sizeof(buf), fp_dump))
291
  {
292
    p = buf;
293
    /* skip space */
294
    while (my_isspace(&my_charset_latin1,*p))
295
      ++p;
296
297
    if (*p++ == '0' && *p++ == 'x')
298
    {
299
      SYM_ENTRY se ;
300
      uchar* addr = (uchar*)read_addr(&p);
301
      if (resolve_addr(addr, &se))
302
	fprintf(fp_out, "%p %s + %d\n", addr, se.symbol,
303
		(int) (addr - se.addr));
304
      else
305
	fprintf(fp_out, "%p (?)\n", addr);
306
307
    }
308
    else
309
    {
310
      fputs(buf, fp_out);
311
      continue;
312
    }
313
  }
314
}
315
316
317
int main(int argc, char** argv)
318
{
319
  MY_INIT(argv[0]);
320
  parse_args(argc, argv);
321
  open_files();
322
  init_sym_table();
323
  do_resolve();
324
  clean_up();
325
  return 0;
326
}