~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to tests/resolve_stack_dump.cc

  • Committer: Brian Aker
  • Date: 2010-08-18 16:12:58 UTC
  • mto: This revision was merged to the branch mainline in revision 1720.
  • Revision ID: brian@tangent.org-20100818161258-1vm71da888dfvwsx
Remove the code surrounding stack trace.

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 "config.h"
21
 
#include <iostream>
22
 
#include <cstdio>
23
 
#include <cerrno>
24
 
 
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"
29
 
#include <boost/program_options.hpp>
30
 
 
31
 
using namespace std;
32
 
namespace po= boost::program_options;
33
 
using namespace drizzled;
34
 
 
35
 
#define INIT_SYM_TABLE  4096
36
 
#define INC_SYM_TABLE  4096
37
 
#define MAX_SYM_SIZE   128
38
 
#define DUMP_VERSION "1.4"
39
 
#define HEX_INVALID  (unsigned char)255
40
 
 
41
 
typedef struct sym_entry
42
 
{
43
 
  char symbol[MAX_SYM_SIZE];
44
 
  unsigned char* addr;
45
 
} SYM_ENTRY;
46
 
 
47
 
 
48
 
std::string dump_fname, sym_fname;
49
 
static DYNAMIC_ARRAY sym_table; /* how do you like this , static DYNAMIC ? */
50
 
static FILE* fp_dump, *fp_sym = 0, *fp_out;
51
 
 
52
 
static void verify_sort(void);
53
 
 
54
 
static void die(const char* fmt, ...)
55
 
{
56
 
  va_list args;
57
 
  va_start(args, fmt);
58
 
  fprintf(stderr, "%s: ", internal::my_progname);
59
 
  vfprintf(stderr, fmt, args);
60
 
  fprintf(stderr, "\n");
61
 
  va_end(args);
62
 
  exit(1);
63
 
}
64
 
 
65
 
static void open_files(void)
66
 
{
67
 
  fp_out = stdout;
68
 
  fp_dump = stdin;
69
 
 
70
 
  if (! dump_fname.empty() && !(fp_dump= fopen(dump_fname.c_str(), "r")))
71
 
      die("Could not open %s", dump_fname.c_str());
72
 
  /* if name not given, assume stdin*/
73
 
 
74
 
  if (sym_fname.empty())
75
 
    die("Please run nm --numeric-sort on drizzled binary that produced stack "
76
 
        "trace dump and specify the path to it with -s or --symbols-file");
77
 
  if (!(fp_sym= fopen(sym_fname.c_str(), "r")))
78
 
    die("Could not open %s", sym_fname.c_str());
79
 
 
80
 
}
81
 
 
82
 
static unsigned char hex_val(char c)
83
 
{
84
 
  unsigned char l;
85
 
  if (my_isdigit(&my_charset_utf8_general_ci,c))
86
 
    return c - '0';
87
 
  l = my_tolower(&my_charset_utf8_general_ci,c);
88
 
  if (l < 'a' || l > 'f')
89
 
    return HEX_INVALID;
90
 
  return (unsigned char)10 + ((unsigned char)c - (unsigned char)'a');
91
 
}
92
 
 
93
 
static unsigned long read_addr(char** buf)
94
 
{
95
 
  unsigned char c;
96
 
  char* p = *buf;
97
 
  unsigned long addr = 0;
98
 
 
99
 
  while((c = hex_val(*p++)) != HEX_INVALID)
100
 
      addr = (addr << 4) + c;
101
 
 
102
 
  *buf = p;
103
 
  return addr;
104
 
}
105
 
 
106
 
static int init_sym_entry(SYM_ENTRY* se, char* buf)
107
 
{
108
 
  char* p, *p_end;
109
 
  se->addr = (unsigned char*)read_addr(&buf);
110
 
 
111
 
  if (!se->addr)
112
 
    return -1;
113
 
  while (my_isspace(&my_charset_utf8_general_ci,*buf++))
114
 
    /* empty */;
115
 
 
116
 
  while (my_isspace(&my_charset_utf8_general_ci,*buf++))
117
 
    /* empty - skip more space */;
118
 
  --buf;
119
 
  /* now we are on the symbol */
120
 
  for (p = se->symbol, p_end = se->symbol + sizeof(se->symbol) - 1;
121
 
       *buf != '\n' && *buf && p < p_end; ++buf,++p)
122
 
    *p = *buf;
123
 
  *p = 0;
124
 
  if (!strcmp(se->symbol, "gcc2_compiled."))
125
 
    return -1;
126
 
  return 0;
127
 
}
128
 
 
129
 
static void init_sym_table(void)
130
 
{
131
 
  char buf[512];
132
 
  if (my_init_dynamic_array(&sym_table, sizeof(SYM_ENTRY), INIT_SYM_TABLE,
133
 
                            INC_SYM_TABLE))
134
 
    die("Failed in my_init_dynamic_array() -- looks like out of memory problem");
135
 
 
136
 
  while (fgets(buf, sizeof(buf), fp_sym))
137
 
  {
138
 
    SYM_ENTRY se;
139
 
    if (init_sym_entry(&se, buf))
140
 
      continue;
141
 
    if (insert_dynamic(&sym_table, (unsigned char*)&se))
142
 
      die("insert_dynamic() failed - looks like we are out of memory");
143
 
  }
144
 
 
145
 
  verify_sort();
146
 
}
147
 
 
148
 
static void clean_up(void)
149
 
{
150
 
  delete_dynamic(&sym_table);
151
 
}
152
 
 
153
 
static void verify_sort()
154
 
{
155
 
  uint32_t i;
156
 
  unsigned char* last = 0;
157
 
 
158
 
  for (i = 0; i < sym_table.elements; i++)
159
 
  {
160
 
    SYM_ENTRY se;
161
 
    get_dynamic(&sym_table, (unsigned char*)&se, i);
162
 
    if (se.addr < last)
163
 
      die("sym table does not appear to be sorted, did you forget "
164
 
          "--numeric-sort arg to nm? trouble addr = %p, last = %p",
165
 
          se.addr, last);
166
 
    last = se.addr;
167
 
  }
168
 
}
169
 
 
170
 
 
171
 
static SYM_ENTRY* resolve_addr(unsigned char* addr, SYM_ENTRY* se)
172
 
{
173
 
  uint32_t i;
174
 
  get_dynamic(&sym_table, (unsigned char*)se, 0);
175
 
  if (addr < se->addr)
176
 
    return 0;
177
 
 
178
 
  for (i = 1; i < sym_table.elements; i++)
179
 
  {
180
 
    get_dynamic(&sym_table, (unsigned char*)se, i);
181
 
    if (addr < se->addr)
182
 
    {
183
 
      get_dynamic(&sym_table, (unsigned char*)se, i - 1);
184
 
      return se;
185
 
    }
186
 
  }
187
 
 
188
 
  return se;
189
 
}
190
 
 
191
 
 
192
 
static void do_resolve(void)
193
 
{
194
 
  char buf[1024], *p;
195
 
  while (fgets(buf, sizeof(buf), fp_dump))
196
 
  {
197
 
    p = buf;
198
 
    /* skip space */
199
 
    while (my_isspace(&my_charset_utf8_general_ci,*p))
200
 
      ++p;
201
 
 
202
 
    if (*p++ == '0' && *p++ == 'x')
203
 
    {
204
 
      SYM_ENTRY se ;
205
 
      unsigned char* addr = (unsigned char*)read_addr(&p);
206
 
      if (resolve_addr(addr, &se))
207
 
        fprintf(fp_out, "%p %s + %d\n", addr, se.symbol,
208
 
                (int) (addr - se.addr));
209
 
      else
210
 
        fprintf(fp_out, "%p (?)\n", addr);
211
 
 
212
 
    }
213
 
    else
214
 
    {
215
 
      fputs(buf, fp_out);
216
 
      continue;
217
 
    }
218
 
  }
219
 
}
220
 
 
221
 
 
222
 
int main(int argc, char** argv)
223
 
{
224
 
try
225
 
{
226
 
  MY_INIT(argv[0]);
227
 
 
228
 
  po::options_description commandline_options("Options specific to the commandline");
229
 
  commandline_options.add_options()
230
 
  ("help,h", "Display this help and exit.")
231
 
  ("version,V", "Output version information and exit.") 
232
 
  ;
233
 
 
234
 
  po::options_description positional_options("Positional Options");
235
 
  positional_options.add_options()
236
 
  ("symbols-file,s", po::value<string>(),
237
 
  "Use specified symbols file.")
238
 
  ("numeric-dump-file,n", po::value<string>(),
239
 
  "Read the dump from specified file.")
240
 
  ;
241
 
 
242
 
  po::options_description long_options("Allowed Options");
243
 
  long_options.add(commandline_options).add(positional_options);
244
 
 
245
 
  po::positional_options_description p;
246
 
  p.add("symbols-file,s", 1);
247
 
  p.add("numeric-dump-file,n",1);
248
 
 
249
 
  po::variables_map vm;
250
 
  po::store(po::command_line_parser(argc, argv).options(long_options).positional(p).run(), vm);
251
 
  po::notify(vm);
252
 
 
253
 
  if (vm.count("help"))
254
 
  {
255
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,DUMP_VERSION,
256
 
         VERSION,HOST_VENDOR,HOST_OS,HOST_CPU);
257
 
    printf("MySQL AB, by Sasha Pachev\n");
258
 
    printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
259
 
    printf("Resolve numeric stack strace dump into symbols.\n\n");
260
 
    printf("Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n",
261
 
          internal::my_progname);
262
 
    cout << long_options << endl;
263
 
    printf("\n"
264
 
         "The symbols-file should include the output from: \n"
265
 
         "  'nm --numeric-sort drizzled'.\n"
266
 
         "The numeric-dump-file should contain a numeric stack trace "
267
 
         "from drizzled.\n"
268
 
         "If the numeric-dump-file is not given, the stack trace is "
269
 
         "read from stdin.\n");
270
 
  }
271
 
    
272
 
  if (vm.count("version"))
273
 
  {
274
 
    printf("%s  Ver %s Distrib %s, for %s-%s (%s)\n",internal::my_progname,DUMP_VERSION,
275
 
         VERSION,HOST_VENDOR,HOST_OS,HOST_CPU);
276
 
  }
277
 
    
278
 
  if (vm.count("symbols-file") && vm.count("numeric-file-dump"))
279
 
  {
280
 
    sym_fname= vm["symbols-file"].as<string>();
281
 
    dump_fname= vm["numeric-dump-file"].as<string>();
282
 
  }
283
 
 
284
 
  open_files();
285
 
  init_sym_table();
286
 
  do_resolve();
287
 
  clean_up();
288
 
}
289
 
  catch(exception &err)
290
 
  {
291
 
    cerr << err.what() << endl;
292
 
  }
293
 
 
294
 
   return 0;
295
 
}