~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to tests/resolve_stack_dump.cc

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
16
 
/* Resolve numeric stack dump produced by drizzled 3.23.30 and later
17
 
   versions into symbolic names. By Sasha Pachev <sasha@mysql.com>
18
 
 */
19
 
 
20
 
#include <drizzled/global.h>
21
 
#include <mystrings/m_ctype.h>
22
 
#include <mysys/my_sys.h>
23
 
#include <mystrings/m_string.h>
24
 
#include <errno.h>
25
 
#include <mysys/my_getopt.h>
26
 
#include <stdio.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  (unsigned char)255
33
 
 
34
 
 
35
 
typedef struct sym_entry
36
 
{
37
 
  char symbol[MAX_SYM_SIZE];
38
 
  unsigned char* addr;
39
 
} SYM_ENTRY;
40
 
 
41
 
 
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; 
45
 
 
46
 
static struct my_option my_long_options[] =
47
 
{
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,
56
 
   0, 0, 0, 0, 0, 0},
57
 
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
58
 
};
59
 
 
60
 
 
61
 
static void verify_sort(void);
62
 
 
63
 
static void print_version(void)
64
 
{
65
 
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION,
66
 
         VERSION,SYSTEM_TYPE,MACHINE_TYPE);
67
 
}
68
 
 
69
 
 
70
 
static void usage(void)
71
 
{
72
 
  print_version();
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",
77
 
         my_progname);
78
 
  my_print_help(my_long_options);
79
 
  my_print_variables(my_long_options);
80
 
  printf("\n\
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");
84
 
}
85
 
 
86
 
static void die(const char* fmt, ...)
87
 
{
88
 
  va_list args;
89
 
  va_start(args, fmt);
90
 
  fprintf(stderr, "%s: ", my_progname);
91
 
  vfprintf(stderr, fmt, args);
92
 
  fprintf(stderr, "\n");
93
 
  va_end(args);
94
 
  exit(1);
95
 
}
96
 
 
97
 
 
98
 
static bool
99
 
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
100
 
               char *argument __attribute__((unused)))
101
 
{
102
 
  switch(optid) {
103
 
  case 'V':
104
 
    print_version();
105
 
    exit(0);
106
 
  case '?':
107
 
    usage();
108
 
    exit(0);
109
 
  }
110
 
  return 0;
111
 
}
112
 
 
113
 
 
114
 
static int parse_args(int argc, char **argv)
115
 
{
116
 
  int ho_error;
117
 
 
118
 
  if ((ho_error= handle_options(&argc, &argv, my_long_options, get_one_option)))
119
 
    exit(ho_error);
120
 
 
121
 
  /*
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
124
 
  */
125
 
 
126
 
  if (argc == 2)
127
 
  {
128
 
    sym_fname= argv[0];
129
 
    dump_fname= argv[1];
130
 
  }
131
 
  else if (argc == 1)
132
 
  {
133
 
    if (!sym_fname)
134
 
      sym_fname = argv[0];
135
 
    else if (!dump_fname)
136
 
      dump_fname = argv[0];
137
 
    else
138
 
    {
139
 
      usage();
140
 
      exit(1);
141
 
    }
142
 
  }
143
 
  else if (argc != 0 || !sym_fname)
144
 
  {
145
 
    usage();
146
 
    exit(1);
147
 
  }
148
 
  return 0;
149
 
}
150
 
 
151
 
 
152
 
static void open_files(void)
153
 
{
154
 
  fp_out = stdout;
155
 
  fp_dump = stdin;
156
 
 
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*/
160
 
 
161
 
  if (!sym_fname)
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);
166
 
 
167
 
}
168
 
 
169
 
static unsigned char hex_val(char c)
170
 
{
171
 
  unsigned char l;
172
 
  if (my_isdigit(&my_charset_utf8_general_ci,c))
173
 
    return c - '0';
174
 
  l = my_tolower(&my_charset_utf8_general_ci,c);
175
 
  if (l < 'a' || l > 'f')
176
 
    return HEX_INVALID; 
177
 
  return (unsigned char)10 + ((unsigned char)c - (unsigned char)'a');
178
 
}
179
 
 
180
 
static unsigned long read_addr(char** buf)
181
 
{
182
 
  unsigned char c;
183
 
  char* p = *buf;
184
 
  unsigned long addr = 0;
185
 
 
186
 
  while((c = hex_val(*p++)) != HEX_INVALID)
187
 
      addr = (addr << 4) + c;
188
 
 
189
 
  *buf = p; 
190
 
  return addr;
191
 
}
192
 
 
193
 
static int init_sym_entry(SYM_ENTRY* se, char* buf)
194
 
{
195
 
  char* p, *p_end;
196
 
  se->addr = (unsigned char*)read_addr(&buf);
197
 
 
198
 
  if (!se->addr)
199
 
    return -1;
200
 
  while (my_isspace(&my_charset_utf8_general_ci,*buf++))
201
 
    /* empty */;
202
 
 
203
 
  while (my_isspace(&my_charset_utf8_general_ci,*buf++))
204
 
    /* empty - skip more space */;
205
 
  --buf;
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)
209
 
    *p = *buf;
210
 
  *p = 0;
211
 
  if (!strcmp(se->symbol, "gcc2_compiled."))
212
 
    return -1;
213
 
  return 0;
214
 
}
215
 
 
216
 
static void init_sym_table(void)
217
 
{
218
 
  char buf[512];
219
 
  if (my_init_dynamic_array(&sym_table, sizeof(SYM_ENTRY), INIT_SYM_TABLE,
220
 
                            INC_SYM_TABLE))
221
 
    die("Failed in my_init_dynamic_array() -- looks like out of memory problem");
222
 
 
223
 
  while (fgets(buf, sizeof(buf), fp_sym))
224
 
  {
225
 
    SYM_ENTRY se;
226
 
    if (init_sym_entry(&se, buf))
227
 
      continue;
228
 
    if (insert_dynamic(&sym_table, (unsigned char*)&se))
229
 
      die("insert_dynamic() failed - looks like we are out of memory");
230
 
  }
231
 
 
232
 
  verify_sort();
233
 
}
234
 
 
235
 
static void clean_up(void)
236
 
{
237
 
  delete_dynamic(&sym_table);
238
 
}
239
 
 
240
 
static void verify_sort()
241
 
{
242
 
  uint32_t i;
243
 
  unsigned char* last = 0;
244
 
 
245
 
  for (i = 0; i < sym_table.elements; i++)
246
 
  {
247
 
    SYM_ENTRY se;
248
 
    get_dynamic(&sym_table, (unsigned char*)&se, i);
249
 
    if (se.addr < last)
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);
252
 
    last = se.addr;
253
 
  }
254
 
}
255
 
 
256
 
 
257
 
static SYM_ENTRY* resolve_addr(unsigned char* addr, SYM_ENTRY* se)
258
 
{
259
 
  uint32_t i;
260
 
  get_dynamic(&sym_table, (unsigned char*)se, 0);
261
 
  if (addr < se->addr)
262
 
    return 0;
263
 
 
264
 
  for (i = 1; i < sym_table.elements; i++)
265
 
  {
266
 
    get_dynamic(&sym_table, (unsigned char*)se, i);
267
 
    if (addr < se->addr)
268
 
    {
269
 
      get_dynamic(&sym_table, (unsigned char*)se, i - 1);
270
 
      return se;
271
 
    }
272
 
  }
273
 
 
274
 
  return se;
275
 
}
276
 
 
277
 
 
278
 
static void do_resolve(void)
279
 
{
280
 
  char buf[1024], *p;
281
 
  while (fgets(buf, sizeof(buf), fp_dump))
282
 
  {
283
 
    p = buf;
284
 
    /* skip space */
285
 
    while (my_isspace(&my_charset_utf8_general_ci,*p))
286
 
      ++p;
287
 
 
288
 
    if (*p++ == '0' && *p++ == 'x')
289
 
    {
290
 
      SYM_ENTRY se ;
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));
295
 
      else
296
 
        fprintf(fp_out, "%p (?)\n", addr);
297
 
 
298
 
    }
299
 
    else
300
 
    {
301
 
      fputs(buf, fp_out);
302
 
      continue;
303
 
    }
304
 
  }
305
 
}
306
 
 
307
 
 
308
 
int main(int argc, char** argv)
309
 
{
310
 
  MY_INIT(argv[0]);
311
 
  parse_args(argc, argv);
312
 
  open_files();
313
 
  init_sym_table();
314
 
  do_resolve();
315
 
  clean_up();
316
 
  return 0;
317
 
}