~ubuntu-branches/ubuntu/natty/mysql-5.1/natty

« back to all changes in this revision

Viewing changes to pstack/pstack.c

Tags: 5.1.54-1ubuntu1
* Synchronize from Debian Experimental:
* Merge from debian unstable:
  + debian/control:
     * Update maintainer according to spec.
     * Move section from "misc" to "database".
     * Added libmysqlclient16-dev an empty transitional package. 
     * Added mysql-client-core-5.1 package.
     * Suggest mailx for mysql-server-5.1
     * Add mysql-testsuite package so you can run the testsuite seperately.
  + debian/additions/my.cnf:
    * Remove language options. Error message files are located in a different directory in Mysql
      5.0. Setting the language option to use /usr/share/mysql/english breaks Mysql 5.0. Both 5.0
      and 5.1 use a different value that works. (LP: #316974)
  + Add apparmor profile:
    + debian/apparmor-profile: apparmor-profile
    + debian/rules, debian/mysql-server-5.1.files: install apparmor profile
    + debian/mysql-server-5.1.dirs: add etc/apparmor.d/fore-complain
    + debian/mysql-server-5.1.postrm: remove symlink in force-complain/ on purge.
    + debian/mysql-server-5.1.README.Debian: add apparmor documentation.
    + debian/additions/my.cnf: Add warning about apparmor. (LP: #201799)
    + debian/mysql-server-5.1.postinst: reload apparmor profiles
  * Convert the package from sysvinit to upstart:
    + debian/mysql-server-5.1.mysql.upstart: Add upstart script.
    + debian/mysql-server-5.1.mysql.init: Dropped, unused now with upstart.
    + debian/additions/mysqld_safe_syslog.cnf: Dropped, unused now with upstart.
    + debian/additons/my.cnf: Remove pid declaration and setup error logging to /var/log/mysql since
      we're not piping anything around logger anymore.
    + debian/rules, debian/mysql-server-5.1.logcheck.ignore.{paranoid,worstation},
      debian/mysql-server-5.1.logcheck.ignore.server: : Remove references to mysqld_safe
    + debian/patches/38_scripts_mysqld_safe.sh_signals.dpatch: Dropped
  * Added -fno-strict-aliasing to CFLAGS to get around mysql testsuite build failures.
  * Add Apport hook (LP: #354188):
    + debian/mysql-server-5.1.py: apport package hook
    + debian/rules: Make it installable
  * debian/mysql-server-5.1.mysql-server.logrotate: Check to see if mysql is running before
    running logrotate. (LP: #513135)
  * Make the testsuite installable. (LP: #530752)
    + debian/mysql-server-5.1.files, debian/rules: install apport package hook
  * debian/mysql-server-5.1.preinst: Set mysql user's home directory
    to /nonexistent to protect against having the /var/lib/mysql
    user-writeable. If an attacker can trick mysqld into creating
    dot files in the home directory, he could do .rhost-like attacks
    on the system. (LP: #293258)
  * debian/control: mysql-client-5.1 should depend on mysql-core-client-5.1.
    (LP: #590952)
  * debian/mysql-server.5.1.postinst: Specify the mysql user when installing 
    the mysql databases. (LP: #591875)
  * Installing mysql_config_pic in /usr/bin so users of libmysqld-pic
    can extract the appropriate compile flags. (LP: #605021) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 pstack.c -- asynchronous stack trace of a running process
3
 
 Copyright (c) 1999 Ross Thompson
4
 
 Author: Ross Thompson <ross@whatsis.com>
5
 
 Critical bug fix: Tim Waugh
6
 
*/
7
 
 
8
 
/*
9
 
 This file is free software; you can redistribute it and/or modify
10
 
 it under the terms of the GNU General Public License as published by
11
 
 the Free Software Foundation; either version 2 of the License, or
12
 
 (at your option) any later version.
13
 
 
14
 
 This program is distributed in the hope that it will be useful,
15
 
 but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
 GNU General Public License for more details.
18
 
 
19
 
 You should have received a copy of the GNU General Public License
20
 
 along with this program; if not, write to the Free Software
21
 
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
 
*/
23
 
 
24
 
/* RESTRICTIONS:
25
 
 
26
 
   pstack currently works only on Linux, only on an x86 machine running
27
 
   32 bit ELF binaries (64 bit not supported).  Also, for symbolic
28
 
   information, you need to use a GNU compiler to generate your
29
 
   program, and you can't strip symbols from the binaries.  For thread
30
 
   information to be dumped, you have to use the debug-aware version
31
 
   of libpthread.so.  (To check, run 'nm' on your libpthread.so, and
32
 
   make sure that the symbol "__pthread_threads_debug" is defined.)
33
 
 
34
 
   The details of pulling stuff out of ELF files and running through
35
 
   program images is very platform specific, and I don't want to
36
 
   try to support modes or machine types I can't test in or on.
37
 
   If someone wants to generalize this to other architectures, I would
38
 
   be happy to help and coordinate the activity.  Please send me whatever
39
 
   changes you make to support these machines, so that I can own the
40
 
   central font of all truth (at least as regards this program).
41
 
 
42
 
   Thanks 
43
 
*/
44
 
 
45
 
#include <sys/types.h>
46
 
#include <sys/stat.h>
47
 
#include <sys/wait.h>
48
 
#include <sys/ptrace.h>
49
 
#include <asm/ptrace.h>
50
 
 
51
 
#include <assert.h>
52
 
#include <fcntl.h>
53
 
#include <link.h>
54
 
#include <malloc.h>
55
 
#include <string.h>
56
 
#include <stdarg.h>
57
 
#include <unistd.h>
58
 
#include <stdlib.h>
59
 
#include <stdio.h>
60
 
#include <errno.h>
61
 
#include <signal.h>
62
 
#include <pthread.h>
63
 
#include <limits.h>             /* PTHREAD_THREADS_MAX */
64
 
 
65
 
 
66
 
#include <bfd.h>
67
 
 
68
 
#include "libiberty.h"
69
 
 
70
 
#include "pstack.h"             /* just one function */
71
 
#include "budbg.h"              /* binutils stuff related to debugging symbols. */
72
 
#include "bucomm.h"             /* some common stuff */
73
 
#include "debug.h"              /* and more binutils stuff... */
74
 
#include "budbg.h"
75
 
#include "linuxthreads.h"       /* LinuxThreads specific stuff... */
76
 
 
77
 
 
78
 
/*
79
 
 * fprintf for file descriptors :) NOTE: we have to use fixed-size buffer :)(
80
 
 * due to malloc's unavalaibility.
81
 
 */
82
 
int
83
 
fdprintf(       int             fd,
84
 
                const char*     fmt,...)
85
 
{
86
 
        char    xbuf[2048];// FIXME: enough?
87
 
        va_list ap;
88
 
        int     r;
89
 
        if (fd<0)
90
 
                return -1;
91
 
        va_start(ap, fmt);
92
 
        r = vsnprintf(xbuf, sizeof(xbuf), fmt, ap);
93
 
        va_end(ap);
94
 
        return write(fd, xbuf, r);
95
 
}
96
 
 
97
 
int
98
 
fdputc(         char            c,
99
 
                int             fd)
100
 
{
101
 
        if (fd<0)
102
 
                return -1;
103
 
        return write(fd, &c, sizeof(c));
104
 
}
105
 
 
106
 
int
107
 
fdputs(         const char*     s,
108
 
                int             fd)
109
 
{
110
 
        if (fd<0)
111
 
                return -1;
112
 
        return write(fd, s, strlen(s));
113
 
}
114
 
 
115
 
/*
116
 
 * Use this function to open log file.
117
 
 * Flags: truncate on opening.
118
 
 */
119
 
static  const char*             path_format = "stack-trace-on-segv-%d.txt";
120
 
static int
121
 
open_log_file(  const pthread_t tid,
122
 
                const pid_t     pid)
123
 
{
124
 
        char    fname[PATH_MAX];
125
 
        int     r;
126
 
        snprintf(fname, sizeof(fname), path_format, tid, pid);
127
 
        r = open(fname, O_WRONLY|O_CREAT|O_TRUNC,
128
 
                        S_IRUSR|S_IWUSR);
129
 
        if (r<0)
130
 
                perror("open");
131
 
        return r;
132
 
}
133
 
/*
134
 
 * Add additional debugging information for functions.
135
 
 */
136
 
 
137
 
/*
138
 
 * Lineno
139
 
 */
140
 
typedef struct {
141
 
        int                     lineno;
142
 
        bfd_vma                 addr;
143
 
} debug_lineno_t;
144
 
 
145
 
/*
146
 
 * Block - a {} pair.
147
 
 */
148
 
typedef struct debug_block_st {
149
 
        bfd_vma                 begin_addr;     /* where did it start */
150
 
        bfd_vma                 end_addr;       /* where did it end */
151
 
        struct debug_block_st*  parent;
152
 
        struct debug_block_st*  childs;
153
 
        int                     childs_count;
154
 
} debug_block_t;
155
 
 
156
 
/*
157
 
 * Function parameter.
158
 
 */
159
 
typedef struct {
160
 
        bfd_vma                 offset; /* Offset in the stack */
161
 
        const char*             name;   /* And name. */
162
 
} debug_parameter_t;
163
 
 
164
 
/*
165
 
 * Extra information about functions.
166
 
 */
167
 
typedef struct {
168
 
        asymbol*                symbol; /* mangled function name, addr */
169
 
        debug_lineno_t*         lines;
170
 
        int                     lines_count;
171
 
        int                     max_lines_count;
172
 
        const char*             name;
173
 
        const char*             filename;/* a file name it occured in... */
174
 
        debug_block_t*          block;  /* each function has a block, or not, you know */
175
 
        debug_parameter_t*      argv;   /* argument types. */
176
 
        int                     argc;
177
 
        int                     max_argc;
178
 
} debug_function_t;
179
 
 
180
 
/* This is the structure we use as a handle for these routines.  */
181
 
struct pr_handle
182
 
{
183
 
  /* File to print information to.  */
184
 
  FILE *f;
185
 
  /* Current indentation level.  */
186
 
  unsigned int indent;
187
 
  /* Type stack.  */
188
 
  struct pr_stack *stack;
189
 
  /* Parameter number we are about to output.  */
190
 
  int parameter;
191
 
  debug_block_t*        block;                  /* current block */
192
 
  debug_function_t*     function;               /* current function */
193
 
  debug_function_t*     functions;              /* all functions */
194
 
  int                   functions_size;         /* current size */
195
 
  int                   functions_maxsize;      /* maximum size */
196
 
};
197
 
 
198
 
/* The type stack.  */
199
 
 
200
 
struct pr_stack
201
 
{
202
 
  /* Next element on the stack.  */
203
 
  struct pr_stack *next;
204
 
  /* This element.  */
205
 
  char *type;
206
 
  /* Current visibility of fields if this is a class.  */
207
 
  enum debug_visibility visibility;
208
 
  /* Name of the current method we are handling.  */
209
 
  const char *method;
210
 
};
211
 
 
212
 
static void indent PARAMS ((struct pr_handle *));
213
 
static boolean push_type PARAMS ((struct pr_handle *, const char *));
214
 
static boolean prepend_type PARAMS ((struct pr_handle *, const char *));
215
 
static boolean append_type PARAMS ((struct pr_handle *, const char *));
216
 
static boolean substitute_type PARAMS ((struct pr_handle *, const char *));
217
 
static boolean indent_type PARAMS ((struct pr_handle *));
218
 
static char *pop_type PARAMS ((struct pr_handle *));
219
 
static void print_vma PARAMS ((bfd_vma, char *, boolean, boolean));
220
 
static boolean pr_fix_visibility
221
 
  PARAMS ((struct pr_handle *, enum debug_visibility));
222
 
 
223
 
static boolean pr_start_compilation_unit PARAMS ((PTR, const char *));
224
 
static boolean pr_start_source PARAMS ((PTR, const char *));
225
 
static boolean pr_empty_type PARAMS ((PTR));
226
 
static boolean pr_void_type PARAMS ((PTR));
227
 
static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean));
228
 
static boolean pr_float_type PARAMS ((PTR, unsigned int));
229
 
static boolean pr_complex_type PARAMS ((PTR, unsigned int));
230
 
static boolean pr_bool_type PARAMS ((PTR, unsigned int));
231
 
static boolean pr_enum_type
232
 
  PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
233
 
static boolean pr_pointer_type PARAMS ((PTR));
234
 
static boolean pr_function_type PARAMS ((PTR, int, boolean));
235
 
static boolean pr_reference_type PARAMS ((PTR));
236
 
static boolean pr_range_type PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma));
237
 
static boolean pr_array_type
238
 
  PARAMS ((PTR, bfd_signed_vma, bfd_signed_vma, boolean));
239
 
static boolean pr_set_type PARAMS ((PTR, boolean));
240
 
static boolean pr_offset_type PARAMS ((PTR));
241
 
static boolean pr_method_type PARAMS ((PTR, boolean, int, boolean));
242
 
static boolean pr_const_type PARAMS ((PTR));
243
 
static boolean pr_volatile_type PARAMS ((PTR));
244
 
static boolean pr_start_struct_type
245
 
  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
246
 
static boolean pr_struct_field
247
 
  PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
248
 
static boolean pr_end_struct_type PARAMS ((PTR));
249
 
static boolean pr_start_class_type
250
 
  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
251
 
           boolean));
252
 
static boolean pr_class_static_member
253
 
  PARAMS ((PTR, const char *, const char *, enum debug_visibility));
254
 
static boolean pr_class_baseclass
255
 
  PARAMS ((PTR, bfd_vma, boolean, enum debug_visibility));
256
 
static boolean pr_class_start_method PARAMS ((PTR, const char *));
257
 
static boolean pr_class_method_variant
258
 
  PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean,
259
 
           bfd_vma, boolean));
260
 
static boolean pr_class_static_method_variant
261
 
  PARAMS ((PTR, const char *, enum debug_visibility, boolean, boolean));
262
 
static boolean pr_class_end_method PARAMS ((PTR));
263
 
static boolean pr_end_class_type PARAMS ((PTR));
264
 
static boolean pr_typedef_type PARAMS ((PTR, const char *));
265
 
static boolean pr_tag_type
266
 
  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
267
 
static boolean pr_typdef PARAMS ((PTR, const char *));
268
 
static boolean pr_tag PARAMS ((PTR, const char *));
269
 
static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma));
270
 
static boolean pr_float_constant PARAMS ((PTR, const char *, double));
271
 
static boolean pr_typed_constant PARAMS ((PTR, const char *, bfd_vma));
272
 
static boolean pr_variable
273
 
  PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma));
274
 
static boolean pr_start_function PARAMS ((PTR, const char *, boolean));
275
 
static boolean pr_function_parameter
276
 
  PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
277
 
static boolean pr_start_block PARAMS ((PTR, bfd_vma));
278
 
static boolean pr_end_block PARAMS ((PTR, bfd_vma));
279
 
static boolean pr_end_function PARAMS ((PTR));
280
 
static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
281
 
 
282
 
static const struct debug_write_fns pr_fns =
283
 
{
284
 
  pr_start_compilation_unit,
285
 
  pr_start_source,
286
 
  pr_empty_type,
287
 
  pr_void_type,
288
 
  pr_int_type,
289
 
  pr_float_type,
290
 
  pr_complex_type,
291
 
  pr_bool_type,
292
 
  pr_enum_type,
293
 
  pr_pointer_type,
294
 
  pr_function_type,
295
 
  pr_reference_type,
296
 
  pr_range_type,
297
 
  pr_array_type,
298
 
  pr_set_type,
299
 
  pr_offset_type,
300
 
  pr_method_type,
301
 
  pr_const_type,
302
 
  pr_volatile_type,
303
 
  pr_start_struct_type,
304
 
  pr_struct_field,
305
 
  pr_end_struct_type,
306
 
  pr_start_class_type,
307
 
  pr_class_static_member,
308
 
  pr_class_baseclass,
309
 
  pr_class_start_method,
310
 
  pr_class_method_variant,
311
 
  pr_class_static_method_variant,
312
 
  pr_class_end_method,
313
 
  pr_end_class_type,
314
 
  pr_typedef_type,
315
 
  pr_tag_type,
316
 
  pr_typdef,
317
 
  pr_tag,
318
 
  pr_int_constant,
319
 
  pr_float_constant,
320
 
  pr_typed_constant,
321
 
  pr_variable,
322
 
  pr_start_function,
323
 
  pr_function_parameter,
324
 
  pr_start_block,
325
 
  pr_end_block,
326
 
  pr_end_function,
327
 
  pr_lineno
328
 
};
329
 
 
330
 
 
331
 
/* Indent to the current indentation level.  */
332
 
 
333
 
static void
334
 
indent (info)
335
 
     struct pr_handle *info;
336
 
{
337
 
  unsigned int i;
338
 
 
339
 
  for (i = 0; i < info->indent; i++)
340
 
    TRACE_PUTC ((' ', info->f));
341
 
}
342
 
 
343
 
/* Push a type on the type stack.  */
344
 
 
345
 
static boolean
346
 
push_type (info, type)
347
 
     struct pr_handle *info;
348
 
     const char *type;
349
 
{
350
 
  struct pr_stack *n;
351
 
 
352
 
  if (type == NULL)
353
 
    return false;
354
 
 
355
 
  n = (struct pr_stack *) xmalloc (sizeof *n);
356
 
  memset (n, 0, sizeof *n);
357
 
 
358
 
  n->type = xstrdup (type);
359
 
  n->visibility = DEBUG_VISIBILITY_IGNORE;
360
 
  n->method = NULL;
361
 
  n->next = info->stack;
362
 
  info->stack = n;
363
 
 
364
 
  return true;
365
 
}
366
 
 
367
 
/* Prepend a string onto the type on the top of the type stack.  */
368
 
 
369
 
static boolean
370
 
prepend_type (info, s)
371
 
     struct pr_handle *info;
372
 
     const char *s;
373
 
{
374
 
  char *n;
375
 
 
376
 
  assert (info->stack != NULL);
377
 
 
378
 
  n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
379
 
  sprintf (n, "%s%s", s, info->stack->type);
380
 
  free (info->stack->type);
381
 
  info->stack->type = n;
382
 
 
383
 
  return true;
384
 
}
385
 
 
386
 
/* Append a string to the type on the top of the type stack.  */
387
 
 
388
 
static boolean
389
 
append_type (info, s)
390
 
     struct pr_handle *info;
391
 
     const char *s;
392
 
{
393
 
  unsigned int len;
394
 
 
395
 
  if (s == NULL)
396
 
    return false;
397
 
 
398
 
  assert (info->stack != NULL);
399
 
 
400
 
  len = strlen (info->stack->type);
401
 
  info->stack->type = (char *) xrealloc (info->stack->type,
402
 
                                         len + strlen (s) + 1);
403
 
  strcpy (info->stack->type + len, s);
404
 
 
405
 
  return true;
406
 
}
407
 
 
408
 
/* We use an underscore to indicate where the name should go in a type
409
 
   string.  This function substitutes a string for the underscore.  If
410
 
   there is no underscore, the name follows the type.  */
411
 
 
412
 
static boolean
413
 
substitute_type (info, s)
414
 
     struct pr_handle *info;
415
 
     const char *s;
416
 
{
417
 
  char *u;
418
 
 
419
 
  assert (info->stack != NULL);
420
 
 
421
 
  u = strchr (info->stack->type, '|');
422
 
  if (u != NULL)
423
 
    {
424
 
      char *n;
425
 
 
426
 
      n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
427
 
 
428
 
      memcpy (n, info->stack->type, u - info->stack->type);
429
 
      strcpy (n + (u - info->stack->type), s);
430
 
      strcat (n, u + 1);
431
 
 
432
 
      free (info->stack->type);
433
 
      info->stack->type = n;
434
 
 
435
 
      return true;
436
 
    }
437
 
 
438
 
  if (strchr (s, '|') != NULL
439
 
      && (strchr (info->stack->type, '{') != NULL
440
 
          || strchr (info->stack->type, '(') != NULL))
441
 
    {
442
 
      if (! prepend_type (info, "(")
443
 
          || ! append_type (info, ")"))
444
 
        return false;
445
 
    }
446
 
 
447
 
  if (*s == '\0')
448
 
    return true;
449
 
 
450
 
  return (append_type (info, " ")
451
 
          && append_type (info, s));
452
 
}
453
 
 
454
 
/* Indent the type at the top of the stack by appending spaces.  */
455
 
 
456
 
static boolean
457
 
indent_type (info)
458
 
     struct pr_handle *info;
459
 
{
460
 
  unsigned int i;
461
 
 
462
 
  for (i = 0; i < info->indent; i++)
463
 
    {
464
 
      if (! append_type (info, " "))
465
 
        return false;
466
 
    }
467
 
 
468
 
  return true;
469
 
}
470
 
 
471
 
/* Pop a type from the type stack.  */
472
 
 
473
 
static char *
474
 
pop_type (info)
475
 
     struct pr_handle *info;
476
 
{
477
 
  struct pr_stack *o;
478
 
  char *ret;
479
 
 
480
 
  assert (info->stack != NULL);
481
 
 
482
 
  o = info->stack;
483
 
  info->stack = o->next;
484
 
  ret = o->type;
485
 
  free (o);
486
 
 
487
 
  return ret;
488
 
}
489
 
 
490
 
/* Print a VMA value into a string.  */
491
 
 
492
 
static void
493
 
print_vma (vma, buf, unsignedp, hexp)
494
 
     bfd_vma vma;
495
 
     char *buf;
496
 
     boolean unsignedp;
497
 
     boolean hexp;
498
 
{
499
 
  if (sizeof (vma) <= sizeof (unsigned long))
500
 
    {
501
 
      if (hexp)
502
 
        sprintf (buf, "0x%lx", (unsigned long) vma);
503
 
      else if (unsignedp)
504
 
        sprintf (buf, "%lu", (unsigned long) vma);
505
 
      else
506
 
        sprintf (buf, "%ld", (long) vma);
507
 
    }
508
 
  else
509
 
    {
510
 
      buf[0] = '0';
511
 
      buf[1] = 'x';
512
 
      sprintf_vma (buf + 2, vma);
513
 
    }
514
 
}
515
 
 
516
 
/* Start a new compilation unit.  */
517
 
 
518
 
static boolean
519
 
pr_start_compilation_unit (p, filename)
520
 
     PTR p;
521
 
     const char *filename;
522
 
{
523
 
  struct pr_handle *info = (struct pr_handle *) p;
524
 
 
525
 
  assert (info->indent == 0);
526
 
/*
527
 
  TRACE_FPRINTF( (info->f, "%s:\n", filename));
528
 
*/
529
 
  return true;
530
 
}
531
 
 
532
 
/* Start a source file within a compilation unit.  */
533
 
 
534
 
static boolean
535
 
pr_start_source (p, filename)
536
 
     PTR p;
537
 
     const char *filename;
538
 
{
539
 
  struct pr_handle *info = (struct pr_handle *) p;
540
 
 
541
 
  assert (info->indent == 0);
542
 
/*
543
 
  TRACE_FPRINTF( (info->f, " %s:\n", filename));
544
 
*/
545
 
  return true;
546
 
}
547
 
 
548
 
/* Push an empty type onto the type stack.  */
549
 
 
550
 
static boolean
551
 
pr_empty_type (p)
552
 
     PTR p;
553
 
{
554
 
  struct pr_handle *info = (struct pr_handle *) p;
555
 
 
556
 
  return push_type (info, "<undefined>");
557
 
}
558
 
 
559
 
/* Push a void type onto the type stack.  */
560
 
 
561
 
static boolean
562
 
pr_void_type (p)
563
 
     PTR p;
564
 
{
565
 
  struct pr_handle *info = (struct pr_handle *) p;
566
 
 
567
 
  return push_type (info, "void");
568
 
}
569
 
 
570
 
/* Push an integer type onto the type stack.  */
571
 
 
572
 
static boolean
573
 
pr_int_type (p, size, unsignedp)
574
 
     PTR p;
575
 
     unsigned int size;
576
 
     boolean unsignedp;
577
 
{
578
 
  struct pr_handle *info = (struct pr_handle *) p;
579
 
  char ab[10];
580
 
 
581
 
  sprintf (ab, "%sint%d", unsignedp ? "u" : "", size * 8);
582
 
  return push_type (info, ab);
583
 
}
584
 
 
585
 
/* Push a floating type onto the type stack.  */
586
 
 
587
 
static boolean
588
 
pr_float_type (p, size)
589
 
     PTR p;
590
 
     unsigned int size;
591
 
{
592
 
  struct pr_handle *info = (struct pr_handle *) p;
593
 
  char ab[10];
594
 
 
595
 
  if (size == 4)
596
 
    return push_type (info, "float");
597
 
  else if (size == 8)
598
 
    return push_type (info, "double");
599
 
 
600
 
  sprintf (ab, "float%d", size * 8);
601
 
  return push_type (info, ab);
602
 
}
603
 
 
604
 
/* Push a complex type onto the type stack.  */
605
 
 
606
 
static boolean
607
 
pr_complex_type (p, size)
608
 
     PTR p;
609
 
     unsigned int size;
610
 
{
611
 
  struct pr_handle *info = (struct pr_handle *) p;
612
 
 
613
 
  if (! pr_float_type (p, size))
614
 
    return false;
615
 
 
616
 
  return prepend_type (info, "complex ");
617
 
}
618
 
 
619
 
/* Push a boolean type onto the type stack.  */
620
 
 
621
 
static boolean
622
 
pr_bool_type (p, size)
623
 
     PTR p;
624
 
     unsigned int size;
625
 
{
626
 
  struct pr_handle *info = (struct pr_handle *) p;
627
 
  char ab[10];
628
 
 
629
 
  sprintf (ab, "bool%d", size * 8);
630
 
 
631
 
  return push_type (info, ab);
632
 
}
633
 
 
634
 
/* Push an enum type onto the type stack.  */
635
 
 
636
 
static boolean
637
 
pr_enum_type (p, tag, names, values)
638
 
     PTR p;
639
 
     const char *tag;
640
 
     const char **names;
641
 
     bfd_signed_vma *values;
642
 
{
643
 
  struct pr_handle *info = (struct pr_handle *) p;
644
 
  unsigned int i;
645
 
  bfd_signed_vma val;
646
 
 
647
 
  if (! push_type (info, "enum "))
648
 
    return false;
649
 
  if (tag != NULL)
650
 
    {
651
 
      if (! append_type (info, tag)
652
 
          || ! append_type (info, " "))
653
 
        return false;
654
 
    }
655
 
  if (! append_type (info, "{ "))
656
 
    return false;
657
 
 
658
 
  if (names == NULL)
659
 
    {
660
 
      if (! append_type (info, "/* undefined */"))
661
 
        return false;
662
 
    }
663
 
  else
664
 
    {
665
 
      val = 0;
666
 
      for (i = 0; names[i] != NULL; i++)
667
 
        {
668
 
          if (i > 0)
669
 
            {
670
 
              if (! append_type (info, ", "))
671
 
                return false;
672
 
            }
673
 
 
674
 
          if (! append_type (info, names[i]))
675
 
            return false;
676
 
 
677
 
          if (values[i] != val)
678
 
            {
679
 
              char ab[20];
680
 
 
681
 
              print_vma (values[i], ab, false, false);
682
 
              if (! append_type (info, " = ")
683
 
                  || ! append_type (info, ab))
684
 
                return false;
685
 
              val = values[i];
686
 
            }
687
 
 
688
 
          ++val;
689
 
        }
690
 
    }
691
 
 
692
 
  return append_type (info, " }");
693
 
}
694
 
 
695
 
/* Turn the top type on the stack into a pointer.  */
696
 
 
697
 
static boolean
698
 
pr_pointer_type (p)
699
 
     PTR p;
700
 
{
701
 
  struct pr_handle *info = (struct pr_handle *) p;
702
 
  char *s;
703
 
 
704
 
  assert (info->stack != NULL);
705
 
 
706
 
  s = strchr (info->stack->type, '|');
707
 
  if (s != NULL && s[1] == '[')
708
 
    return substitute_type (info, "(*|)");
709
 
  return substitute_type (info, "*|");
710
 
}
711
 
 
712
 
/* Turn the top type on the stack into a function returning that type.  */
713
 
 
714
 
static boolean
715
 
pr_function_type (p, argcount, varargs)
716
 
     PTR p;
717
 
     int argcount;
718
 
     boolean varargs;
719
 
{
720
 
  struct pr_handle *info = (struct pr_handle *) p;
721
 
  char **arg_types;
722
 
  unsigned int len;
723
 
  char *s;
724
 
 
725
 
  assert (info->stack != NULL);
726
 
 
727
 
  len = 10;
728
 
 
729
 
  if (argcount <= 0)
730
 
    {
731
 
      arg_types = NULL;
732
 
      len += 15;
733
 
    }
734
 
  else
735
 
    {
736
 
      int i;
737
 
 
738
 
      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
739
 
      for (i = argcount - 1; i >= 0; i--)
740
 
        {
741
 
          if (! substitute_type (info, ""))
742
 
            return false;
743
 
          arg_types[i] = pop_type (info);
744
 
          if (arg_types[i] == NULL)
745
 
            return false;
746
 
          len += strlen (arg_types[i]) + 2;
747
 
        }
748
 
      if (varargs)
749
 
        len += 5;
750
 
    }
751
 
 
752
 
  /* Now the return type is on the top of the stack.  */
753
 
 
754
 
  s = (char *) xmalloc (len);
755
 
  strcpy (s, "(|) (");
756
 
 
757
 
  if (argcount < 0)
758
 
    {
759
 
#if 0
760
 
      /* Turn off unknown arguments. */
761
 
      strcat (s, "/* unknown */");
762
 
#endif
763
 
    }
764
 
  else
765
 
    {
766
 
      int i;
767
 
 
768
 
      for (i = 0; i < argcount; i++)
769
 
        {
770
 
          if (i > 0)
771
 
            strcat (s, ", ");
772
 
          strcat (s, arg_types[i]);
773
 
        }
774
 
      if (varargs)
775
 
        {
776
 
          if (i > 0)
777
 
            strcat (s, ", ");
778
 
          strcat (s, "...");
779
 
        }
780
 
      if (argcount > 0)
781
 
        free (arg_types);
782
 
    }
783
 
 
784
 
  strcat (s, ")");
785
 
 
786
 
  if (! substitute_type (info, s))
787
 
    return false;
788
 
 
789
 
  free (s);
790
 
 
791
 
  return true;
792
 
}
793
 
 
794
 
/* Turn the top type on the stack into a reference to that type.  */
795
 
 
796
 
static boolean
797
 
pr_reference_type (p)
798
 
     PTR p;
799
 
{
800
 
  struct pr_handle *info = (struct pr_handle *) p;
801
 
 
802
 
  assert (info->stack != NULL);
803
 
 
804
 
  return substitute_type (info, "&|");
805
 
}
806
 
 
807
 
/* Make a range type.  */
808
 
 
809
 
static boolean
810
 
pr_range_type (p, lower, upper)
811
 
     PTR p;
812
 
     bfd_signed_vma lower;
813
 
     bfd_signed_vma upper;
814
 
{
815
 
  struct pr_handle *info = (struct pr_handle *) p;
816
 
  char abl[20], abu[20];
817
 
 
818
 
  assert (info->stack != NULL);
819
 
 
820
 
  if (! substitute_type (info, ""))
821
 
    return false;
822
 
 
823
 
  print_vma (lower, abl, false, false);
824
 
  print_vma (upper, abu, false, false);
825
 
 
826
 
  return (prepend_type (info, "range (")
827
 
          && append_type (info, "):")
828
 
          && append_type (info, abl)
829
 
          && append_type (info, ":")
830
 
          && append_type (info, abu));
831
 
}
832
 
 
833
 
/* Make an array type.  */
834
 
 
835
 
/*ARGSUSED*/
836
 
static boolean
837
 
pr_array_type (p, lower, upper, stringp)
838
 
     PTR p;
839
 
     bfd_signed_vma lower;
840
 
     bfd_signed_vma upper;
841
 
     boolean stringp;
842
 
{
843
 
  struct pr_handle *info = (struct pr_handle *) p;
844
 
  char *range_type;
845
 
  char abl[20], abu[20], ab[50];
846
 
 
847
 
  range_type = pop_type (info);
848
 
  if (range_type == NULL)
849
 
    return false;
850
 
 
851
 
  if (lower == 0)
852
 
    {
853
 
      if (upper == -1)
854
 
        sprintf (ab, "|[]");
855
 
      else
856
 
        {
857
 
          print_vma (upper + 1, abu, false, false);
858
 
          sprintf (ab, "|[%s]", abu);
859
 
        }
860
 
    }
861
 
  else
862
 
    {
863
 
      print_vma (lower, abl, false, false);
864
 
      print_vma (upper, abu, false, false);
865
 
      sprintf (ab, "|[%s:%s]", abl, abu);
866
 
    }
867
 
 
868
 
  if (! substitute_type (info, ab))
869
 
    return false;
870
 
 
871
 
  if (strcmp (range_type, "int") != 0)
872
 
    {
873
 
      if (! append_type (info, ":")
874
 
          || ! append_type (info, range_type))
875
 
        return false;
876
 
    }
877
 
 
878
 
  if (stringp)
879
 
    {
880
 
      if (! append_type (info, " /* string */"))
881
 
        return false;
882
 
    }
883
 
 
884
 
  return true;
885
 
}
886
 
 
887
 
/* Make a set type.  */
888
 
 
889
 
/*ARGSUSED*/
890
 
static boolean
891
 
pr_set_type (p, bitstringp)
892
 
     PTR p;
893
 
     boolean bitstringp;
894
 
{
895
 
  struct pr_handle *info = (struct pr_handle *) p;
896
 
 
897
 
  if (! substitute_type (info, ""))
898
 
    return false;
899
 
 
900
 
  if (! prepend_type (info, "set { ")
901
 
      || ! append_type (info, " }"))
902
 
    return false;
903
 
 
904
 
  if (bitstringp)
905
 
    {
906
 
      if (! append_type (info, "/* bitstring */"))
907
 
        return false;
908
 
    }
909
 
 
910
 
  return true;
911
 
}
912
 
 
913
 
/* Make an offset type.  */
914
 
 
915
 
static boolean
916
 
pr_offset_type (p)
917
 
     PTR p;
918
 
{
919
 
  struct pr_handle *info = (struct pr_handle *) p;
920
 
  char *t;
921
 
 
922
 
  if (! substitute_type (info, ""))
923
 
    return false;
924
 
 
925
 
  t = pop_type (info);
926
 
  if (t == NULL)
927
 
    return false;
928
 
 
929
 
  return (substitute_type (info, "")
930
 
          && prepend_type (info, " ")
931
 
          && prepend_type (info, t)
932
 
          && append_type (info, "::|"));
933
 
}
934
 
 
935
 
/* Make a method type.  */
936
 
 
937
 
static boolean
938
 
pr_method_type (p, domain, argcount, varargs)
939
 
     PTR p;
940
 
     boolean domain;
941
 
     int argcount;
942
 
     boolean varargs;
943
 
{
944
 
  struct pr_handle *info = (struct pr_handle *) p;
945
 
  unsigned int len;
946
 
  char *domain_type;
947
 
  char **arg_types;
948
 
  char *s;
949
 
 
950
 
  len = 10;
951
 
 
952
 
  if (! domain)
953
 
    domain_type = NULL;
954
 
  else
955
 
    {
956
 
      if (! substitute_type (info, ""))
957
 
        return false;
958
 
      domain_type = pop_type (info);
959
 
      if (domain_type == NULL)
960
 
        return false;
961
 
      if (strncmp (domain_type, "class ", sizeof "class " - 1) == 0
962
 
          && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
963
 
        domain_type += sizeof "class " - 1;
964
 
      else if (strncmp (domain_type, "union class ",
965
 
                        sizeof "union class ") == 0
966
 
               && (strchr (domain_type + sizeof "union class " - 1, ' ')
967
 
                   == NULL))
968
 
        domain_type += sizeof "union class " - 1;
969
 
      len += strlen (domain_type);
970
 
    }
971
 
 
972
 
  if (argcount <= 0)
973
 
    {
974
 
      arg_types = NULL;
975
 
      len += 15;
976
 
    }
977
 
  else
978
 
    {
979
 
      int i;
980
 
 
981
 
      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
982
 
      for (i = argcount - 1; i >= 0; i--)
983
 
        {
984
 
          if (! substitute_type (info, ""))
985
 
            return false;
986
 
          arg_types[i] = pop_type (info);
987
 
          if (arg_types[i] == NULL)
988
 
            return false;
989
 
          len += strlen (arg_types[i]) + 2;
990
 
        }
991
 
      if (varargs)
992
 
        len += 5;
993
 
    }
994
 
 
995
 
  /* Now the return type is on the top of the stack.  */
996
 
 
997
 
  s = (char *) xmalloc (len);
998
 
  if (! domain)
999
 
    *s = '\0';
1000
 
  else
1001
 
    strcpy (s, domain_type);
1002
 
  strcat (s, "::| (");
1003
 
 
1004
 
  if (argcount < 0)
1005
 
    strcat (s, "/* unknown */");
1006
 
  else
1007
 
    {
1008
 
      int i;
1009
 
 
1010
 
      for (i = 0; i < argcount; i++)
1011
 
        {
1012
 
          if (i > 0)
1013
 
            strcat (s, ", ");
1014
 
          strcat (s, arg_types[i]);
1015
 
        }
1016
 
      if (varargs)
1017
 
        {
1018
 
          if (i > 0)
1019
 
            strcat (s, ", ");
1020
 
          strcat (s, "...");
1021
 
        }
1022
 
      if (argcount > 0)
1023
 
        free (arg_types);
1024
 
    }
1025
 
 
1026
 
  strcat (s, ")");
1027
 
 
1028
 
  if (! substitute_type (info, s))
1029
 
    return false;
1030
 
 
1031
 
  free (s);
1032
 
 
1033
 
  return true;
1034
 
}
1035
 
 
1036
 
/* Make a const qualified type.  */
1037
 
 
1038
 
static boolean
1039
 
pr_const_type (p)
1040
 
     PTR p;
1041
 
{
1042
 
  struct pr_handle *info = (struct pr_handle *) p;
1043
 
 
1044
 
  return substitute_type (info, "const |");
1045
 
}
1046
 
 
1047
 
/* Make a volatile qualified type.  */
1048
 
 
1049
 
static boolean
1050
 
pr_volatile_type (p)
1051
 
     PTR p;
1052
 
{
1053
 
  struct pr_handle *info = (struct pr_handle *) p;
1054
 
 
1055
 
  return substitute_type (info, "volatile |");
1056
 
}
1057
 
 
1058
 
/* Start accumulating a struct type.  */
1059
 
 
1060
 
static boolean
1061
 
pr_start_struct_type (p, tag, id, structp, size)
1062
 
     PTR p;
1063
 
     const char *tag;
1064
 
     unsigned int id;
1065
 
     boolean structp;
1066
 
     unsigned int size;
1067
 
{
1068
 
  struct pr_handle *info = (struct pr_handle *) p;
1069
 
 
1070
 
  info->indent += 2;
1071
 
 
1072
 
  if (! push_type (info, structp ? "struct " : "union "))
1073
 
    return false;
1074
 
  if (tag != NULL)
1075
 
    {
1076
 
      if (! append_type (info, tag))
1077
 
        return false;
1078
 
    }
1079
 
  else
1080
 
    {
1081
 
      char idbuf[20];
1082
 
 
1083
 
      sprintf (idbuf, "%%anon%u", id);
1084
 
      if (! append_type (info, idbuf))
1085
 
        return false;
1086
 
    }
1087
 
 
1088
 
  if (! append_type (info, " {"))
1089
 
    return false;
1090
 
  if (size != 0 || tag != NULL)
1091
 
    {
1092
 
      char ab[30];
1093
 
 
1094
 
      if (! append_type (info, " /*"))
1095
 
        return false;
1096
 
 
1097
 
      if (size != 0)
1098
 
        {
1099
 
          sprintf (ab, " size %u", size);
1100
 
          if (! append_type (info, ab))
1101
 
            return false;
1102
 
        }
1103
 
      if (tag != NULL)
1104
 
        {
1105
 
          sprintf (ab, " id %u", id);
1106
 
          if (! append_type (info, ab))
1107
 
            return false;
1108
 
        }
1109
 
      if (! append_type (info, " */"))
1110
 
        return false;
1111
 
    }
1112
 
  if (! append_type (info, "\n"))
1113
 
    return false;
1114
 
 
1115
 
  info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
1116
 
 
1117
 
  return indent_type (info);
1118
 
}
1119
 
 
1120
 
/* Output the visibility of a field in a struct.  */
1121
 
 
1122
 
static boolean
1123
 
pr_fix_visibility (info, visibility)
1124
 
     struct pr_handle *info;
1125
 
     enum debug_visibility visibility;
1126
 
{
1127
 
  const char *s;
1128
 
  char *t;
1129
 
  unsigned int len;
1130
 
 
1131
 
  assert (info->stack != NULL);
1132
 
 
1133
 
  if (info->stack->visibility == visibility)
1134
 
    return true;
1135
 
 
1136
 
  assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
1137
 
 
1138
 
  switch (visibility)
1139
 
    {
1140
 
    case DEBUG_VISIBILITY_PUBLIC:
1141
 
      s = "public";
1142
 
      break;
1143
 
    case DEBUG_VISIBILITY_PRIVATE:
1144
 
      s = "private";
1145
 
      break;
1146
 
    case DEBUG_VISIBILITY_PROTECTED:
1147
 
      s = "protected";
1148
 
      break;
1149
 
    case DEBUG_VISIBILITY_IGNORE:
1150
 
      s = "/* ignore */";
1151
 
      break;
1152
 
    default:
1153
 
      abort ();
1154
 
      return false;
1155
 
    }
1156
 
 
1157
 
  /* Trim off a trailing space in the struct string, to make the
1158
 
     output look a bit better, then stick on the visibility string.  */
1159
 
 
1160
 
  t = info->stack->type;
1161
 
  len = strlen (t);
1162
 
  assert (t[len - 1] == ' ');
1163
 
  t[len - 1] = '\0';
1164
 
 
1165
 
  if (! append_type (info, s)
1166
 
      || ! append_type (info, ":\n")
1167
 
      || ! indent_type (info))
1168
 
    return false;
1169
 
 
1170
 
  info->stack->visibility = visibility;
1171
 
 
1172
 
  return true;
1173
 
}
1174
 
 
1175
 
/* Add a field to a struct type.  */
1176
 
 
1177
 
static boolean
1178
 
pr_struct_field (p, name, bitpos, bitsize, visibility)
1179
 
     PTR p;
1180
 
     const char *name;
1181
 
     bfd_vma bitpos;
1182
 
     bfd_vma bitsize;
1183
 
     enum debug_visibility visibility;
1184
 
{
1185
 
  struct pr_handle *info = (struct pr_handle *) p;
1186
 
  char ab[20];
1187
 
  char *t;
1188
 
 
1189
 
  if (! substitute_type (info, name))
1190
 
    return false;
1191
 
 
1192
 
  if (! append_type (info, "; /* "))
1193
 
    return false;
1194
 
 
1195
 
  if (bitsize != 0)
1196
 
    {
1197
 
      print_vma (bitsize, ab, true, false);
1198
 
      if (! append_type (info, "bitsize ")
1199
 
          || ! append_type (info, ab)
1200
 
          || ! append_type (info, ", "))
1201
 
        return false;
1202
 
    }
1203
 
 
1204
 
  print_vma (bitpos, ab, true, false);
1205
 
  if (! append_type (info, "bitpos ")
1206
 
      || ! append_type (info, ab)
1207
 
      || ! append_type (info, " */\n")
1208
 
      || ! indent_type (info))
1209
 
    return false;
1210
 
 
1211
 
  t = pop_type (info);
1212
 
  if (t == NULL)
1213
 
    return false;
1214
 
 
1215
 
  if (! pr_fix_visibility (info, visibility))
1216
 
    return false;
1217
 
 
1218
 
  return append_type (info, t);
1219
 
}
1220
 
 
1221
 
/* Finish a struct type.  */
1222
 
 
1223
 
static boolean
1224
 
pr_end_struct_type (p)
1225
 
     PTR p;
1226
 
{
1227
 
  struct pr_handle *info = (struct pr_handle *) p;
1228
 
  char *s;
1229
 
 
1230
 
  assert (info->stack != NULL);
1231
 
  assert (info->indent >= 2);
1232
 
 
1233
 
  info->indent -= 2;
1234
 
 
1235
 
  /* Change the trailing indentation to have a close brace.  */
1236
 
  s = info->stack->type + strlen (info->stack->type) - 2;
1237
 
  assert (s[0] == ' ' && s[1] == ' ' && s[2] == '\0');
1238
 
 
1239
 
  *s++ = '}';
1240
 
  *s = '\0';
1241
 
 
1242
 
  return true;
1243
 
}
1244
 
 
1245
 
/* Start a class type.  */
1246
 
 
1247
 
static boolean
1248
 
pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
1249
 
     PTR p;
1250
 
     const char *tag;
1251
 
     unsigned int id;
1252
 
     boolean structp;
1253
 
     unsigned int size;
1254
 
     boolean vptr;
1255
 
     boolean ownvptr;
1256
 
{
1257
 
  struct pr_handle *info = (struct pr_handle *) p;
1258
 
  char *tv = NULL;
1259
 
 
1260
 
  info->indent += 2;
1261
 
 
1262
 
  if (vptr && ! ownvptr)
1263
 
    {
1264
 
      tv = pop_type (info);
1265
 
      if (tv == NULL)
1266
 
        return false;
1267
 
    }
1268
 
 
1269
 
  if (! push_type (info, structp ? "class " : "union class "))
1270
 
    return false;
1271
 
  if (tag != NULL)
1272
 
    {
1273
 
      if (! append_type (info, tag))
1274
 
        return false;
1275
 
    }
1276
 
  else
1277
 
    {
1278
 
      char idbuf[20];
1279
 
 
1280
 
      sprintf (idbuf, "%%anon%u", id);
1281
 
      if (! append_type (info, idbuf))
1282
 
        return false;
1283
 
    }
1284
 
 
1285
 
  if (! append_type (info, " {"))
1286
 
    return false;
1287
 
  if (size != 0 || vptr || ownvptr || tag != NULL)
1288
 
    {
1289
 
      if (! append_type (info, " /*"))
1290
 
        return false;
1291
 
 
1292
 
      if (size != 0)
1293
 
        {
1294
 
          char ab[20];
1295
 
 
1296
 
          sprintf (ab, "%u", size);
1297
 
          if (! append_type (info, " size ")
1298
 
              || ! append_type (info, ab))
1299
 
            return false;
1300
 
        }
1301
 
 
1302
 
      if (vptr)
1303
 
        {
1304
 
          if (! append_type (info, " vtable "))
1305
 
            return false;
1306
 
          if (ownvptr)
1307
 
            {
1308
 
              if (! append_type (info, "self "))
1309
 
                return false;
1310
 
            }
1311
 
          else
1312
 
            {
1313
 
              if (! append_type (info, tv)
1314
 
                  || ! append_type (info, " "))
1315
 
                return false;
1316
 
            }
1317
 
        }
1318
 
 
1319
 
      if (tag != NULL)
1320
 
        {
1321
 
          char ab[30];
1322
 
 
1323
 
          sprintf (ab, " id %u", id);
1324
 
          if (! append_type (info, ab))
1325
 
            return false;
1326
 
        }
1327
 
 
1328
 
      if (! append_type (info, " */"))
1329
 
        return false;
1330
 
    }
1331
 
 
1332
 
  info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
1333
 
 
1334
 
  return (append_type (info, "\n")
1335
 
          && indent_type (info));
1336
 
}
1337
 
 
1338
 
/* Add a static member to a class.  */
1339
 
 
1340
 
static boolean
1341
 
pr_class_static_member (p, name, physname, visibility)
1342
 
     PTR p;
1343
 
     const char *name;
1344
 
     const char *physname;
1345
 
     enum debug_visibility visibility;
1346
 
{
1347
 
  struct pr_handle *info = (struct pr_handle *) p;
1348
 
  char *t;
1349
 
 
1350
 
  if (! substitute_type (info, name))
1351
 
    return false;
1352
 
 
1353
 
  if (! prepend_type (info, "static ")
1354
 
      || ! append_type (info, "; /* ")
1355
 
      || ! append_type (info, physname)
1356
 
      || ! append_type (info, " */\n")
1357
 
      || ! indent_type (info))
1358
 
    return false;
1359
 
 
1360
 
  t = pop_type (info);
1361
 
  if (t == NULL)
1362
 
    return false;
1363
 
 
1364
 
  if (! pr_fix_visibility (info, visibility))
1365
 
    return false;
1366
 
 
1367
 
  return append_type (info, t);
1368
 
}
1369
 
 
1370
 
/* Add a base class to a class.  */
1371
 
 
1372
 
static boolean
1373
 
pr_class_baseclass (p, bitpos, virtual, visibility)
1374
 
     PTR p;
1375
 
     bfd_vma bitpos;
1376
 
     boolean virtual;
1377
 
     enum debug_visibility visibility;
1378
 
{
1379
 
  struct pr_handle *info = (struct pr_handle *) p;
1380
 
  char *t;
1381
 
  const char *prefix;
1382
 
  char ab[20];
1383
 
  char *s, *l, *n;
1384
 
 
1385
 
  assert (info->stack != NULL && info->stack->next != NULL);
1386
 
 
1387
 
  if (! substitute_type (info, ""))
1388
 
    return false;
1389
 
 
1390
 
  t = pop_type (info);
1391
 
  if (t == NULL)
1392
 
    return false;
1393
 
 
1394
 
  if (strncmp (t, "class ", sizeof "class " - 1) == 0)
1395
 
    t += sizeof "class " - 1;
1396
 
 
1397
 
  /* Push it back on to take advantage of the prepend_type and
1398
 
     append_type routines.  */
1399
 
  if (! push_type (info, t))
1400
 
    return false;
1401
 
 
1402
 
  if (virtual)
1403
 
    {
1404
 
      if (! prepend_type (info, "virtual "))
1405
 
        return false;
1406
 
    }
1407
 
 
1408
 
  switch (visibility)
1409
 
    {
1410
 
    case DEBUG_VISIBILITY_PUBLIC:
1411
 
      prefix = "public ";
1412
 
      break;
1413
 
    case DEBUG_VISIBILITY_PROTECTED:
1414
 
      prefix = "protected ";
1415
 
      break;
1416
 
    case DEBUG_VISIBILITY_PRIVATE:
1417
 
      prefix = "private ";
1418
 
      break;
1419
 
    default:
1420
 
      prefix = "/* unknown visibility */ ";
1421
 
      break;
1422
 
    }
1423
 
 
1424
 
  if (! prepend_type (info, prefix))
1425
 
    return false;
1426
 
 
1427
 
  if (bitpos != 0)
1428
 
    {
1429
 
      print_vma (bitpos, ab, true, false);
1430
 
      if (! append_type (info, " /* bitpos ")
1431
 
          || ! append_type (info, ab)
1432
 
          || ! append_type (info, " */"))
1433
 
        return false;
1434
 
    }
1435
 
 
1436
 
  /* Now the top of the stack is something like "public A / * bitpos
1437
 
     10 * /".  The next element on the stack is something like "class
1438
 
     xx { / * size 8 * /\n...".  We want to substitute the top of the
1439
 
     stack in before the {.  */
1440
 
  s = strchr (info->stack->next->type, '{');
1441
 
  assert (s != NULL);
1442
 
  --s;
1443
 
 
1444
 
  /* If there is already a ':', then we already have a baseclass, and
1445
 
     we must append this one after a comma.  */
1446
 
  for (l = info->stack->next->type; l != s; l++)
1447
 
    if (*l == ':')
1448
 
      break;
1449
 
  if (! prepend_type (info, l == s ? " : " : ", "))
1450
 
    return false;
1451
 
 
1452
 
  t = pop_type (info);
1453
 
  if (t == NULL)
1454
 
    return false;
1455
 
 
1456
 
  n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
1457
 
  memcpy (n, info->stack->type, s - info->stack->type);
1458
 
  strcpy (n + (s - info->stack->type), t);
1459
 
  strcat (n, s);
1460
 
 
1461
 
  free (info->stack->type);
1462
 
  info->stack->type = n;
1463
 
 
1464
 
  free (t);
1465
 
 
1466
 
  return true;
1467
 
}
1468
 
 
1469
 
/* Start adding a method to a class.  */
1470
 
 
1471
 
static boolean
1472
 
pr_class_start_method (p, name)
1473
 
     PTR p;
1474
 
     const char *name;
1475
 
{
1476
 
  struct pr_handle *info = (struct pr_handle *) p;
1477
 
 
1478
 
  assert (info->stack != NULL);
1479
 
  info->stack->method = name;
1480
 
  return true;
1481
 
}
1482
 
 
1483
 
/* Add a variant to a method.  */
1484
 
 
1485
 
static boolean
1486
 
pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset,
1487
 
                         context)
1488
 
     PTR p;
1489
 
     const char *physname;
1490
 
     enum debug_visibility visibility;
1491
 
     boolean constp;
1492
 
     boolean volatilep;
1493
 
     bfd_vma voffset;
1494
 
     boolean context;
1495
 
{
1496
 
  struct pr_handle *info = (struct pr_handle *) p;
1497
 
  char *method_type;
1498
 
  char *context_type;
1499
 
 
1500
 
  assert (info->stack != NULL);
1501
 
  assert (info->stack->next != NULL);
1502
 
 
1503
 
  /* Put the const and volatile qualifiers on the type.  */
1504
 
  if (volatilep)
1505
 
    {
1506
 
      if (! append_type (info, " volatile"))
1507
 
        return false;
1508
 
    }
1509
 
  if (constp)
1510
 
    {
1511
 
      if (! append_type (info, " const"))
1512
 
        return false;
1513
 
    }
1514
 
 
1515
 
  /* Stick the name of the method into its type.  */
1516
 
  if (! substitute_type (info,
1517
 
                         (context
1518
 
                          ? info->stack->next->next->method
1519
 
                          : info->stack->next->method)))
1520
 
    return false;
1521
 
 
1522
 
  /* Get the type.  */
1523
 
  method_type = pop_type (info);
1524
 
  if (method_type == NULL)
1525
 
    return false;
1526
 
 
1527
 
  /* Pull off the context type if there is one.  */
1528
 
  if (! context)
1529
 
    context_type = NULL;
1530
 
  else
1531
 
    {
1532
 
      context_type = pop_type (info);
1533
 
      if (context_type == NULL)
1534
 
        return false;
1535
 
    }
1536
 
 
1537
 
  /* Now the top of the stack is the class.  */
1538
 
 
1539
 
  if (! pr_fix_visibility (info, visibility))
1540
 
    return false;
1541
 
 
1542
 
  if (! append_type (info, method_type)
1543
 
      || ! append_type (info, " /* ")
1544
 
      || ! append_type (info, physname)
1545
 
      || ! append_type (info, " "))
1546
 
    return false;
1547
 
  if (context || voffset != 0)
1548
 
    {
1549
 
      char ab[20];
1550
 
 
1551
 
      if (context)
1552
 
        {
1553
 
          if (! append_type (info, "context ")
1554
 
              || ! append_type (info, context_type)
1555
 
              || ! append_type (info, " "))
1556
 
            return false;
1557
 
        }
1558
 
      print_vma (voffset, ab, true, false);
1559
 
      if (! append_type (info, "voffset ")
1560
 
          || ! append_type (info, ab))
1561
 
        return false;
1562
 
    }
1563
 
 
1564
 
  return (append_type (info, " */;\n")
1565
 
          && indent_type (info));
1566
 
}
1567
 
 
1568
 
/* Add a static variant to a method.  */
1569
 
 
1570
 
static boolean
1571
 
pr_class_static_method_variant (p, physname, visibility, constp, volatilep)
1572
 
     PTR p;
1573
 
     const char *physname;
1574
 
     enum debug_visibility visibility;
1575
 
     boolean constp;
1576
 
     boolean volatilep;
1577
 
{
1578
 
  struct pr_handle *info = (struct pr_handle *) p;
1579
 
  char *method_type;
1580
 
 
1581
 
  assert (info->stack != NULL);
1582
 
  assert (info->stack->next != NULL);
1583
 
  assert (info->stack->next->method != NULL);
1584
 
 
1585
 
  /* Put the const and volatile qualifiers on the type.  */
1586
 
  if (volatilep)
1587
 
    {
1588
 
      if (! append_type (info, " volatile"))
1589
 
        return false;
1590
 
    }
1591
 
  if (constp)
1592
 
    {
1593
 
      if (! append_type (info, " const"))
1594
 
        return false;
1595
 
    }
1596
 
 
1597
 
  /* Mark it as static.  */
1598
 
  if (! prepend_type (info, "static "))
1599
 
    return false;
1600
 
 
1601
 
  /* Stick the name of the method into its type.  */
1602
 
  if (! substitute_type (info, info->stack->next->method))
1603
 
    return false;
1604
 
 
1605
 
  /* Get the type.  */
1606
 
  method_type = pop_type (info);
1607
 
  if (method_type == NULL)
1608
 
    return false;
1609
 
 
1610
 
  /* Now the top of the stack is the class.  */
1611
 
 
1612
 
  if (! pr_fix_visibility (info, visibility))
1613
 
    return false;
1614
 
 
1615
 
  return (append_type (info, method_type)
1616
 
          && append_type (info, " /* ")
1617
 
          && append_type (info, physname)
1618
 
          && append_type (info, " */;\n")
1619
 
          && indent_type (info));
1620
 
}
1621
 
 
1622
 
/* Finish up a method.  */
1623
 
 
1624
 
static boolean
1625
 
pr_class_end_method (p)
1626
 
     PTR p;
1627
 
{
1628
 
  struct pr_handle *info = (struct pr_handle *) p;
1629
 
 
1630
 
  info->stack->method = NULL;
1631
 
  return true;
1632
 
}
1633
 
 
1634
 
/* Finish up a class.  */
1635
 
 
1636
 
static boolean
1637
 
pr_end_class_type (p)
1638
 
     PTR p;
1639
 
{
1640
 
  return pr_end_struct_type (p);
1641
 
}
1642
 
 
1643
 
/* Push a type on the stack using a typedef name.  */
1644
 
 
1645
 
static boolean
1646
 
pr_typedef_type (p, name)
1647
 
     PTR p;
1648
 
     const char *name;
1649
 
{
1650
 
  struct pr_handle *info = (struct pr_handle *) p;
1651
 
 
1652
 
  return push_type (info, name);
1653
 
}
1654
 
 
1655
 
/* Push a type on the stack using a tag name.  */
1656
 
 
1657
 
static boolean
1658
 
pr_tag_type (p, name, id, kind)
1659
 
     PTR p;
1660
 
     const char *name;
1661
 
     unsigned int id;
1662
 
     enum debug_type_kind kind;
1663
 
{
1664
 
  struct pr_handle *info = (struct pr_handle *) p;
1665
 
  const char *t, *tag;
1666
 
  char idbuf[30];
1667
 
 
1668
 
  switch (kind)
1669
 
    {
1670
 
    case DEBUG_KIND_STRUCT:
1671
 
      t = "struct ";
1672
 
      break;
1673
 
    case DEBUG_KIND_UNION:
1674
 
      t = "union ";
1675
 
      break;
1676
 
    case DEBUG_KIND_ENUM:
1677
 
      t = "enum ";
1678
 
      break;
1679
 
    case DEBUG_KIND_CLASS:
1680
 
      t = "class ";
1681
 
      break;
1682
 
    case DEBUG_KIND_UNION_CLASS:
1683
 
      t = "union class ";
1684
 
      break;
1685
 
    default:
1686
 
      abort ();
1687
 
      return false;
1688
 
    }
1689
 
 
1690
 
  if (! push_type (info, t))
1691
 
    return false;
1692
 
  if (name != NULL)
1693
 
    tag = name;
1694
 
  else
1695
 
    {
1696
 
      sprintf (idbuf, "%%anon%u", id);
1697
 
      tag = idbuf;
1698
 
    }
1699
 
 
1700
 
  if (! append_type (info, tag))
1701
 
    return false;
1702
 
  if (name != NULL && kind != DEBUG_KIND_ENUM)
1703
 
    {
1704
 
      sprintf (idbuf, " /* id %u */", id);
1705
 
      if (! append_type (info, idbuf))
1706
 
        return false;
1707
 
    }
1708
 
 
1709
 
  return true;
1710
 
}
1711
 
 
1712
 
/* Output a typedef.  */
1713
 
 
1714
 
static boolean
1715
 
pr_typdef (p, name)
1716
 
     PTR p;
1717
 
     const char *name;
1718
 
{
1719
 
  struct pr_handle *info = (struct pr_handle *) p;
1720
 
  char *s;
1721
 
 
1722
 
  if (! substitute_type (info, name))
1723
 
    return false;
1724
 
 
1725
 
  s = pop_type (info);
1726
 
  if (s == NULL)
1727
 
    return false;
1728
 
/*
1729
 
  indent (info);
1730
 
  TRACE_FPRINTF( (info->f, "typedef %s;\n", s));
1731
 
*/
1732
 
  free (s);
1733
 
 
1734
 
  return true;
1735
 
}
1736
 
 
1737
 
/* Output a tag.  The tag should already be in the string on the
1738
 
   stack, so all we have to do here is print it out.  */
1739
 
 
1740
 
/*ARGSUSED*/
1741
 
static boolean
1742
 
pr_tag (p, name)
1743
 
     PTR p;
1744
 
     const char *name;
1745
 
{
1746
 
  struct pr_handle *info = (struct pr_handle *) p;
1747
 
  char *t;
1748
 
 
1749
 
  t = pop_type (info);
1750
 
  if (t == NULL)
1751
 
    return false;
1752
 
/*
1753
 
  indent (info);
1754
 
  TRACE_FPRINTF( (info->f, "%s;\n", t));
1755
 
*/
1756
 
  free (t);
1757
 
 
1758
 
  return true;
1759
 
}
1760
 
 
1761
 
/* Output an integer constant.  */
1762
 
 
1763
 
static boolean
1764
 
pr_int_constant (p, name, val)
1765
 
     PTR p;
1766
 
     const char *name;
1767
 
     bfd_vma val;
1768
 
{
1769
 
/*
1770
 
  struct pr_handle *info = (struct pr_handle *) p;
1771
 
  char ab[20];
1772
 
  indent (info);
1773
 
  print_vma (val, ab, false, false);
1774
 
  TRACE_FPRINTF( (info->f, "const int %s = %s;\n", name, ab));
1775
 
 */
1776
 
  return true;
1777
 
}
1778
 
 
1779
 
/* Output a floating point constant.  */
1780
 
 
1781
 
static boolean
1782
 
pr_float_constant (p, name, val)
1783
 
     PTR p;
1784
 
     const char *name;
1785
 
     double val;
1786
 
{
1787
 
/*
1788
 
  struct pr_handle *info = (struct pr_handle *) p;
1789
 
  indent (info);
1790
 
  TRACE_FPRINTF( (info->f, "const double %s = %g;\n", name, val));
1791
 
 */
1792
 
  return true;
1793
 
}
1794
 
 
1795
 
/* Output a typed constant.  */
1796
 
 
1797
 
static boolean
1798
 
pr_typed_constant (p, name, val)
1799
 
     PTR p;
1800
 
     const char *name;
1801
 
     bfd_vma val;
1802
 
{
1803
 
  struct pr_handle *info = (struct pr_handle *) p;
1804
 
  char *t;
1805
 
 
1806
 
  t = pop_type (info);
1807
 
  if (t == NULL)
1808
 
    return false;
1809
 
/*
1810
 
  char ab[20];
1811
 
  indent (info);
1812
 
  print_vma (val, ab, false, false);
1813
 
  TRACE_FPRINTF( (info->f, "const %s %s = %s;\n", t, name, ab));
1814
 
*/
1815
 
  free (t);
1816
 
 
1817
 
  return true;
1818
 
}
1819
 
 
1820
 
/* Output a variable.  */
1821
 
 
1822
 
static boolean
1823
 
pr_variable (p, name, kind, val)
1824
 
     PTR p;
1825
 
     const char *name;
1826
 
     enum debug_var_kind kind;
1827
 
     bfd_vma val;
1828
 
{
1829
 
  struct pr_handle *info = (struct pr_handle *) p;
1830
 
  char *t;
1831
 
  char ab[20];
1832
 
  (void)ab;
1833
 
 
1834
 
  if (! substitute_type (info, name))
1835
 
    return false;
1836
 
 
1837
 
  t = pop_type (info);
1838
 
  if (t == NULL)
1839
 
    return false;
1840
 
 
1841
 
#if 0
1842
 
  indent (info);
1843
 
  switch (kind)
1844
 
    {
1845
 
    case DEBUG_STATIC:
1846
 
    case DEBUG_LOCAL_STATIC:
1847
 
      TRACE_FPRINTF( (info->f, "static "));
1848
 
      break;
1849
 
    case DEBUG_REGISTER:
1850
 
      TRACE_FPRINTF( (info->f, "register "));
1851
 
      break;
1852
 
    default:
1853
 
      break;
1854
 
    }
1855
 
  print_vma (val, ab, true, true);
1856
 
  TRACE_FPRINTF( (info->f, "%s /* %s */;\n", t, ab));
1857
 
#else /* 0 */
1858
 
#if 0
1859
 
        if (kind==DEBUG_STATIC || kind==DEBUG_LOCAL_STATIC) {
1860
 
                print_vma (val, ab, true, true);
1861
 
                TRACE_FPRINTF( (info->f, "STATIC_VAR: %s /* %s */;\n", t, ab));
1862
 
        }
1863
 
#endif /* 0 */
1864
 
#endif /* !0 */
1865
 
 
1866
 
  free (t);
1867
 
 
1868
 
  return true;
1869
 
}
1870
 
 
1871
 
/* Start outputting a function.  */
1872
 
 
1873
 
static boolean
1874
 
pr_start_function (p, name, global)
1875
 
     PTR p;
1876
 
     const char *name;
1877
 
     boolean global;
1878
 
{
1879
 
  struct pr_handle *info = (struct pr_handle *) p;
1880
 
  char *t;
1881
 
 
1882
 
  if (! substitute_type (info, name))
1883
 
    return false;
1884
 
 
1885
 
  t = pop_type (info);
1886
 
  if (t == NULL)
1887
 
    return false;
1888
 
 
1889
 
#if 0
1890
 
  indent (info);
1891
 
  if (! global)
1892
 
    TRACE_FPRINTF( (info->f, "static "));
1893
 
  TRACE_FPRINTF( (info->f, "%s (", t));
1894
 
  info->parameter = 1;
1895
 
#else /* 0 */
1896
 
        if (info->functions_size==info->functions_maxsize) {
1897
 
                info->functions_maxsize *= 2;
1898
 
                info->functions = xrealloc(info->functions,
1899
 
                        info->functions_maxsize*sizeof(debug_function_t));
1900
 
                assert(info->functions!=0);
1901
 
        }
1902
 
        /* info->functions[info->functions_size] = xmalloc(sizeof(debug_function_t)); */
1903
 
        info->function = &info->functions[info->functions_size];
1904
 
        ++info->functions_size;
1905
 
        info->function->symbol = NULL;
1906
 
        info->function->lines = NULL;
1907
 
        info->function->lines_count = 0;
1908
 
        info->function->max_lines_count = 0;
1909
 
        info->function->name = t;
1910
 
        info->function->filename = NULL;
1911
 
        info->function->block = NULL;
1912
 
        info->function->argv = NULL;
1913
 
        info->function->argc = 0;
1914
 
        info->function->max_argc = 0;
1915
 
#endif /* !0 */
1916
 
        return true;
1917
 
}
1918
 
 
1919
 
/* Output a function parameter.  */
1920
 
 
1921
 
static boolean
1922
 
pr_function_parameter (p, name, kind, val)
1923
 
     PTR p;
1924
 
     const char *name;
1925
 
     enum debug_parm_kind kind;
1926
 
     bfd_vma val;
1927
 
{
1928
 
  struct pr_handle *info = (struct pr_handle *) p;
1929
 
  debug_function_t*     f = info->function;
1930
 
  char *t;
1931
 
  char ab[20];
1932
 
  (void)ab;
1933
 
 
1934
 
  if (kind == DEBUG_PARM_REFERENCE
1935
 
      || kind == DEBUG_PARM_REF_REG)
1936
 
    {
1937
 
      if (! pr_reference_type (p))
1938
 
        return false;
1939
 
    }
1940
 
 
1941
 
  if (! substitute_type (info, name))
1942
 
    return false;
1943
 
 
1944
 
  t = pop_type (info);
1945
 
  if (t == NULL)
1946
 
    return false;
1947
 
 
1948
 
#if 0
1949
 
  if (info->parameter != 1)
1950
 
    TRACE_FPRINTF( (info->f, ", "));
1951
 
 
1952
 
  if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
1953
 
    TRACE_FPRINTF( (info->f, "register "));
1954
 
 
1955
 
  print_vma (val, ab, true, true);
1956
 
  TRACE_FPRINTF( (info->f, "%s /* %s */", t, ab));
1957
 
  free (t);
1958
 
  ++info->parameter;
1959
 
#else /* 0 */
1960
 
        assert(f!=NULL);
1961
 
        if (f->argv==NULL) {
1962
 
                f->max_argc = 7; /* rarely anyone has more than that many args... */
1963
 
                f->argv = xmalloc(sizeof(debug_parameter_t)*f->max_argc);
1964
 
        } else if (f->argc==f->max_argc) {
1965
 
                f->max_argc *= 2;
1966
 
                f->argv = realloc(f->argv,sizeof(debug_parameter_t)*f->max_argc);
1967
 
        }
1968
 
        f->argv[f->argc].offset = val;
1969
 
        f->argv[f->argc].name = t;
1970
 
        ++f->argc;
1971
 
#endif /* !0 */
1972
 
        return true;
1973
 
}
1974
 
 
1975
 
/* Start writing out a block.  */
1976
 
 
1977
 
static boolean
1978
 
pr_start_block (p, addr)
1979
 
     PTR p;
1980
 
     bfd_vma addr;
1981
 
{
1982
 
        struct pr_handle *info = (struct pr_handle *) p;
1983
 
        char ab[20];
1984
 
        debug_block_t*  block = 0;
1985
 
        (void)ab;
1986
 
#if 0
1987
 
  if (info->parameter > 0)
1988
 
    {
1989
 
      TRACE_FPRINTF( (info->f, ")\n"));
1990
 
      info->parameter = 0;
1991
 
    }
1992
 
  indent (info);
1993
 
  print_vma (addr, ab, true, true);
1994
 
  TRACE_FPRINTF( (info->f, "{ /* %s */\n", ab));
1995
 
  info->indent += 2;
1996
 
#else
1997
 
        if (info->block) {
1998
 
                if (info->block->childs_count==0)
1999
 
                        info->block->childs = xmalloc(sizeof(debug_block_t));
2000
 
                else
2001
 
                        info->block->childs = xrealloc(info->block->childs,
2002
 
                                                info->block->childs_count*sizeof(debug_block_t));
2003
 
                block = &info->block->childs[info->block->childs_count];
2004
 
        } else {
2005
 
                block = xmalloc(sizeof(debug_block_t));
2006
 
                info->function->block = block;
2007
 
        }
2008
 
        block->begin_addr = addr;
2009
 
        block->end_addr = 0;
2010
 
        block->parent = info->block;
2011
 
        block->childs = NULL;
2012
 
        block->childs_count = 0;
2013
 
        info->block = block;
2014
 
#endif
2015
 
        return true;
2016
 
}
2017
 
 
2018
 
/* Write out line number information.  */
2019
 
 
2020
 
static boolean
2021
 
pr_lineno (p, filename, lineno, addr)
2022
 
     PTR p;
2023
 
     const char *filename;
2024
 
     unsigned long lineno;
2025
 
     bfd_vma addr;
2026
 
{
2027
 
        struct pr_handle *info = (struct pr_handle *) p;
2028
 
        char ab[20];
2029
 
        debug_function_t*       f = info->function;
2030
 
        (void)ab;
2031
 
 
2032
 
#if 0
2033
 
  indent (info);
2034
 
  print_vma (addr, ab, true, true);
2035
 
  TRACE_FPRINTF( (info->f, "/* file %s line %lu addr %s */\n", filename, lineno, ab));
2036
 
#else /* 0 */
2037
 
        if (f==NULL)    /* FIXME: skips junk silently. */
2038
 
                return true;
2039
 
        /* assert(f!=NULL); */
2040
 
        if (f->filename==NULL) {
2041
 
                f->filename = filename;
2042
 
                assert(f->lines==0);
2043
 
                f->max_lines_count = 4;
2044
 
                f->lines = xmalloc(sizeof(debug_lineno_t)*f->max_lines_count);
2045
 
        }
2046
 
        if (f->lines_count==f->max_lines_count) {
2047
 
                f->max_lines_count *= 2;
2048
 
                f->lines = xrealloc(f->lines, sizeof(debug_lineno_t)*f->max_lines_count);
2049
 
        }
2050
 
        f->lines[f->lines_count].lineno = lineno;
2051
 
        f->lines[f->lines_count].addr = addr;
2052
 
        ++f->lines_count;
2053
 
#endif /* !0 */
2054
 
 
2055
 
  return true;
2056
 
}
2057
 
 
2058
 
/* Finish writing out a block.  */
2059
 
 
2060
 
static boolean
2061
 
pr_end_block (p, addr)
2062
 
     PTR p;
2063
 
     bfd_vma addr;
2064
 
{
2065
 
        struct pr_handle *info = (struct pr_handle *) p;
2066
 
 
2067
 
#if 0
2068
 
  char ab[20];
2069
 
 
2070
 
  info->indent -= 2;
2071
 
  indent (info);
2072
 
  print_vma (addr, ab, true, true);
2073
 
  TRACE_FPRINTF( (info->f, "} /* %s */\n", ab));
2074
 
#else /* 0 */
2075
 
        assert(info->block!=0);
2076
 
        info->block->end_addr = addr;
2077
 
        info->block = info->block->parent;
2078
 
#endif /* !0 */
2079
 
 
2080
 
        return true;
2081
 
}
2082
 
 
2083
 
/* Finish writing out a function.  */
2084
 
 
2085
 
/*ARGSUSED*/
2086
 
static boolean
2087
 
pr_end_function (p)
2088
 
     PTR p;
2089
 
{
2090
 
        struct pr_handle *info = (struct pr_handle *) p;
2091
 
        assert(info->block==0);
2092
 
        info->function = NULL;
2093
 
        return true;
2094
 
}
2095
 
 
2096
 
/* third parameter to segv_action. */
2097
 
/* Got it after a bit of head scratching and stack dumping. */
2098
 
typedef struct {
2099
 
        u_int32_t       foo1;   /* +0x00 */
2100
 
        u_int32_t       foo2;
2101
 
        u_int32_t       foo3;
2102
 
        u_int32_t       foo4;   /* usually 2 */
2103
 
        u_int32_t       foo5;   /* +0x10 */
2104
 
        u_int32_t       xgs;    /* always zero */
2105
 
        u_int32_t       xfs;    /* always zero */
2106
 
        u_int32_t       xes;    /* always es=ds=ss */
2107
 
        u_int32_t       xds;    /* +0x20 */
2108
 
        u_int32_t       edi;
2109
 
        u_int32_t       esi;
2110
 
        u_int32_t       ebp;
2111
 
        u_int32_t       esp;    /* +0x30 */
2112
 
        u_int32_t       ebx;
2113
 
        u_int32_t       edx;
2114
 
        u_int32_t       ecx;
2115
 
        u_int32_t       eax;    /* +0x40 */
2116
 
        u_int32_t       foo11;  /* usually 0xe */
2117
 
        u_int32_t       foo12;  /* usually 0x6 */
2118
 
        u_int32_t       eip;    /* instruction pointer */
2119
 
        u_int32_t       xcs;    /* +0x50 */
2120
 
        u_int32_t       foo21;  /* usually 0x2 */
2121
 
        u_int32_t       foo22;  /* second stack pointer?! Probably. */
2122
 
        u_int32_t       xss;
2123
 
        u_int32_t       foo31;  /* +0x60 */ /* usually 0x0 */
2124
 
        u_int32_t       foo32;  /* usually 0x2 */
2125
 
        u_int32_t       fault_addr;     /* Address which caused a fault */
2126
 
        u_int32_t       foo41;  /* usually 0x2 */
2127
 
} signal_regs_t;
2128
 
 
2129
 
signal_regs_t*  ptrace_regs = 0;        /* Tells my_ptrace to "ptrace" current process" */
2130
 
/*
2131
 
 * my_ptrace: small wrapper around ptrace.
2132
 
 * Act as normal ptrace if ptrace_regs==0.
2133
 
 * Read data from current process if ptrace_regs!=0.
2134
 
 */
2135
 
static int
2136
 
my_ptrace(      int     request,
2137
 
                int     pid,
2138
 
                int     addr,
2139
 
                int     data)
2140
 
{
2141
 
        if (ptrace_regs==0)
2142
 
                return ptrace(request, pid, addr, data);
2143
 
        /* we are tracing ourselves! */
2144
 
        switch (request) {
2145
 
        case PTRACE_ATTACH:     return 0;
2146
 
        case PTRACE_CONT:       return 0;
2147
 
        case PTRACE_DETACH:     return 0;
2148
 
        case PTRACE_PEEKUSER:
2149
 
                                switch (addr / 4) {
2150
 
                                case EIP:       return ptrace_regs->eip;
2151
 
                                case EBP:       return ptrace_regs->ebp;
2152
 
                                default:        assert(0);
2153
 
                                }
2154
 
        case PTRACE_PEEKTEXT:   /* FALLTHROUGH */
2155
 
        case PTRACE_PEEKDATA:   return *(int*)(addr);
2156
 
        default:                assert(0);
2157
 
        }
2158
 
        errno = 1;      /* what to do here? */
2159
 
        return 1;       /* failed?! */
2160
 
}
2161
 
 
2162
 
#define MAXARGS 6
2163
 
 
2164
 
/*
2165
 
 * To minimize the number of parameters.
2166
 
 */
2167
 
typedef struct {
2168
 
        asymbol**               syms;   /* Sorted! */
2169
 
        int                     symcount;
2170
 
        debug_function_t**      functions;
2171
 
        int                     functions_size;
2172
 
} symbol_data_t;
2173
 
 
2174
 
/*
2175
 
 * Perform a search. A binary search for a symbol.
2176
 
 */
2177
 
static void
2178
 
decode_symbol(  symbol_data_t*          symbol_data,
2179
 
                const unsigned long     addr,
2180
 
                char*                   buf,
2181
 
                const int               bufsize)
2182
 
{
2183
 
        asymbol**       syms = symbol_data->syms;
2184
 
        const int       symcount = symbol_data->symcount;
2185
 
        int             bottom = 0;
2186
 
        int             top = symcount - 1;
2187
 
        int             i;
2188
 
        if (symcount==0) {
2189
 
                sprintf(buf, "????");
2190
 
                return;
2191
 
        }
2192
 
        while (top>bottom+1) {
2193
 
                i = (top+bottom) / 2;
2194
 
                if (bfd_asymbol_value(syms[i])==addr) {
2195
 
                        sprintf(buf, "%s", syms[i]->name);
2196
 
                        return;
2197
 
                } else if (bfd_asymbol_value(syms[i]) > addr)
2198
 
                        top = i;
2199
 
                else
2200
 
                        bottom = i;
2201
 
        }
2202
 
        i = bottom;
2203
 
        if (addr<bfd_asymbol_value(syms[i]) || addr>(syms[i]->section->vma+syms[i]->section->_cooked_size))
2204
 
                sprintf(buf, "????");
2205
 
        else
2206
 
                sprintf(buf, "%s + 0x%lx", syms[i]->name, addr-bfd_asymbol_value(syms[i]));
2207
 
}
2208
 
 
2209
 
/*
2210
 
 * 1. Perform a binary search for an debug_function_t.
2211
 
 * 2. Fill buf/bufsize with name, parameters and lineno, if found
2212
 
 *    Or with '????' otherwise.
2213
 
 */
2214
 
static debug_function_t*
2215
 
find_debug_function_t(  symbol_data_t*          symbol_data,
2216
 
                        const pid_t             pid,
2217
 
                        const unsigned long     fp,     /* frame pointer */
2218
 
                        const unsigned long     addr,
2219
 
                        char*                   buf,    /* string buffer */
2220
 
                        const int               bufsize)/* FIXME: not used! */
2221
 
{
2222
 
        debug_function_t**      syms = symbol_data->functions;
2223
 
        debug_function_t*       f = NULL;
2224
 
        debug_block_t*          block = NULL;
2225
 
        debug_lineno_t*         lineno = NULL;
2226
 
        const int               symcount = symbol_data->functions_size;
2227
 
        int                     bottom = 0;
2228
 
        int                     top = symcount - 1;
2229
 
        int                     i;
2230
 
        char*                   bufptr = buf;
2231
 
 
2232
 
        if (symcount==0) {
2233
 
                sprintf(buf, "????");
2234
 
                return NULL;
2235
 
        }
2236
 
        while (top>bottom+1) {
2237
 
                i = (top+bottom) / 2;
2238
 
                if (syms[i]->block->begin_addr==addr) {
2239
 
                        f = syms[i];
2240
 
                        break;
2241
 
                } else if (syms[i]->block->begin_addr > addr)
2242
 
                                top = i;
2243
 
                else
2244
 
                        if (syms[i]->block->end_addr >= addr) {
2245
 
                                f = syms[i];
2246
 
                                break;
2247
 
                        } else
2248
 
                                bottom = i;
2249
 
        }
2250
 
        i = bottom;
2251
 
        if (f!=0)
2252
 
                block = f->block;
2253
 
        else {
2254
 
                block = syms[i]->block;
2255
 
                if (block->begin_addr>=addr && block->end_addr<=addr)
2256
 
                        f = syms[i];
2257
 
        }
2258
 
        if (f==0)
2259
 
                sprintf(buf, "????");
2260
 
        else {
2261
 
                /*
2262
 
                 * Do the backtrace the GDB way...
2263
 
                 */
2264
 
                unsigned long   arg;
2265
 
                /* assert(f->lines_count>0); */
2266
 
                if (f->lines_count>0) {
2267
 
                        lineno = &f->lines[f->lines_count-1];
2268
 
                        for (i=1; i<f->lines_count; ++i)
2269
 
                                if (f->lines[i].addr>addr) {
2270
 
                                        lineno = &f->lines[i-1];
2271
 
                                        break;
2272
 
                                }
2273
 
                }
2274
 
                bufptr[0] = 0;
2275
 
                bufptr += sprintf(bufptr, "%s+0x%lx (", f->name, addr-block->begin_addr);
2276
 
                for (i=0; i<f->argc; ++i) {
2277
 
                        bufptr += sprintf(bufptr, "%s = ", f->argv[i].name);
2278
 
                        /* FIXME: better parameter printing */
2279
 
                        errno = 0;
2280
 
                        arg = my_ptrace(PTRACE_PEEKDATA, pid, fp+f->argv[i].offset, 0);
2281
 
                        assert(errno==0);
2282
 
                        bufptr += sprintf(bufptr, "0x%x", arg);
2283
 
                        if (i!=f->argc-1)
2284
 
                                bufptr += sprintf(bufptr, ", ");
2285
 
                }
2286
 
                if (lineno!=0)
2287
 
                        bufptr += sprintf(bufptr, ") at %s:%d", f->filename, lineno->lineno);
2288
 
        }
2289
 
        return f;
2290
 
}
2291
 
 
2292
 
/*
2293
 
 * Advance through the stacks and display frames as needed.
2294
 
 */
2295
 
static int
2296
 
my_crawl(       int             pid,
2297
 
                symbol_data_t*  symbol_data,
2298
 
                int             fout)
2299
 
{
2300
 
        unsigned long           pc = 0;
2301
 
        unsigned long           fp = 0;
2302
 
        unsigned long           nextfp;
2303
 
        unsigned long           nargs;
2304
 
        unsigned long           i;
2305
 
        unsigned long           arg;
2306
 
        char                    buf[8096];      // FIXME: enough?
2307
 
        debug_function_t*       f = 0;
2308
 
 
2309
 
        errno = 0;
2310
 
 
2311
 
        pc = my_ptrace(PTRACE_PEEKUSER, pid, EIP * 4, 0);
2312
 
        if (!errno)
2313
 
                fp = my_ptrace(PTRACE_PEEKUSER, pid, EBP * 4, 0);
2314
 
 
2315
 
        if (!errno) {
2316
 
#if 1
2317
 
                f = find_debug_function_t(symbol_data, pid, fp, pc, buf, sizeof(buf));
2318
 
                fdprintf(fout,"0x%08lx: %s", pc, buf);
2319
 
                for ( ; !errno && fp; ) {
2320
 
                        nextfp = my_ptrace(PTRACE_PEEKDATA, pid, fp, 0);
2321
 
                        if (errno)
2322
 
                                break;
2323
 
 
2324
 
                        if (f==0) {
2325
 
                                nargs = (nextfp - fp - 8) / 4;
2326
 
                                if (nargs > MAXARGS)
2327
 
                                        nargs = MAXARGS;
2328
 
                                if (nargs > 0) {
2329
 
                                        fdputs(" (", fout);
2330
 
                                        for (i = 1; i <= nargs; i++) {
2331
 
                                                arg = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0);
2332
 
                                                if (errno)
2333
 
                                                        break;
2334
 
                                                fdprintf(fout,"%lx", arg);
2335
 
                                                if (i < nargs)
2336
 
                                                        fdputs(", ", fout);
2337
 
                                        }
2338
 
                                        fdputc(')', fout);
2339
 
                                        nargs = nextfp - fp - 8 - (4 * nargs);
2340
 
                                        if (!errno && nargs > 0)
2341
 
                                                fdprintf(fout," + %lx\n", nargs);
2342
 
                                        else
2343
 
                                                fdputc('\n', fout);
2344
 
                                } else
2345
 
                                        fdputc('\n', fout);
2346
 
                        } else
2347
 
                                fdputc('\n', fout);
2348
 
 
2349
 
                        if (errno || !nextfp)
2350
 
                                break;
2351
 
                        pc = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0);
2352
 
                        fp = nextfp;
2353
 
                        if (errno)
2354
 
                                break;
2355
 
                        f = find_debug_function_t(symbol_data, pid, fp, pc, buf, sizeof(buf));
2356
 
                        fdprintf(fout,"0x%08lx: %s", pc, buf);
2357
 
                }
2358
 
#else /* 1 */
2359
 
                decode_symbol(symbol_data, pc, buf, sizeof(buf));
2360
 
                fdprintf(fout,"0x%08lx: %s", pc, buf);
2361
 
                for ( ; !errno && fp; ) {
2362
 
                        nextfp = my_ptrace(PTRACE_PEEKDATA, pid, fp, 0);
2363
 
                        if (errno)
2364
 
                                break;
2365
 
 
2366
 
                        nargs = (nextfp - fp - 8) / 4;
2367
 
                        if (nargs > MAXARGS)
2368
 
                                nargs = MAXARGS;
2369
 
                        if (nargs > 0) {
2370
 
                                fputs(" (", fout);
2371
 
                                for (i = 1; i <= nargs; i++) {
2372
 
                                        arg = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0);
2373
 
                                        if (errno)
2374
 
                                                break;
2375
 
                                        fdprintf(fout,"%lx", arg);
2376
 
                                        if (i < nargs)
2377
 
                                                fputs(", ", fout);
2378
 
                                }
2379
 
                                fdputc(')', fout);
2380
 
                                nargs = nextfp - fp - 8 - (4 * nargs);
2381
 
                                if (!errno && nargs > 0)
2382
 
                                        fdprintf(fout," + %lx\n", nargs);
2383
 
                                else
2384
 
                                        fdputc('\n', fout);
2385
 
                        } else
2386
 
                                fdputc('\n', fout);
2387
 
 
2388
 
                        if (errno || !nextfp)
2389
 
                                break;
2390
 
                        pc = my_ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0);
2391
 
                        fp = nextfp;
2392
 
                        if (errno)
2393
 
                                break;
2394
 
                        decode_symbol(symbol_data, pc, buf, sizeof(buf));
2395
 
                        fdprintf(fout,"0x%08lx: %s", pc, buf);
2396
 
                }
2397
 
#endif /* !1 */
2398
 
        }
2399
 
        if (errno)
2400
 
                perror("my_crawl");
2401
 
        return errno;
2402
 
}
2403
 
 
2404
 
/* layout from /usr/src/linux/arch/i386/kernel/process.c */
2405
 
static void
2406
 
show_regs(      signal_regs_t*  regs,
2407
 
                int             fd)
2408
 
{
2409
 
        /* long cr0 = 0L, cr2 = 0L, cr3 = 0L; */
2410
 
 
2411
 
        fdprintf(fd,"\n");
2412
 
        fdprintf(fd,"FAULT ADDR: %08x\n", regs->fault_addr);
2413
 
        fdprintf(fd,"EIP: %04x:[<%08x>]",0xffff & regs->xcs,regs->eip);
2414
 
        if (regs->xcs & 3)
2415
 
                fdprintf(fd," ESP: %04x:%08x",0xffff & regs->xss,regs->esp);
2416
 
        /*fdprintf(fd," EFLAGS: %08lx\n",regs->eflags); */
2417
 
        fdprintf(fd, "\n");
2418
 
        fdprintf(fd,"EAX: %08x EBX: %08x ECX: %08x EDX: %08x\n",
2419
 
                regs->eax,regs->ebx,regs->ecx,regs->edx);
2420
 
        fdprintf(fd,"ESI: %08x EDI: %08x EBP: %08x",
2421
 
                regs->esi, regs->edi, regs->ebp);
2422
 
        fdprintf(fd," DS: %04x ES: %04x\n",
2423
 
                0xffff & regs->xds,0xffff & regs->xes);
2424
 
        /*
2425
 
        __asm__("movl %%cr0, %0": "=r" (cr0));
2426
 
        __asm__("movl %%cr2, %0": "=r" (cr2));
2427
 
        __asm__("movl %%cr3, %0": "=r" (cr3));
2428
 
        fprintf(stderr,"CR0: %08lx CR2: %08lx CR3: %08lx\n", cr0, cr2, cr3); */
2429
 
}
2430
 
 
2431
 
/*
2432
 
 * Load a BFD for an executable based on PID. Return 0 on failure.
2433
 
 */
2434
 
static bfd*
2435
 
load_bfd(       const int       pid)
2436
 
{
2437
 
        char    filename[512];
2438
 
        bfd*    abfd = 0;
2439
 
 
2440
 
        /* Get the contents from procfs. */
2441
 
#if 1
2442
 
        sprintf(filename, "/proc/%d/exe", pid);
2443
 
#else
2444
 
        sprintf(filename, "crashing");
2445
 
#endif 
2446
 
 
2447
 
        if ((abfd = bfd_openr (filename, 0))== NULL)
2448
 
                bfd_nonfatal (filename);
2449
 
        else {
2450
 
                char**  matching;
2451
 
                assert(bfd_check_format(abfd, bfd_archive)!=true);
2452
 
 
2453
 
                /*
2454
 
                 * There is no indication in BFD documentation that it should be done.
2455
 
                 * God knows why...
2456
 
                 */
2457
 
                if (!bfd_check_format_matches (abfd, bfd_object, &matching)) {
2458
 
                        bfd_nonfatal (bfd_get_filename (abfd));
2459
 
                        if (bfd_get_error () == bfd_error_file_ambiguously_recognized) {
2460
 
                                list_matching_formats (matching);
2461
 
                                free (matching);
2462
 
                        }
2463
 
                }
2464
 
        }
2465
 
        return abfd;
2466
 
}
2467
 
 
2468
 
/*
2469
 
 * Those are for qsort. We need only function addresses, so all the others don't count.
2470
 
 */
2471
 
/*
2472
 
 * Compare two BFD::asymbol-s.
2473
 
 */
2474
 
static int 
2475
 
compare_symbols(const void*     ap,
2476
 
                const void*     bp)
2477
 
{
2478
 
        const asymbol *a = *(const asymbol **)ap;
2479
 
        const asymbol *b = *(const asymbol **)bp;
2480
 
        if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
2481
 
                return 1;
2482
 
        else if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
2483
 
                return -1;
2484
 
        return 0;
2485
 
}
2486
 
 
2487
 
/*
2488
 
 * Compare two debug_asymbol_t-s.
2489
 
 */
2490
 
static int 
2491
 
compare_debug_function_t(const void*    ap,
2492
 
                        const void*     bp)
2493
 
{
2494
 
        const debug_function_t *a = *(const debug_function_t **)ap;
2495
 
        const debug_function_t *b = *(const debug_function_t **)bp;
2496
 
        assert(a->block!=0);
2497
 
        assert(b->block!=0);
2498
 
        {
2499
 
                const bfd_vma   addr1 = a->block->begin_addr;
2500
 
                const bfd_vma   addr2 = b->block->begin_addr;
2501
 
                if (addr1 > addr2)
2502
 
                        return 1;
2503
 
                else if (addr2 > addr1)
2504
 
                        return -1;
2505
 
        }
2506
 
        return 0;
2507
 
}
2508
 
 
2509
 
/*
2510
 
 * Filter out (in place) symbols that are useless for stack tracing.
2511
 
 * COUNT is the number of elements in SYMBOLS.
2512
 
 * Return the number of useful symbols.
2513
 
 */
2514
 
 
2515
 
static long
2516
 
remove_useless_symbols( asymbol**       symbols,
2517
 
                        long            count)
2518
 
{
2519
 
        asymbol**       in_ptr = symbols;
2520
 
        asymbol**       out_ptr = symbols;
2521
 
 
2522
 
        while (--count >= 0) {
2523
 
                asymbol *sym = *in_ptr++;
2524
 
 
2525
 
                if (sym->name == NULL || sym->name[0] == '\0' || sym->value==0)
2526
 
                        continue;
2527
 
                if (sym->flags & (BSF_DEBUGGING))
2528
 
                        continue;
2529
 
                if (bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section))
2530
 
                        continue;
2531
 
                *out_ptr++ = sym;
2532
 
        }
2533
 
        return out_ptr - symbols;
2534
 
}
2535
 
 
2536
 
/*
2537
 
 * Debugging information.
2538
 
 */
2539
 
static  bfd*                    abfd = 0;
2540
 
static  PTR                     dhandle = 0;
2541
 
static  asymbol**               syms = 0;
2542
 
static  long                    symcount = 0;
2543
 
static  asymbol**               sorted_syms = 0;
2544
 
static  long                    sorted_symcount = 0;
2545
 
static  debug_function_t**      functions = 0;
2546
 
static  int                     functions_size = 0;
2547
 
static  int                     sigreport = SIGUSR1;
2548
 
static  pthread_t               segv_tid;       /* What thread did SEGV? */
2549
 
static  pid_t                   segv_pid;
2550
 
 
2551
 
/*
2552
 
 * We'll get here after a SIGSEGV. But you can install it on other signals, too :)
2553
 
 * Because we are in the middle of the SIGSEGV, we are on our own. We can't do
2554
 
 * any malloc(), any fopen(), nothing. The last is actually a sin. We event can't
2555
 
 * fprintf(stderr,...)!!!
2556
 
 */
2557
 
static void
2558
 
segv_action(int signo, siginfo_t* siginfo, void* ptr)
2559
 
{
2560
 
        symbol_data_t           symbol_data;
2561
 
        int                     fd = -1;
2562
 
 
2563
 
        segv_pid = getpid();
2564
 
        segv_tid = pthread_self();
2565
 
        fd = open_log_file(segv_tid, segv_pid);
2566
 
        /* signal(SIGSEGV, SIG_DFL); */
2567
 
        ptrace_regs = (signal_regs_t*)ptr;
2568
 
        assert(ptrace_regs!=0);
2569
 
 
2570
 
        /* Show user how guilty we are. */
2571
 
        fdprintf(fd,"--------- SEGV in PROCESS %d, THREAD %d ---------------\n", segv_pid, pthread_self());
2572
 
        show_regs(ptrace_regs, fd);
2573
 
 
2574
 
        /* Some form of stack trace, too. */
2575
 
        fdprintf(fd, "STACK TRACE:\n");
2576
 
 
2577
 
        symbol_data.syms = sorted_syms;
2578
 
        symbol_data.symcount = sorted_symcount;
2579
 
        symbol_data.functions = functions;
2580
 
        symbol_data.functions_size = functions_size;
2581
 
        my_crawl(segv_pid, &symbol_data, fd);
2582
 
        //fflush(stdout);
2583
 
        close(fd);
2584
 
        linuxthreads_notify_others(sigreport);
2585
 
}
2586
 
 
2587
 
 
2588
 
static void
2589
 
report_action(int signo, siginfo_t* siginfo, void* ptr)
2590
 
{
2591
 
        const int       pid = getpid();
2592
 
        pthread_t       tid = pthread_self();
2593
 
        symbol_data_t   symbol_data;
2594
 
        int             fd;
2595
 
        if (pthread_equal(tid, segv_tid)) {
2596
 
                /* We have already printed our stack trace... */
2597
 
                return;
2598
 
        }
2599
 
 
2600
 
        fd = open_log_file(tid, pid);
2601
 
        fdprintf(fd, "REPORT: CURRENT PROCESS:%d, THREAD:%d\n", getpid(), pthread_self());
2602
 
        /* signal(SIGSEGV, SIG_DFL); */
2603
 
        ptrace_regs = (signal_regs_t*)ptr;
2604
 
        assert(ptrace_regs!=0);
2605
 
 
2606
 
        /* Show user how guilty we are. */
2607
 
        fdprintf(fd,"--------- STACK TRACE FOR PROCESS %d, THREAD %d ---------------\n", pid, pthread_self());
2608
 
        show_regs(ptrace_regs, fd);
2609
 
 
2610
 
        /* Some form of stack trace, too. */
2611
 
        fdprintf(fd, "STACK TRACE:\n");
2612
 
 
2613
 
        symbol_data.syms = sorted_syms;
2614
 
        symbol_data.symcount = sorted_symcount;
2615
 
        symbol_data.functions = functions;
2616
 
        symbol_data.functions_size = functions_size;
2617
 
        my_crawl(pid, &symbol_data, fd);
2618
 
        //fflush(stdout);
2619
 
        close(fd);
2620
 
        /* Tell segv_thread to proceed after pause(). */
2621
 
        /*pthread_kill(segv_tid, sigreport);
2622
 
        kill(segv_pid, sigreport);
2623
 
        pthread_cancel(tid); */
2624
 
}
2625
 
 
2626
 
/*
2627
 
 * Main library routine. Just call it on your program.
2628
 
 */
2629
 
int
2630
 
pstack_install_segv_action(     const char*     path_format_)
2631
 
{
2632
 
        const int               pid = getpid();
2633
 
        struct sigaction        act;
2634
 
 
2635
 
        /* Store what we have to for later usage. */
2636
 
        path_format = path_format_;
2637
 
 
2638
 
        /* We need a signal action for SIGSEGV and sigreport ! */
2639
 
        sigreport = SIGUSR1;
2640
 
        act.sa_handler = 0;
2641
 
        sigemptyset(&act.sa_mask);
2642
 
        act.sa_flags = SA_SIGINFO|SA_ONESHOT;   /* Just one SIGSEGV. */
2643
 
        act.sa_sigaction = segv_action;
2644
 
        act.sa_restorer = NULL;
2645
 
        if (sigaction(SIGSEGV, &act, NULL)!=0) {
2646
 
                perror("sigaction");
2647
 
                return 1;
2648
 
        }
2649
 
        act.sa_sigaction = report_action;
2650
 
        act.sa_flags = SA_SIGINFO;              /* But many sigreports. */
2651
 
        if (sigaction(sigreport, &act, NULL)!=0) {
2652
 
                perror("sigaction");
2653
 
                return 1;
2654
 
        }
2655
 
 
2656
 
        /* And a little setup for libiberty. */
2657
 
        program_name = "crashing";
2658
 
        xmalloc_set_program_name (program_name);
2659
 
 
2660
 
        /* Umm, and initialize BFD, too */
2661
 
        bfd_init();
2662
 
#if 0
2663
 
        list_supported_targets(0, stdout);
2664
 
        set_default_bfd_target(); 
2665
 
#endif /* 0 */
2666
 
 
2667
 
        if ((abfd = load_bfd(pid))==0)
2668
 
                fprintf(stderr, "BFD load failed..\n");
2669
 
        else {
2670
 
                long    storage_needed= (bfd_get_file_flags(abfd) & HAS_SYMS) ?
2671
 
                  bfd_get_symtab_upper_bound (abfd) : 0;
2672
 
                long    i;
2673
 
                (void)i;
2674
 
 
2675
 
                if (storage_needed < 0)
2676
 
                        fprintf(stderr, "Symbol table size estimation failure.\n");
2677
 
                else if (storage_needed > 0) {
2678
 
                        syms = (asymbol **) xmalloc (storage_needed);
2679
 
                        symcount = bfd_canonicalize_symtab (abfd, syms);
2680
 
 
2681
 
                        TRACE_FPRINTF((stderr, "TOTAL: %ld SYMBOLS.\n", symcount));
2682
 
                        /* We need debugging info, too! */
2683
 
                        if (symcount==0 || (dhandle = read_debugging_info (abfd, syms, symcount))==0)
2684
 
                                fprintf(stderr, "NO DEBUGGING INFORMATION FOUND.\n");
2685
 
 
2686
 
                        /* We make a copy of syms to sort.  We don't want to sort syms
2687
 
                        because that will screw up the relocs.  */
2688
 
                        sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *));
2689
 
                        memcpy (sorted_syms, syms, symcount * sizeof (asymbol *));
2690
 
 
2691
 
#if 0
2692
 
                        for (i=0; i<symcount; ++i)
2693
 
                                if (syms[i]->name!=0 && strlen(syms[i]->name)>0 && syms[i]->value!=0)
2694
 
                                        printf("%08lx T %s\n", syms[i]->section->vma + syms[i]->value, syms[i]->name);
2695
 
#endif
2696
 
                        sorted_symcount = remove_useless_symbols (sorted_syms, symcount);
2697
 
                        TRACE_FPRINTF((stderr, "SORTED: %ld SYMBOLS.\n", sorted_symcount));
2698
 
 
2699
 
                        /* Sort the symbols into section and symbol order */
2700
 
                        qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols);
2701
 
#if 0
2702
 
                        for (i=0; i<sorted_symcount; ++i)
2703
 
                                if (sorted_syms[i]->name!=0 && strlen(sorted_syms[i]->name)>0 && sorted_syms[i]->value!=0)
2704
 
                                        printf("%08lx T %s\n", sorted_syms[i]->section->vma + sorted_syms[i]->value, sorted_syms[i]->name);
2705
 
#endif
2706
 
                        /* We have symbols, we need debugging info somehow sorted out. */
2707
 
                        if (dhandle==0) {
2708
 
                                fprintf(stderr, "STACK TRACE WILL BE UNCOMFORTABLE.\n");
2709
 
                        } else {
2710
 
                                /* Start collecting the debugging information.... */
2711
 
                                struct pr_handle info;
2712
 
 
2713
 
                                info.f = stdout;
2714
 
                                info.indent = 0;
2715
 
                                info.stack = NULL;
2716
 
                                info.parameter = 0;
2717
 
                                info.block = NULL;
2718
 
                                info.function = NULL;
2719
 
                                info.functions_size = 0;
2720
 
                                info.functions_maxsize = 1000;
2721
 
                                info.functions = (debug_function_t*)xmalloc(sizeof(debug_function_t)*info.functions_maxsize);
2722
 
                                debug_write (dhandle, &pr_fns, (PTR) &info);
2723
 
                                TRACE_FPRINTF((stdout, "\n%d DEBUG SYMBOLS\n", info.functions_size));
2724
 
                                assert(info.functions_size!=0);
2725
 
                                functions = xmalloc(sizeof(debug_function_t*)*info.functions_size);
2726
 
                                functions_size = info.functions_size;
2727
 
                                for (i=0; i<functions_size; ++i)
2728
 
                                        functions[i] = &info.functions[i];
2729
 
                                /* Sort the symbols into section and symbol order */
2730
 
                                qsort (functions, functions_size, sizeof(debug_function_t*),
2731
 
                                        compare_debug_function_t);
2732
 
#if 0
2733
 
                                for (i=0; i<info.functions_size; ++i)
2734
 
                                        fprintf(stdout, "%08lx T %s\n", info.functions[i].block->begin_addr, info.functions[i].name);
2735
 
#endif
2736
 
                                fflush(stdout);
2737
 
                        }
2738
 
                } else /* storage_needed == 0 */
2739
 
                        fprintf(stderr, "NO SYMBOLS FOUND.\n");
2740
 
        }
2741
 
        return 0;
2742
 
}
2743
 
 
2744
 
/*********************************************************************/
2745
 
/*********************************************************************/
2746
 
/*********************************************************************/