forked from gbenson/binutils-gdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstabs.c
5438 lines (4687 loc) · 132 KB
/
stabs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* stabs.c -- Parse stabs debugging information
Copyright (C) 1995-2015 Free Software Foundation, Inc.
Written by Ian Lance Taylor <[email protected]>.
This file is part of GNU Binutils.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
/* This file contains code which parses stabs debugging information.
The organization of this code is based on the gdb stabs reading
code. The job it does is somewhat different, because it is not
trying to identify the correct address for anything. */
#include "sysdep.h"
#include "bfd.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "demangle.h"
#include "debug.h"
#include "budbg.h"
#include "filenames.h"
#include "aout/aout64.h"
#include "aout/stab_gnu.h"
/* The number of predefined XCOFF types. */
#define XCOFF_TYPE_COUNT 34
/* This structure is used as a handle so that the stab parsing doesn't
need to use any static variables. */
struct stab_handle
{
/* The BFD. */
bfd *abfd;
/* TRUE if this is stabs in sections. */
bfd_boolean sections;
/* The symbol table. */
asymbol **syms;
/* The number of symbols. */
long symcount;
/* The accumulated file name string. */
char *so_string;
/* The value of the last N_SO symbol. */
bfd_vma so_value;
/* The value of the start of the file, so that we can handle file
relative N_LBRAC and N_RBRAC symbols. */
bfd_vma file_start_offset;
/* The offset of the start of the function, so that we can handle
function relative N_LBRAC and N_RBRAC symbols. */
bfd_vma function_start_offset;
/* The version number of gcc which compiled the current compilation
unit, 0 if not compiled by gcc. */
int gcc_compiled;
/* Whether an N_OPT symbol was seen that was not generated by gcc,
so that we can detect the SunPRO compiler. */
bfd_boolean n_opt_found;
/* The main file name. */
char *main_filename;
/* A stack of unfinished N_BINCL files. */
struct bincl_file *bincl_stack;
/* A list of finished N_BINCL files. */
struct bincl_file *bincl_list;
/* Whether we are inside a function or not. */
bfd_boolean within_function;
/* The address of the end of the function, used if we have seen an
N_FUN symbol while in a function. This is -1 if we have not seen
an N_FUN (the normal case). */
bfd_vma function_end;
/* The depth of block nesting. */
int block_depth;
/* List of pending variable definitions. */
struct stab_pending_var *pending;
/* Number of files for which we have types. */
unsigned int files;
/* Lists of types per file. */
struct stab_types **file_types;
/* Predefined XCOFF types. */
debug_type xcoff_types[XCOFF_TYPE_COUNT];
/* Undefined tags. */
struct stab_tag *tags;
/* Set by parse_stab_type if it sees a structure defined as a cross
reference to itself. Reset by parse_stab_type otherwise. */
bfd_boolean self_crossref;
};
/* A list of these structures is used to hold pending variable
definitions seen before the N_LBRAC of a block. */
struct stab_pending_var
{
/* Next pending variable definition. */
struct stab_pending_var *next;
/* Name. */
const char *name;
/* Type. */
debug_type type;
/* Kind. */
enum debug_var_kind kind;
/* Value. */
bfd_vma val;
};
/* A list of these structures is used to hold the types for a single
file. */
struct stab_types
{
/* Next set of slots for this file. */
struct stab_types *next;
/* Types indexed by type number. */
#define STAB_TYPES_SLOTS (16)
debug_type types[STAB_TYPES_SLOTS];
};
/* We keep a list of undefined tags that we encounter, so that we can
fill them in if the tag is later defined. */
struct stab_tag
{
/* Next undefined tag. */
struct stab_tag *next;
/* Tag name. */
const char *name;
/* Type kind. */
enum debug_type_kind kind;
/* Slot to hold real type when we discover it. If we don't, we fill
in an undefined tag type. */
debug_type slot;
/* Indirect type we have created to point at slot. */
debug_type type;
};
static char *savestring (const char *, int);
static bfd_vma parse_number (const char **, bfd_boolean *);
static void bad_stab (const char *);
static void warn_stab (const char *, const char *);
static bfd_boolean parse_stab_string
(void *, struct stab_handle *, int, int, bfd_vma, const char *);
static debug_type parse_stab_type
(void *, struct stab_handle *, const char *, const char **, debug_type **);
static bfd_boolean parse_stab_type_number (const char **, int *);
static debug_type parse_stab_range_type
(void *, struct stab_handle *, const char *, const char **, const int *);
static debug_type parse_stab_sun_builtin_type (void *, const char **);
static debug_type parse_stab_sun_floating_type (void *, const char **);
static debug_type parse_stab_enum_type (void *, const char **);
static debug_type parse_stab_struct_type
(void *, struct stab_handle *, const char *, const char **,
bfd_boolean, const int *);
static bfd_boolean parse_stab_baseclasses
(void *, struct stab_handle *, const char **, debug_baseclass **);
static bfd_boolean parse_stab_struct_fields
(void *, struct stab_handle *, const char **, debug_field **, bfd_boolean *);
static bfd_boolean parse_stab_cpp_abbrev
(void *, struct stab_handle *, const char **, debug_field *);
static bfd_boolean parse_stab_one_struct_field
(void *, struct stab_handle *, const char **, const char *,
debug_field *, bfd_boolean *);
static bfd_boolean parse_stab_members
(void *, struct stab_handle *, const char *, const char **, const int *,
debug_method **);
static debug_type parse_stab_argtypes
(void *, struct stab_handle *, debug_type, const char *, const char *,
debug_type, const char *, bfd_boolean, bfd_boolean, const char **);
static bfd_boolean parse_stab_tilde_field
(void *, struct stab_handle *, const char **, const int *, debug_type *,
bfd_boolean *);
static debug_type parse_stab_array_type
(void *, struct stab_handle *, const char **, bfd_boolean);
static void push_bincl (struct stab_handle *, const char *, bfd_vma);
static const char *pop_bincl (struct stab_handle *);
static bfd_boolean find_excl (struct stab_handle *, const char *, bfd_vma);
static bfd_boolean stab_record_variable
(void *, struct stab_handle *, const char *, debug_type,
enum debug_var_kind, bfd_vma);
static bfd_boolean stab_emit_pending_vars (void *, struct stab_handle *);
static debug_type *stab_find_slot (struct stab_handle *, const int *);
static debug_type stab_find_type (void *, struct stab_handle *, const int *);
static bfd_boolean stab_record_type
(void *, struct stab_handle *, const int *, debug_type);
static debug_type stab_xcoff_builtin_type
(void *, struct stab_handle *, int);
static debug_type stab_find_tagged_type
(void *, struct stab_handle *, const char *, int, enum debug_type_kind);
static debug_type *stab_demangle_argtypes
(void *, struct stab_handle *, const char *, bfd_boolean *, unsigned int);
static debug_type *stab_demangle_v3_argtypes
(void *, struct stab_handle *, const char *, bfd_boolean *);
static debug_type *stab_demangle_v3_arglist
(void *, struct stab_handle *, struct demangle_component *, bfd_boolean *);
static debug_type stab_demangle_v3_arg
(void *, struct stab_handle *, struct demangle_component *, debug_type,
bfd_boolean *);
/* Save a string in memory. */
static char *
savestring (const char *start, int len)
{
char *ret;
ret = (char *) xmalloc (len + 1);
memcpy (ret, start, len);
ret[len] = '\0';
return ret;
}
/* Read a number from a string. */
static bfd_vma
parse_number (const char **pp, bfd_boolean *poverflow)
{
unsigned long ul;
const char *orig;
if (poverflow != NULL)
*poverflow = FALSE;
orig = *pp;
errno = 0;
ul = strtoul (*pp, (char **) pp, 0);
if (ul + 1 != 0 || errno == 0)
{
/* If bfd_vma is larger than unsigned long, and the number is
meant to be negative, we have to make sure that we sign
extend properly. */
if (*orig == '-')
return (bfd_vma) (bfd_signed_vma) (long) ul;
return (bfd_vma) ul;
}
/* Note that even though strtoul overflowed, it should have set *pp
to the end of the number, which is where we want it. */
if (sizeof (bfd_vma) > sizeof (unsigned long))
{
const char *p;
bfd_boolean neg;
int base;
bfd_vma over, lastdig;
bfd_boolean overflow;
bfd_vma v;
/* Our own version of strtoul, for a bfd_vma. */
p = orig;
neg = FALSE;
if (*p == '+')
++p;
else if (*p == '-')
{
neg = TRUE;
++p;
}
base = 10;
if (*p == '0')
{
if (p[1] == 'x' || p[1] == 'X')
{
base = 16;
p += 2;
}
else
{
base = 8;
++p;
}
}
over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
overflow = FALSE;
v = 0;
while (1)
{
int d;
d = *p++;
if (ISDIGIT (d))
d -= '0';
else if (ISUPPER (d))
d -= 'A';
else if (ISLOWER (d))
d -= 'a';
else
break;
if (d >= base)
break;
if (v > over || (v == over && (bfd_vma) d > lastdig))
{
overflow = TRUE;
break;
}
}
if (! overflow)
{
if (neg)
v = - v;
return v;
}
}
/* If we get here, the number is too large to represent in a
bfd_vma. */
if (poverflow != NULL)
*poverflow = TRUE;
else
warn_stab (orig, _("numeric overflow"));
return 0;
}
/* Give an error for a bad stab string. */
static void
bad_stab (const char *p)
{
fprintf (stderr, _("Bad stab: %s\n"), p);
}
/* Warn about something in a stab string. */
static void
warn_stab (const char *p, const char *err)
{
fprintf (stderr, _("Warning: %s: %s\n"), err, p);
}
/* Create a handle to parse stabs symbols with. */
void *
start_stab (void *dhandle ATTRIBUTE_UNUSED, bfd *abfd, bfd_boolean sections,
asymbol **syms, long symcount)
{
struct stab_handle *ret;
ret = (struct stab_handle *) xmalloc (sizeof *ret);
memset (ret, 0, sizeof *ret);
ret->abfd = abfd;
ret->sections = sections;
ret->syms = syms;
ret->symcount = symcount;
ret->files = 1;
ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
ret->file_types[0] = NULL;
ret->function_end = (bfd_vma) -1;
return (void *) ret;
}
/* When we have processed all the stabs information, we need to go
through and fill in all the undefined tags. */
bfd_boolean
finish_stab (void *dhandle, void *handle)
{
struct stab_handle *info = (struct stab_handle *) handle;
struct stab_tag *st;
if (info->within_function)
{
if (! stab_emit_pending_vars (dhandle, info)
|| ! debug_end_function (dhandle, info->function_end))
return FALSE;
info->within_function = FALSE;
info->function_end = (bfd_vma) -1;
}
for (st = info->tags; st != NULL; st = st->next)
{
enum debug_type_kind kind;
kind = st->kind;
if (kind == DEBUG_KIND_ILLEGAL)
kind = DEBUG_KIND_STRUCT;
st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
if (st->slot == DEBUG_TYPE_NULL)
return FALSE;
}
return TRUE;
}
/* Handle a single stabs symbol. */
bfd_boolean
parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
const char *string)
{
struct stab_handle *info = (struct stab_handle *) handle;
/* gcc will emit two N_SO strings per compilation unit, one for the
directory name and one for the file name. We just collect N_SO
strings as we see them, and start the new compilation unit when
we see a non N_SO symbol. */
if (info->so_string != NULL
&& (type != N_SO || *string == '\0' || value != info->so_value))
{
if (! debug_set_filename (dhandle, info->so_string))
return FALSE;
info->main_filename = info->so_string;
info->gcc_compiled = 0;
info->n_opt_found = FALSE;
/* Generally, for stabs in the symbol table, the N_LBRAC and
N_RBRAC symbols are relative to the N_SO symbol value. */
if (! info->sections)
info->file_start_offset = info->so_value;
/* We need to reset the mapping from type numbers to types. We
can't free the old mapping, because of the use of
debug_make_indirect_type. */
info->files = 1;
info->file_types = ((struct stab_types **)
xmalloc (sizeof *info->file_types));
info->file_types[0] = NULL;
info->so_string = NULL;
/* Now process whatever type we just got. */
}
switch (type)
{
case N_FN:
case N_FN_SEQ:
break;
case N_LBRAC:
/* Ignore extra outermost context from SunPRO cc and acc. */
if (info->n_opt_found && desc == 1)
break;
if (! info->within_function)
{
fprintf (stderr, _("N_LBRAC not within function\n"));
return FALSE;
}
/* Start an inner lexical block. */
if (! debug_start_block (dhandle,
(value
+ info->file_start_offset
+ info->function_start_offset)))
return FALSE;
/* Emit any pending variable definitions. */
if (! stab_emit_pending_vars (dhandle, info))
return FALSE;
++info->block_depth;
break;
case N_RBRAC:
/* Ignore extra outermost context from SunPRO cc and acc. */
if (info->n_opt_found && desc == 1)
break;
/* We shouldn't have any pending variable definitions here, but,
if we do, we probably need to emit them before closing the
block. */
if (! stab_emit_pending_vars (dhandle, info))
return FALSE;
/* End an inner lexical block. */
if (! debug_end_block (dhandle,
(value
+ info->file_start_offset
+ info->function_start_offset)))
return FALSE;
--info->block_depth;
if (info->block_depth < 0)
{
fprintf (stderr, _("Too many N_RBRACs\n"));
return FALSE;
}
break;
case N_SO:
/* This always ends a function. */
if (info->within_function)
{
bfd_vma endval;
endval = value;
if (*string != '\0'
&& info->function_end != (bfd_vma) -1
&& info->function_end < endval)
endval = info->function_end;
if (! stab_emit_pending_vars (dhandle, info)
|| ! debug_end_function (dhandle, endval))
return FALSE;
info->within_function = FALSE;
info->function_end = (bfd_vma) -1;
}
/* An empty string is emitted by gcc at the end of a compilation
unit. */
if (*string == '\0')
return TRUE;
/* Just accumulate strings until we see a non N_SO symbol. If
the string starts with a directory separator or some other
form of absolute path specification, we discard the previously
accumulated strings. */
if (info->so_string == NULL)
info->so_string = xstrdup (string);
else
{
char *f;
f = info->so_string;
if (IS_ABSOLUTE_PATH (string))
info->so_string = xstrdup (string);
else
info->so_string = concat (info->so_string, string,
(const char *) NULL);
free (f);
}
info->so_value = value;
break;
case N_SOL:
/* Start an include file. */
if (! debug_start_source (dhandle, string))
return FALSE;
break;
case N_BINCL:
/* Start an include file which may be replaced. */
push_bincl (info, string, value);
if (! debug_start_source (dhandle, string))
return FALSE;
break;
case N_EINCL:
/* End an N_BINCL include. */
if (! debug_start_source (dhandle, pop_bincl (info)))
return FALSE;
break;
case N_EXCL:
/* This is a duplicate of a header file named by N_BINCL which
was eliminated by the linker. */
if (! find_excl (info, string, value))
return FALSE;
break;
case N_SLINE:
if (! debug_record_line (dhandle, desc,
value + (info->within_function
? info->function_start_offset : 0)))
return FALSE;
break;
case N_BCOMM:
if (! debug_start_common_block (dhandle, string))
return FALSE;
break;
case N_ECOMM:
if (! debug_end_common_block (dhandle, string))
return FALSE;
break;
case N_FUN:
if (*string == '\0')
{
if (info->within_function)
{
/* This always marks the end of a function; we don't
need to worry about info->function_end. */
if (info->sections)
value += info->function_start_offset;
if (! stab_emit_pending_vars (dhandle, info)
|| ! debug_end_function (dhandle, value))
return FALSE;
info->within_function = FALSE;
info->function_end = (bfd_vma) -1;
}
break;
}
/* A const static symbol in the .text section will have an N_FUN
entry. We need to use these to mark the end of the function,
in case we are looking at gcc output before it was changed to
always emit an empty N_FUN. We can't call debug_end_function
here, because it might be a local static symbol. */
if (info->within_function
&& (info->function_end == (bfd_vma) -1
|| value < info->function_end))
info->function_end = value;
/* Fall through. */
/* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
symbols, and if it does not start with :S, gdb relocates the
value to the start of the section. gcc always seems to use
:S, so we don't worry about this. */
/* Fall through. */
default:
{
const char *colon;
colon = strchr (string, ':');
if (colon != NULL
&& (colon[1] == 'f' || colon[1] == 'F'))
{
if (info->within_function)
{
bfd_vma endval;
endval = value;
if (info->function_end != (bfd_vma) -1
&& info->function_end < endval)
endval = info->function_end;
if (! stab_emit_pending_vars (dhandle, info)
|| ! debug_end_function (dhandle, endval))
return FALSE;
info->function_end = (bfd_vma) -1;
}
/* For stabs in sections, line numbers and block addresses
are offsets from the start of the function. */
if (info->sections)
info->function_start_offset = value;
info->within_function = TRUE;
}
if (! parse_stab_string (dhandle, info, type, desc, value, string))
return FALSE;
}
break;
case N_OPT:
if (string != NULL && strcmp (string, "gcc2_compiled.") == 0)
info->gcc_compiled = 2;
else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
info->gcc_compiled = 1;
else
info->n_opt_found = TRUE;
break;
case N_OBJ:
case N_ENDM:
case N_MAIN:
case N_WARNING:
break;
}
return TRUE;
}
/* Parse the stabs string. */
static bfd_boolean
parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
int desc ATTRIBUTE_UNUSED, bfd_vma value, const char *string)
{
const char *p;
char *name;
int type;
debug_type dtype;
bfd_boolean synonym;
bfd_boolean self_crossref;
debug_type *slot;
p = strchr (string, ':');
if (p == NULL)
return TRUE;
while (p[1] == ':')
{
p += 2;
p = strchr (p, ':');
if (p == NULL)
{
bad_stab (string);
return FALSE;
}
}
/* FIXME: Sometimes the special C++ names start with '.'. */
name = NULL;
if (string[0] == '$')
{
switch (string[1])
{
case 't':
name = "this";
break;
case 'v':
/* Was: name = "vptr"; */
break;
case 'e':
name = "eh_throw";
break;
case '_':
/* This was an anonymous type that was never fixed up. */
break;
case 'X':
/* SunPRO (3.0 at least) static variable encoding. */
break;
default:
warn_stab (string, _("unknown C++ encoded name"));
break;
}
}
if (name == NULL)
{
if (p == string || (string[0] == ' ' && p == string + 1))
name = NULL;
else
name = savestring (string, p - string);
}
++p;
if (ISDIGIT (*p) || *p == '(' || *p == '-')
type = 'l';
else
type = *p++;
switch (type)
{
case 'c':
/* c is a special case, not followed by a type-number.
SYMBOL:c=iVALUE for an integer constant symbol.
SYMBOL:c=rVALUE for a floating constant symbol.
SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
e.g. "b:c=e6,0" for "const b = blob1"
(where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
if (*p != '=')
{
bad_stab (string);
return FALSE;
}
++p;
switch (*p++)
{
case 'r':
/* Floating point constant. */
if (! debug_record_float_const (dhandle, name, atof (p)))
return FALSE;
break;
case 'i':
/* Integer constant. */
/* Defining integer constants this way is kind of silly,
since 'e' constants allows the compiler to give not only
the value, but the type as well. C has at least int,
long, unsigned int, and long long as constant types;
other languages probably should have at least unsigned as
well as signed constants. */
if (! debug_record_int_const (dhandle, name, atoi (p)))
return FALSE;
break;
case 'e':
/* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
can be represented as integral.
e.g. "b:c=e6,0" for "const b = blob1"
(where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
dtype = parse_stab_type (dhandle, info, (const char *) NULL,
&p, (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (*p != ',')
{
bad_stab (string);
return FALSE;
}
if (! debug_record_typed_const (dhandle, name, dtype, atoi (p)))
return FALSE;
break;
default:
bad_stab (string);
return FALSE;
}
break;
case 'C':
/* The name of a caught exception. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL,
&p, (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_label (dhandle, name, dtype, value))
return FALSE;
break;
case 'f':
case 'F':
/* A function definition. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
return FALSE;
/* Sun acc puts declared types of arguments here. We don't care
about their actual types (FIXME -- we should remember the whole
function prototype), but the list may define some new types
that we have to remember, so we must scan it now. */
while (*p == ';')
{
++p;
if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL)
== DEBUG_TYPE_NULL)
return FALSE;
}
break;
case 'G':
{
asymbol **ps;
/* A global symbol. The value must be extracted from the
symbol table. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (name != NULL)
{
char leading;
long c;
leading = bfd_get_symbol_leading_char (info->abfd);
for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
{
const char *n;
n = bfd_asymbol_name (*ps);
if (leading != '\0' && *n == leading)
++n;
if (*n == *name && strcmp (n, name) == 0)
break;
}
if (c > 0)
value = bfd_asymbol_value (*ps);
}
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
value))
return FALSE;
}
break;
/* This case is faked by a conditional above, when there is no
code letter in the dbx data. Dbx data never actually
contains 'l'. */
case 'l':
case 's':
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
value))
return FALSE;
break;
case 'p':
/* A function parameter. */
if (*p != 'F')
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
else
{
/* pF is a two-letter code that means a function parameter in
Fortran. The type-number specifies the type of the return
value. Translate it into a pointer-to-function type. */
++p;
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype != DEBUG_TYPE_NULL)
{
debug_type ftype;
ftype = debug_make_function_type (dhandle, dtype,
(debug_type *) NULL, FALSE);
dtype = debug_make_pointer_type (dhandle, ftype);
}
}
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
value))
return FALSE;
/* FIXME: At this point gdb considers rearranging the parameter
address on a big endian machine if it is smaller than an int.
We have no way to do that, since we don't really know much
about the target. */
break;
case 'P':
if (stabtype == N_FUN)
{
/* Prototype of a function referenced by this file. */
while (*p == ';')
{
++p;
if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL)
== DEBUG_TYPE_NULL)
return FALSE;
}
break;
}
/* Fall through. */
case 'R':
/* Parameter which is in a register. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
value))
return FALSE;
break;
case 'r':
/* Register variable (either global or local). */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
value))
return FALSE;
/* FIXME: At this point gdb checks to combine pairs of 'p' and
'r' stabs into a single 'P' stab. */
break;
case 'S':
/* Static symbol at top level of file. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
value))
return FALSE;
break;
case 't':
/* A typedef. */
dtype = parse_stab_type (dhandle, info, name, &p, &slot);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (name == NULL)
{
/* A nameless type. Nothing to do. */
return TRUE;
}
dtype = debug_name_type (dhandle, name, dtype);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (slot != NULL)
*slot = dtype;
break;
case 'T':
/* Struct, union, or enum tag. For GNU C++, this can be be followed
by 't' which means we are typedef'ing it as well. */
if (*p != 't')
{
synonym = FALSE;
/* FIXME: gdb sets synonym to TRUE if the current language
is C++. */