~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to pstack/pstack.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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
/*********************************************************************/