blob: 4f4429c5845e48a2b5eacf0027d45fc000022f88 [file] [log] [blame]
njn4bbdc972003-10-16 10:10:55 +00001/*--------------------------------------------------------------------*/
2/*--- Read stabs debug info. vg_symtab_stabs.c ---*/
3/*--------------------------------------------------------------------*/
4
5/*
6 This file is part of Valgrind, an extensible x86 protected-mode
7 emulator for monitoring program execution on x86-Unixes.
8
nethercotebb1c9912004-01-04 16:43:23 +00009 Copyright (C) 2000-2004 Julian Seward
njn4bbdc972003-10-16 10:10:55 +000010 jseward@acm.org
11
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 02111-1307, USA.
26
27 The GNU General Public License is contained in the file COPYING.
28*/
jsgfcb1d1c02003-10-14 21:55:10 +000029
30#include "vg_include.h"
31#include "vg_symtab2.h"
32
33#include <a.out.h> /* stabs defns */
34
35/*------------------------------------------------------------*/
36/*--- Read STABS format debug info. ---*/
37/*------------------------------------------------------------*/
38
39/* Stabs entry types, from:
40 * The "stabs" debug format
41 * Menapace, Kingdon and MacKenzie
42 * Cygnus Support
43 */
44typedef enum { N_UNDEF = 0, /* undefined symbol, new stringtab */
45 N_GSYM = 32, /* Global symbol */
46 N_FUN = 36, /* Function start or end */
47 N_STSYM = 38, /* Data segment file-scope variable */
48 N_LCSYM = 40, /* BSS segment file-scope variable */
49 N_RSYM = 64, /* Register variable */
50 N_SLINE = 68, /* Source line number */
51 N_SO = 100, /* Source file path and name */
52 N_LSYM = 128, /* Stack variable or type */
53 N_BINCL = 130, /* Beginning of an include file */
54 N_SOL = 132, /* Include file name */
55 N_PSYM = 160, /* Function parameter */
56 N_EINCL = 162, /* End of an include file */
57 N_LBRAC = 192, /* Start of lexical block */
58 N_EXCL = 194, /* Placeholder for an include file */
59 N_RBRAC = 224 /* End of lexical block */
60 } stab_types;
61
62
njn4bbdc972003-10-16 10:10:55 +000063/* stabs use a two-dimensional numbering scheme for types: the type
jsgfcb1d1c02003-10-14 21:55:10 +000064 number is either of the form name:N or name:(M,N); name may be
65 empty. N is the type number within a file context; M is the file
66 number (an object may have multiple files by inclusion).
67*/
68
69typedef struct _StabType {
70 Char *str; /* string as it appears in file */
71 SymType *type; /* our type info */
72} StabType;
73
74typedef struct _StabFile {
75 StabType *types;
76 Int ntypes;
77 UInt fileidx; /* for reference, idx of creation */
78} StabFile;
79
80typedef struct _StabTypeTab {
81 StabFile **files;
82 Int nfiles;
83
84 /* List of structure tag names, used for mapping them to actual
85 definitions of the structures. There should really be one of
86 these per object and a global one to cope with cross-object
87 references. */
88 struct structlist {
89 Char *name;
90 Bool isstruct; /* struct (or union) */
91 SymType *type; /* reference */
92 struct structlist *next;
93 } *structlist;
94
95#define HEADER_HASHSZ 53
96 struct header {
97 Char *filename; /* header file name */
98 StabFile *types; /* types for that header */
99 UInt instance; /* instance */
100 struct header *next;
101 } *headerhash[HEADER_HASHSZ];
102} StabTypeTab;
103
104
105static UInt header_hash(Char *filename, UInt instance)
106{
107 Char *cp;
108 UInt hash = 0;
109
110 for(cp = filename; *cp; cp++) {
111 hash += *cp;
112 hash = (hash << 17) | (hash >> (32-17));
113 }
114 hash += instance;
115
116 return hash % HEADER_HASHSZ;
117}
118
119/* Look up a struct/union tag name in table, and return reference to
120 existing type, or create a new tag entry.
121 XXX make this a proper data structure
122*/
123static SymType *structRef(StabTypeTab *tab, SymType *def, Bool isstruct, Char *name)
124{
125 static const Bool debug = False;
126 struct structlist *sl;
127 SymType *ty;
128 static Int warnlen = 0;
129 Int len = 0;
130
131 for(sl = tab->structlist; sl != NULL; sl = sl->next) {
132 len++;
133
134 if (isstruct == sl->isstruct && VG_(strcmp)(name, sl->name) == 0) {
135 if (debug)
136 VG_(printf)("found %s ref for %s\n",
137 isstruct ? "struct" : "union", name);
138 return sl->type;
139 }
140 }
141
142 if (debug && (len > warnlen*2)) {
143 warnlen = len;
144 VG_(printf)("struct ref list reached %d entries\n", len);
145 }
146
147 sl = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*sl));
148 if (isstruct)
149 ty = VG_(st_mkstruct)(def, 0, 0);
150 else
151 ty = VG_(st_mkunion)(def, 0, 0);
152
153 VG_(st_setname)(ty, name);
154 sl->isstruct = isstruct;
155 sl->type = ty;
156 sl->name = name;
157 sl->next = tab->structlist;
158 tab->structlist = sl;
159
160 if (debug)
161 VG_(printf)("created %s ref for %s = %p\n",
162 isstruct ? "struct" : "union", name, ty);
163
164 return ty;
165}
166
167/* Add a structural defintion for a struct/union reference */
168static SymType *structDef(StabTypeTab *tab, SymType *def, Bool isstruct, Char *name)
169{
170 static const Bool debug = False;
171 SymType *ref = structRef(tab, NULL, isstruct, name);
172
173 if (debug)
174 VG_(printf)("defining %s ref for %s %p -> %p\n",
175 isstruct ? "struct" : "union", name, ref, def);
176
177 def = VG_(st_mktypedef)(ref, name, VG_(st_basetype)(def, False));
178 VG_(st_setname)(def, name);
179 return def;
180}
181
182static StabFile *getStabFile(StabTypeTab *tab, Int file, StabFile *set)
183{
184 StabFile *sf;
185 file++; /* file == -1 -> no file */
186
187 if (file < 0)
188 return NULL;
189
190 if (file >= tab->nfiles) {
191 UInt i;
192 StabFile **n = VG_(arena_malloc)(VG_AR_SYMTAB, (file+1) * sizeof(*n));
193
194 for(i = 0; i <= file; i++) {
195 if (i < tab->nfiles)
196 n[i] = tab->files[i];
197 else {
198 n[i] = NULL;
199 }
200 }
201
202 if (tab->files != NULL)
203 VG_(arena_free)(VG_AR_SYMTAB, tab->files);
204
205 tab->files = n;
206 tab->nfiles = file+1;
207 }
208
209 if (set != NULL)
210 tab->files[file] = set;
211
212 if (tab->files[file] == NULL) {
213 sf = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*sf));
214 tab->files[file] = sf;
215 sf->types = NULL;
216 sf->ntypes = 0;
217 sf->fileidx = file - 1; /* compensate for file++ above */
218 }
219
220 sf = tab->files[file];
221
222 return sf;
223}
224
225/* add a new index for a file */
226static void addFileAlias(StabTypeTab *tab, Char *filename, UInt instance, Int idx)
227{
228 static const Bool debug = False;
229 struct header *hp;
230
231 for(hp = tab->headerhash[header_hash(filename, instance)]; hp != NULL; hp = hp->next) {
232 if (hp->instance == instance && VG_(strcmp)(filename, hp->filename) == 0) {
233 if (debug)
234 VG_(printf)("adding alias for \"%s\"/%d fileidx %d to fileidx %d\n",
235 filename, instance, idx, hp->types->fileidx);
236 getStabFile(tab, idx, hp->types);
237 return;
238 }
239 }
240
241 VG_(printf)("Couldn't find previous reference to \"%s\"/%d for fileidx %d\n",
242 filename, instance, idx);
243}
244
245static void addHeader(StabTypeTab *tab, Char *filename, UInt instance, Int idx)
246{
247 static const Bool debug = False;
248 struct header *hp, **bucket;
249
250 if (debug)
251 VG_(printf)("adding new header %s/%d fileidx %d\n", filename, instance, idx);
252
253 bucket = &tab->headerhash[header_hash(filename, instance)];
254
255 hp = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*hp));
256 hp->filename = filename;
257 hp->instance = instance;
258 hp->types = getStabFile(tab, idx, NULL);
259 hp->next = *bucket;
260 *bucket = hp;
261}
262
263static void clearStabFiles(StabTypeTab *tab)
264{
265 VG_(arena_free)(VG_AR_SYMTAB, tab->files);
266
267 tab->files = NULL;
268 tab->nfiles = 0;
269}
270
271static StabType *getStabType(StabTypeTab *tab, Int file, Int sym)
272{
273 StabFile *sf;
274
275 sf = getStabFile(tab, file, NULL);
276
277 if (sf == NULL || sym < 0)
278 return NULL;
279
280 if (sym >= sf->ntypes) {
281 UInt i;
282 StabType *n = VG_(arena_malloc)(VG_AR_SYMTAB, (sym+1) * sizeof(*n));
283
284 for(i = 0; i <= sym; i++) {
285 if (i < sf->ntypes)
286 n[i] = sf->types[i];
287 else {
288 n[i].str = NULL;
289 n[i].type = NULL;
290 }
291 }
292
293 if (sf->types != NULL)
294 VG_(arena_free)(VG_AR_SYMTAB, sf->types);
295
296 sf->types = n;
297 sf->ntypes = sym+1;
298 }
299
300 return &sf->types[sym];
301}
302
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000303static Bool isdigit(Char c, Int base, Int *vp)
jsgfcb1d1c02003-10-14 21:55:10 +0000304{
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000305 Bool ret = False;
306 Int v = 0;
307
jsgfcb1d1c02003-10-14 21:55:10 +0000308 switch(base) {
309 case 10:
310 case 0:
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000311 v = c - '0';
312 ret = (c >= '0' && c <= '9');
313 break;
jsgfcb1d1c02003-10-14 21:55:10 +0000314
315 case 8:
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000316 v = c - '0';
317 ret = (c >= '0' && c <= '7');
318 break;
jsgfcb1d1c02003-10-14 21:55:10 +0000319
320 case 16:
321 if (c >= '0' && c <= '9') {
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000322 v = c - '0';
323 ret = True;
324 } else if (c >= 'a' && c <= 'f') {
325 v = c - 'a';
326 ret = True;
327 } else if (c >= 'A' && c <= 'F') {
328 v = c - 'F';
329 ret = True;
jsgfcb1d1c02003-10-14 21:55:10 +0000330 }
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000331 break;
jsgfcb1d1c02003-10-14 21:55:10 +0000332 }
333
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000334 if (vp && ret)
335 *vp = v;
336
337 return ret;
jsgfcb1d1c02003-10-14 21:55:10 +0000338}
339
340static inline Int getbase(Char **pp)
341{
342 Char *p = *pp;
343 Int base = 10;
344
345 if (p[0] == '0') {
346 if (p[1] == 'x') {
347 base = 16;
348 p += 2;
349 } else {
350 base = 8;
351 p++;
352 }
353 }
354 *pp = p;
355
356 return base;
357}
358
359static Int atoi(Char **pp, Int base)
360{
361 Char *p = *pp;
362 Int ret = 0;
363 Int v;
364 Bool neg = False;
365
366 if (*p == '-') {
367 neg = True;
368 p++;
369 }
370
371 if (base == 0)
372 base = getbase(&p);
373
374 while(isdigit(*p, base, &v)) {
375 ret *= base;
376 ret += v;
377 p++;
378 }
379
380 *pp = p;
381 if (neg)
382 ret = -ret;
383 return ret;
384}
385
386static UInt atou(Char **pp, Int base)
387{
388 Char *p = *pp;
389 UInt ret = 0;
390 Int v;
391
392 if (base == 0)
393 base = getbase(&p);
394
395 while(isdigit(*p, base, &v)) {
396 ret *= base;
397 ret += v;
398 p++;
399 }
400
401 *pp = p;
402 return ret;
403}
404
fitzhardingee5f9d912004-03-09 00:43:08 +0000405/* Skip a ':'-delimited name which may have ::, 'char' or other things in
406 <> brackets */
407static Char *templ_name(Char *p)
408{
409 Int brac = 0;
410
411 for(;;) {
412 if (*p == '<')
413 brac++;
414 if (*p == '>')
415 brac--;
416 /* skip quoted character (note, it could be anything, even a
417 literal \0)
418
419 XXX This is a complete botch; we can't do anything sane here,
420 like support \-quoting, because gcc doesn't seem to generate
421 it, and even if it did, we wouldn't know what "'\'" means -
422 the begining of '\'' or a char in itself ('\\')?
423 */
424 if (brac && p[0] == '\'' && p[2] == '\'')
425 p += 3;
426 if (*p == ':') {
427 if (brac && p[1] == ':')
428 p++;
429 else
430 break;
431 }
jsgfcb1d1c02003-10-14 21:55:10 +0000432 p++;
433 }
434
435 return p;
436}
437
438/* updates pp to point to after parsed typeref */
439static void parse_typeref(Char **pp, Int *filep, Int *symp)
440{
441 Char *p = *pp;
442 Int file, sym;
443
444 file = sym = *filep = *symp = -1;
445
446 if (*p == '(') {
447 p++;
448 file = atoi(&p, 10);
449 if (*p++ != ',')
450 return;
451 sym = atoi(&p, 10);
452 if (*p++ != ')')
453 return;
454 } else if (VG_(isdigit)(*p)) {
455 sym = atoi(&p, 10);
456 }
457
458 *pp = p;
459 *filep = file;
460 *symp = sym;
461}
462
463static void stab_resolve(SymType *st, void *data)
464{
465 static const Bool debug = False;
466 Char *str = (Char *)data;
467 vg_assert(!VG_(st_isresolved)(st));
468
469 if (debug)
470 VG_(printf)("stab_resolve: failing to do anything useful with symtype %p=%s\n",
471 st, str);
472}
473
474/* Top level of recursive descent parser for stab type information.
475 This only extracts the information needed by vg_symtypes.c, which
476 is just structure shapes, pointers and arrays. It is still
477 necessary to parse everything else, because there's no way to skip
478 it to get to the interesting bits. Also, new types can be
479 introduced anywhere, so we need to scan it all to pick them up. */
480static SymType *stabtype_parser(SegInfo *si, SymType *def, Char **pp)
481{
482 static const Bool debug = False;
483 Char *p = *pp;
484 Char t;
485 SymType *type;
486 StabTypeTab *tab = si->stab_typetab;
487
488/* make sure *p == 'c' and skip over it */
489#define EXPECT(c, msg) \
490 do { \
491 if (p == NULL || *p++ != c) { \
492 VG_(printf)("\n @@ expected '%c' at %s (remains=\"%s\")\n", c, msg, p); \
493 return NULL; \
494 } \
495 } while(0)
496
497/* return a pointer to just after the next ch after (and including) ptr */
498#define SKIPPAST(ptr, ch, msg) \
499 ({ \
500 Char *__zz_charptr = VG_(strchr)((ptr), (ch)); \
501 if (__zz_charptr == NULL) { \
502 VG_(printf)("\n @@ expected '%c' at %s (ptr=\"%s\")\n", (ch), (msg), (ptr)); \
503 return NULL; \
504 } \
505 __zz_charptr+1; \
506 })
507
508 t = *p++;
509
510 if (0 && debug)
511 VG_(printf)("stabtype_parser: parsing '%c' remains=\"%s\"\n", t, p);
512
513 switch(t) {
514 case '(':
515 case '0' ... '9': { /* reference (and perhaps definition) */
516 SymType *symtype;
517 Int file, sym;
518 Char *prev;
519
520 p--;
521 prev = p;
522
523 parse_typeref(&p, &file, &sym);
524
525 {
526 /* keep stabtype reference local, because the stabtype table
527 can be rearranged by new insertions, invalidating this
528 pointer; so copy the bits we need and don't hold onto the
529 pointer. */
530 StabType *stabtype = getStabType(tab, file, sym);
531
532 if (stabtype == NULL) {
533 VG_(printf)(" @@ bad type ref: %s\n", prev);
534 return NULL;
535 }
536
537 if (stabtype->type == NULL) {
538 stabtype->type = VG_(st_mkunresolved)(def, stab_resolve, NULL);
539 if (debug)
540 VG_(printf)("making (%d,%d) %p unresolved\n", file, sym, stabtype->type);
541 }
542
543 symtype = stabtype->type;
544 }
545
546 if (*p == '=') {
547 /* a type definition */
548 p++;
549
550 if (VG_(st_isresolved)(symtype)) {
551 /* a redefinition; clear the old type out */
552 StabType *stabtype = getStabType(tab, file, sym);
553
554 symtype = stabtype->type = VG_(st_mkunresolved)(NULL, stab_resolve, NULL);
555 if (debug)
556 VG_(printf)("creating new type %p for definition (%d,%d)\n",
557 symtype, file, sym);
558 } else
559 VG_(st_unresolved_setdata)(symtype, stab_resolve, p);
560
561 if (debug)
562 VG_(printf)("defining type %p (%d,%d) = %s\n", symtype, file, sym, p);
563
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000564 /* Skip type attributes
565 '@' could also be pointer-to-member, so we need to see if
566 the following character looks like a type reference or not.
567 */
568 while(*p == '@' && !(VG_(isdigit)(p[1]) || p[1] == '-' || p[1] == '(') )
jsgfcb1d1c02003-10-14 21:55:10 +0000569 p = SKIPPAST(p+1, ';', "type attrib");
570
571 prev = p;
572
573 type = stabtype_parser(si, symtype, &p);
574 if (debug)
575 VG_(printf)("parsed definition: type=%p symtype=%p\n", type, symtype);
576
577 if (type != symtype) {
578 StabType *stabtype = getStabType(tab, file, sym);
579
580 vg_assert(stabtype->type != NULL);
581 if (0) {
582 /* XXX bogus */
583 vg_assert(!VG_(st_isresolved)(stabtype->type));
584 VG_(arena_free)(VG_AR_SYMTAB, stabtype->type); /* XXX proper free method? */
585 }
586 stabtype->type = type;
587 } else if (!VG_(st_isresolved)(type)) {
588 /* If type is defined in terms of itself, and is
589 therefore not resolved, it is void */
590 if (debug)
591 VG_(printf)("type %p is defined in terms of self - making void\n", type);
592 type = VG_(st_mkvoid)(type);
593 }
594 } else {
595 /* just a type reference */
596 type = symtype;
597 if ((0 || debug) && !VG_(st_isresolved)(type))
598 VG_(printf)("type %p (%d,%d) is unresolved\n", type, file, sym);
599 if ((0 || debug) && VG_(st_isresolved)(type))
600 VG_(printf)("reference (%d,%d) -> %p\n", file, sym, type);
601 }
602 break;
603 }
604
605 case '-': { /* -ve types for builtins? */
606 Int n;
607 p--;
608 n = atoi(&p, 0);
609 switch(n) {
610 case -16: type = VG_(st_mkbool)(def, sizeof(int)); break;
611
612 default:
613 VG_(printf)(" @@ unrecognized negative type %d\n", n);
614 type = NULL;
615 break;
616 }
617 EXPECT(';', "negative builtin type");
618 break;
619 }
620
621 case 't': { /* typedef: 't' TYPE */
622 SymType *td = stabtype_parser(si, NULL, &p);
623 type = VG_(st_mktypedef)(def, NULL, td);
624 break;
625 }
626
627 case 'R': { /* FP type: 'R' FP-TYPE ';' BYTES ';' (extra) ';' */
628 Int fptype, bytes;
629
630 fptype = atoi(&p, 0);
631 EXPECT(';', "FP-TYPE");
632 bytes = atoi(&p, 0);
633 EXPECT(';', "FP-TYPE bytes");
634 atoi(&p, 0);
635 EXPECT(';', "FP-TYPE extra");
636
637 type = VG_(st_mkfloat)(def, bytes * 8);
638 break;
639 }
640
641 case 'r': { /* range: 'r' TYPE ';' MIN ';' MAX ';' */
642 Int min, max;
643 SymType *rtype = stabtype_parser(si, NULL, &p);
644
645 EXPECT(';', "range TYPE");
646
647 /* MIN and MAX are: (INTEGER | 'A' OFFSET | 'T' OFFSET | 'a' REGNO | 't' REGNO | 'J')
648 only expect INTEGER for now (no way to represent the rest yet, and no need so far)
649 */
650 min = atoi(&p, 0);
651 EXPECT(';', "range MIN");
652 max = atoi(&p, 0);
653 EXPECT(';', "range MAX");
654
655 if (debug && 0)
656 VG_(printf)("range: rtype=%p def=%p min=%d max=%d remains = \"%s\"\n",
657 rtype, def, min, max, p);
658
659 if (rtype == def) {
660 if (debug)
661 VG_(printf)("type %p is subrange of self - making int\n", def);
662 type = VG_(st_mkint)(def, sizeof(int), False);
663 } else if (min > max && max == 0) {
664 if (debug)
665 VG_(printf)("type %p has backwards range %d - %d: making float\n",
666 def, min, max);
667 type = VG_(st_mkfloat)(def, min);
668 } else
669 type = VG_(st_mkrange)(def, rtype, min, max);
670
671 vg_assert(VG_(st_isresolved)(type));
672 break;
673 }
674
675 case '&': /* reference */
676 case '*': { /* pointer */
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000677 /* ('*' | '&') TYPE */
jsgfcb1d1c02003-10-14 21:55:10 +0000678 type = stabtype_parser(si, NULL, &p);
679 type = VG_(st_mkpointer)(def, type);
680 break;
681 }
682
jseward9fc153f2004-01-04 22:50:16 +0000683 case 'k': /* const */
684 case 'B': { /* volatile */
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000685 /* ('k' | 'B') TYPE */
jseward9fc153f2004-01-04 22:50:16 +0000686 type = stabtype_parser(si, NULL, &p);
687 break;
688 }
689
jsgfcb1d1c02003-10-14 21:55:10 +0000690 case 'x': { /* reference to undefined type */
691 /* 'x' ('s' | 'u' | 'e') NAME ':' */
jsgfcb1d1c02003-10-14 21:55:10 +0000692 Char kind = *p++; /* get kind */
693 Char *name = p;
694
fitzhardingee5f9d912004-03-09 00:43:08 +0000695 p = templ_name(name);
jsgfcb1d1c02003-10-14 21:55:10 +0000696 EXPECT(':', "struct/union/enum ref");
697
698 name = VG_(addStr)(si, name, p-1-name);
699
700 switch (kind) {
701 case 's': /* struct */
702 case 'u': /* union */
703 type = structRef(tab, def, kind == 's', name);
704 break;
705
706 case 'e': /* enum */
707 type = VG_(st_mkenum)(def, 0);
708 break;
709
710 default:
711 VG_(printf)(" @@ unexpected type ref %c\n", p[-1]);
712 return NULL;
713 };
714
715 break;
716 }
717
fitzhardinge7194a562004-03-09 01:20:47 +0000718 case 'S': { /* set/bitstring */
719 /* 'S' TYPE */
720 SymType *typeinfo;
721
722 typeinfo = stabtype_parser(si, NULL, &p);
723
fitzhardingeb0bde392004-03-11 00:40:11 +0000724 type = VG_(st_mkarray)(def, typeinfo, VG_(st_mkint)(NULL, 1, True));
fitzhardinge7194a562004-03-09 01:20:47 +0000725 break;
726 }
727
jsgfcb1d1c02003-10-14 21:55:10 +0000728 case 'P': /* packed array */
729 case 'a': { /* array */
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000730 /* ( 'a' | 'P' ) IDX-TYPE TYPE */
jsgfcb1d1c02003-10-14 21:55:10 +0000731 SymType *idxtype;
732 SymType *artype;
733
734 idxtype = stabtype_parser(si, NULL, &p);
735 artype = stabtype_parser(si, NULL, &p);
736
737 type = VG_(st_mkarray)(def, idxtype, artype);
738
739 break;
740 }
741
742 case 'e': { /* enum */
743 /* 'e' ( NAME ':' N ',' )* ';' */
744
745 type = VG_(st_mkenum)(def, 0);
746
747 /* don't really care about tags; just skip them */
748 while(*p != ';') {
749 p = SKIPPAST(p, ':', "enum tag NAME");
750 p = SKIPPAST(p, ',', "enum tag N");
751 }
752 p++; /* skip ';' */
753
754 break;
755 }
756
757 case 'u': /* union */
758 case 's': { /* struct */
759 /* Gad. Here we go:
760
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000761 ( 's' | 'u' ) SIZE
jsgfcb1d1c02003-10-14 21:55:10 +0000762 ( '!' NBASE ',' ( VIRT PUB OFF ',' BASE-TYPE ){NBASE} )?
763
764 ( NAME ( ':' ( '/' [0-9] )? TYPE ',' OFFSET ( ',' SIZE )?
765 | '::' ( METHOD-TYPE ':' MANGLE-ARGS ';'
766 PROT QUAL ( '.' | '*' VIRT | '?' ) )+
767 )
768 ';'
769 )*
770
771 ( '~%' FIRST-BASE-CLASS )?
772 ';'
773 */
774 UInt size;
775 Bool method = False;
776
777 size = atou(&p, 0);
778 type = (t == 's' ? VG_(st_mkstruct) : VG_(st_mkunion))(def, size, 0);
779
780 if (*p == '!') {
781 /* base classes */
782 Int nbase;
783
784 p++;
785 nbase = atoi(&p, 0);
786 EXPECT(',', "class base class count");
787 while(nbase--) {
788 p++; /* VIRT flag */
789 p++; /* PUB flag */
790 atoi(&p, 0); /* offset */
791 EXPECT(',', "class base class ref");
792 stabtype_parser(si, NULL, &p);
793
794 if (*p == ';') /* who eats this? */
795 p++;
796 }
797 }
798
799 while(*p != ';') {
800 Char *end;
801 Char *name;
802 UInt off, sz;
803 SymType *fieldty;
804
fitzhardingee5f9d912004-03-09 00:43:08 +0000805 end = templ_name(p);
fitzhardinged8685b82004-02-24 23:46:06 +0000806
jsgfcb1d1c02003-10-14 21:55:10 +0000807 if (end[1] == ':') {
808 /* c++ method names end in :: */
809 method = True;
810
811 if (VG_(strncmp)(p, "op$", 3) == 0) {
812 /* According to stabs.info, operators are named
813 ( "op$::" OP '.' ), where OP is +=, etc. Current
814 gcc doesn't seem to use this; operators just
815 appear as "operator==::" */
816 end = SKIPPAST(end, '.', "op$ name");
817 }
818 name = VG_(addStr)(si, p, end-p);
819 p = end+2;
820 } else {
821 name = VG_(addStr)(si, p, end-p);
822 p = end+1;
823 }
824
825 if (method) {
826 /* don't care about methods, but we still have to crunch
827 through this goo */
828 fieldty = NULL;
829 off = sz = 0;
830
831 do {
832 stabtype_parser(si, NULL, &p); /* METHOD-TYPE */
833
834 EXPECT(':', "struct method MANGLE-ARGS");
835 p = SKIPPAST(p, ';', "struct method MANGLE-ARGS");
836
837 p += 1; /* skip PROT */
838 if (*p >= 'A' && *p <= 'Z')
839 p++; /* skip QUAL (if present) */
840
841 switch(*p++) {
842 case '*': /* VIRT: VTAB-IDX ';' OVERRIDE-CLASS ';' */
843 atoi(&p, 0); /* skip VTAB-IDX */
844 EXPECT(';', "struct method vtab idx");
845 stabtype_parser(si, NULL, &p); /* skip OVERRIDE-CLASS */
846 EXPECT(';', "struct method vtab override");
847 break;
848
849 default:
850 VG_(printf)(" @@ struct method unexpected member-type '%c' \"%s\" remains\n",
851 p[-1], p);
852 /* FALLTHROUGH */
853 case '?':
854 case '.':
855 break;
856 }
857 } while (*p != ';');
858 } else {
859 if (*p == '/') {
860 /* c++ visibility spec: '/' PROT */
861 p += 2;
862 }
863
864 fieldty = stabtype_parser(si, NULL, &p);
865
866 if (*p == ':') {
867 /* static member; don't care (it will appear later) */
868 fieldty = NULL;
869 off = sz = 0;
870
871 p = SKIPPAST(p, ';', "struct static member");
872 p--; /* point at ';' */
873 } else {
874 EXPECT(',', "struct TYPE");
875
876 off = atou(&p, 0);
877
878 if (*p == ',') {
879 EXPECT(',', "struct OFFSET");
880 sz = atou(&p, 0);
881 } else {
882 /* sometimes the size is missing and assumed to be a
883 pointer (in bits) */
884 sz = sizeof(void *) * 8;
885 }
886 }
887 }
888
889 if (fieldty != NULL)
890 VG_(st_addfield)(type, name, fieldty, off, sz);
891
892 EXPECT(';', "struct field end");
893 }
894 p++; /* skip final ';' */
895
896 /* one final C++ surprise */
897 if (*p == '~') {
898 /* "~%" FIRST-BASE-CLASS ';' */
899 p++;
900 EXPECT('%', "struct first base");
901 stabtype_parser(si, NULL, &p); /* skip FIRST-BASE-CLASS */
902 EXPECT(';', "struct first base semi");
903 }
904
905 break;
906 }
907
908 case 'f': /* function */
909 /* 'f' TYPE */
910 type = VG_(st_mkvoid)(def); /* approximate functions as void */
911 stabtype_parser(si, NULL, &p);
912 break;
913
914 case '#': /* method */
915 /* '#' ( '#' RET-TYPE |
916 CLASS-TYPE ',' RET-TYPE ',' ( ARG-TYPE ( ',' ARG-TYPE )* )? )
917 ';'
918 */
919 type = VG_(st_mkvoid)(def); /* methods are really void */
920
921 if (*p == '#') {
922 p++; /* skip '#' */
923 stabtype_parser(si, NULL, &p); /* RET-TYPE */
924 } else {
925 stabtype_parser(si, NULL, &p); /* CLASS-TYPE */
926 EXPECT(',', "method CLASS-TYPE");
927
928 stabtype_parser(si, NULL, &p); /* RET-TYPE */
929 EXPECT(',', "method RET-TYPE");
930
931 while (*p != ';') {
932 stabtype_parser(si, NULL, &p);
933 if (*p == ',')
934 p++;
935 else if (*p != ';')
936 VG_(printf)(" @@ method ARG-TYPE list unexpected '%c'\n", *p);
937 }
938 }
939
940 EXPECT(';', "method definition");
941 break;
942
fitzhardinge3e2c6d52004-03-05 05:43:42 +0000943 case '@': /* pointer to member */
944 /* '@' CLASS-TYPE ',' MEMBER-TYPE */
945 type = VG_(st_mkint)(def, sizeof(int), False); /* make it an int for our use */
946
947 stabtype_parser(si, NULL, &p); /* CLASS-TYPE */
948 EXPECT(',', "member-pointer CLASS-TYPE");
949 stabtype_parser(si, NULL, &p); /* MEMBER-TYPE */
950 break;
951
jsgfcb1d1c02003-10-14 21:55:10 +0000952 default:
953 VG_(printf)(" @@ don't know what type '%c' is\n", t);
954 type = NULL;
955 break;
956 }
957#undef EXPECT
958#undef SKIPPAST
959
960 if (type == NULL)
961 VG_(printf)(" @@ parsing %s gave NULL type (%s remains)\n", *pp, p);
962
963 *pp = p;
964
965 return type;
966}
967
968/* parse a symbol reference: NAME ':' DESC TYPE */
969static Bool initSym(SegInfo *si, Sym *sym, stab_types kind, Char **namep, Int val)
970{
971 static const Bool debug = False;
972 Char *name = *namep;
973 Char *ty;
974 Int len;
975 Bool isTypedef = False;
976 Bool isStruct = False;
977 SymType *base;
978
979 if (debug && 0)
980 VG_(printf)("initSym(si=%p, tab=%p, sym=%p, kind=%d, name=%p \"%s\", val=%d)\n",
981 si, si->stab_typetab, sym, kind, name, name, val);
982
fitzhardingee5f9d912004-03-09 00:43:08 +0000983 ty = templ_name(name);
jsgfcb1d1c02003-10-14 21:55:10 +0000984
985 len = ty - name;
986
987 if (debug) {
988 Char buf[len+1];
989 VG_(strncpy_safely)(buf, name, len+1);
990 VG_(printf)("\ninitSym name=\"%s\" type=%s\n", buf, ty+1);
991 }
992
993 if (*ty != ':') {
994 /* no type info */
995 sym->type = VG_(st_mkvoid)(NULL);
996 } else {
997 ty++; /* skip ':' */
998
999 /* chew through an initial sequence of
1000 type descriptor type describers */
1001 for(;;) {
1002 switch(*ty) {
1003 case 'a': case 'b': case 'c': case 'C':
1004 case 'd': case 'D': case 'f': case 'F':
1005 case 'G': case 'i': case 'I': case 'J':
1006 case 'L': case 'm': case 'p': case 'P':
1007 case 'Q': case 'R': case 'r': case 'S':
1008 case 's': case 'v': case 'V': case 'x':
1009 case 'X':
1010 break;
1011
1012 case 'T': /* struct/union/enum */
1013 isStruct = True;
1014 break;
1015
1016 case 't': /* typedef handled within stabtype_parser */
1017 isTypedef = True;
1018 /* FALLTHROUGH */
1019 case '(': case '-': case '0' ... '9': /* type reference */
1020 default:
1021 goto out;
1022 }
1023 ty++;
1024 }
1025
1026 out:
1027 sym->type = stabtype_parser(si, NULL, &ty);
1028 base = VG_(st_basetype)(sym->type, False);
1029
1030 if (isStruct && (VG_(st_isstruct)(base) || VG_(st_isunion)(base))) {
1031 Char *sname = VG_(addStr)(si, name, len);
1032 structDef(si->stab_typetab, base, VG_(st_isstruct)(base), sname);
1033 }
1034
1035 if (isTypedef) {
1036 Char *tname = VG_(addStr)(si, name, len);
1037 vg_assert(sym->type != base);
1038 if (debug)
1039 VG_(printf)(" typedef %p \"%s\"\n", sym->type, tname);
1040 VG_(st_setname)(sym->type, tname);
1041 VG_(st_setname)(base, tname);
1042 }
1043 }
1044 *namep = ty;
1045
1046 switch(kind) {
1047 case N_STSYM:
1048 case N_LCSYM:
1049 sym->kind = SyStatic;
mueller5ed88f22004-01-06 16:02:29 +00001050 sym->u.addr = si->offset + (Addr)val;
jsgfcb1d1c02003-10-14 21:55:10 +00001051 break;
1052
1053 case N_PSYM:
1054 sym->kind = SyEBPrel; /* +ve offset off EBP (erk, or ESP if no frame pointer) */
mueller5ed88f22004-01-06 16:02:29 +00001055 sym->u.offset = val;
jsgfcb1d1c02003-10-14 21:55:10 +00001056 break;
1057
1058 case N_LSYM:
1059 if (val < 0)
1060 sym->kind = SyEBPrel; /* -ve off EBP when there's a frame pointer */
1061 else
1062 sym->kind = SyESPrel; /* +ve off ESP when there's no frame pointer */
mueller5ed88f22004-01-06 16:02:29 +00001063 sym->u.offset = val;
jsgfcb1d1c02003-10-14 21:55:10 +00001064 break;
1065
1066 case N_RSYM:
1067 sym->kind = SyReg;
mueller5ed88f22004-01-06 16:02:29 +00001068 sym->u.regno = val;
jsgfcb1d1c02003-10-14 21:55:10 +00001069 break;
1070
1071 case N_GSYM:
1072 sym->kind = SyGlobal;
mueller5ed88f22004-01-06 16:02:29 +00001073 sym->u.addr = 0; /* XXX should really look up global address */
jsgfcb1d1c02003-10-14 21:55:10 +00001074 break;
1075
1076 default:
1077 VG_(core_panic)("bad sym kind");
1078 }
1079
1080 if (debug)
1081 VG_(printf)(" %s = type=%p\n", (isStruct || isTypedef) ? "skipping" : "adding", sym->type);
1082
1083 if (isStruct || isTypedef) {
1084 return True; /* skip */
1085 } else {
1086 sym->name = VG_(addStr)(si, name, len);
1087 return False; /* don't skip */
1088 }
1089}
1090
1091/* list of unbound symbols for next scope */
1092struct symlist {
1093 Sym sym;
1094 struct symlist *next;
1095};
1096
1097/* XXX TODO: make sure added syms are unique. A lot of syms added to
1098 the global scope are not. On the other hand, skipping type
1099 definitions helps a lot. */
1100static Scope *addSymsToScope(Scope *sc, struct symlist *list, Int nsyms, Scope *outer)
1101{
1102 static const Bool debug = False;
1103 Int j;
1104 struct symlist *n;
1105 Int base;
1106
1107 if (sc == NULL) {
1108 sc = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*sc));
1109 sc->syms = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*sc->syms) * nsyms);
1110 sc->nsyms = nsyms;
1111 base = 0;
1112 sc->outer = outer;
1113 if (outer == NULL)
1114 sc->depth = 0;
1115 else
1116 sc->depth = outer->depth+1;
1117 } else {
1118 Sym *s = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*s) * (sc->nsyms + nsyms));
1119
1120 VG_(memcpy)(s, sc->syms, sc->nsyms * sizeof(*s));
1121 VG_(arena_free)(VG_AR_SYMTAB, sc->syms);
1122 sc->syms = s;
1123 base = sc->nsyms;
1124 sc->nsyms += nsyms;
1125 }
1126
1127 /* bind any unbound syms to new scope */
1128 for(j = 0; j < nsyms; j++, list = n) {
1129 if (debug)
1130 VG_(printf)(" adding (%p) %s to scope %p depth %d\n",
1131 list->sym.name, list->sym.name, sc, sc->depth);
1132 n = list->next;
1133 sc->syms[base+j] = list->sym;
1134 VG_(arena_free)(VG_AR_SYMTAB, list);
1135 }
1136 vg_assert(list == NULL);
1137
1138 return sc;
1139}
1140
1141/* Read stabs-format debug info. This is all rather horrible because
1142 stabs is a underspecified, kludgy hack.
1143*/
1144void VG_(read_debuginfo_stabs) ( SegInfo* si,
1145 UChar* stabC, Int stab_sz,
1146 UChar* stabstr, Int stabstr_sz )
1147{
1148 static const Bool debug = False;
1149 Int i;
1150 Int n_stab_entries;
1151 struct nlist* stab = (struct nlist*)stabC;
1152 UChar *next_stabstr = NULL;
1153 /* state for various things */
1154 struct {
1155 Addr start; /* start address */
1156 Addr end; /* end address */
1157 Char *name; /* name */
1158 Char *filename; /* source file name */
1159 Int line; /* first line */
1160 } func = { 0, 0, NULL, NULL, -1 };
1161 struct {
1162 Char *name;
1163 Bool same;
1164 } file = { NULL, True };
1165 struct {
1166 Int prev; /* prev line */
1167 Int no; /* current line */
1168 Int ovf; /* line wrap */
1169 Addr addr; /* start of this line */
1170 Bool first; /* first line in function */
1171 Bool jump; /* was a jump from prev line (inline?) */
1172 } line = { 0, 0, 0, 0, False };
1173 struct {
1174 Scope *scope; /* current scope */
1175 struct symlist *symlist; /* unbound symbols */
1176 Int nsyms; /* number of unbound scopes */
1177 Addr addr; /* start of range */
1178 Int depth;
1179 } scope = { NULL, NULL, 0, 0 };
1180 Scope *global;
1181 Int fileidx = 0;
1182 StabTypeTab *tab;
1183
1184 if (si->stab_typetab == NULL) {
1185 si->stab_typetab = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(StabTypeTab));
1186 VG_(memset)(si->stab_typetab, 0, sizeof(StabTypeTab));
1187 }
1188 tab = si->stab_typetab;
1189
1190 /* Ok. It all looks plausible. Go on and read debug data.
1191 stab kinds: 100 N_SO a source file name
1192 68 N_SLINE a source line number
1193 36 N_FUN start of a function
1194
1195 In this loop, we maintain a current file name, updated as
1196 N_SO/N_SOLs appear, and a current function base address,
1197 updated as N_FUNs appear. Based on that, address ranges for
1198 N_SLINEs are calculated, and stuffed into the line info table.
1199
1200 Finding the instruction address range covered by an N_SLINE is
1201 complicated; see the N_SLINE case below.
1202 */
1203 file.name = VG_(addStr)(si,"???", -1);
1204
1205 n_stab_entries = stab_sz/(int)sizeof(struct nlist);
1206
1207 /* empty initial file-wide scope */
1208 global = addSymsToScope(NULL, NULL, 0, NULL);
1209 scope.scope = global;
1210
1211 for (i = 0; i < n_stab_entries; i++) {
1212 const struct nlist *st = &stab[i];
1213 Char *no_fn_name = "???";
1214 Char *string;
1215
1216 if (debug && 1) {
1217 VG_(printf) ( "%2d type=%d othr=%d desc=%d value=0x%x strx=%d %s\n", i,
1218 st->n_type, st->n_other, st->n_desc,
1219 (int)st->n_value,
1220 (int)st->n_un.n_strx,
1221 stabstr + st->n_un.n_strx );
1222 }
1223
1224 /* handle continued string stabs */
1225 {
1226 static const Bool contdebug = False;
1227 Int buflen = 0;
1228 Int idx = 0;
1229 Char *buf = NULL;
1230 Int len;
1231 Bool continuing = False;
1232 UInt stringidx;
1233
1234 stringidx = st->n_un.n_strx;
1235 string = stabstr + stringidx;
1236 len = VG_(strlen)(string);
1237
1238 while(string && len > 0 && (continuing || string[len-1] == '\\')) {
1239 /* Gak, we have a continuation. Skip forward through
1240 subsequent stabs to gather all the parts of the
1241 continuation. Increment i, but keep st pointing at
1242 current stab. */
1243
1244 continuing = string[len-1] == '\\';
1245
1246 /* remove trailing \ */
1247 while(string[len-1] == '\\' && len > 0)
1248 len--;
1249
1250 if (contdebug)
1251 VG_(printf)("found extension string: \"%s\" len=%d(%c) idx=%d buflen=%d\n",
1252 string, len, string[len-1], idx, buflen);
1253
1254 /* XXX this is silly. The si->strtab should have a way of
1255 appending to the last added string... */
1256 if ((idx + len) >= buflen) {
1257 Char *n;
1258
1259 if (buflen == 0)
1260 buflen = 16;
1261 while((idx + len) >= buflen)
1262 buflen *= 2;
1263 n = VG_(arena_malloc)(VG_AR_SYMTAB, buflen);
1264 VG_(memcpy)(n, buf, idx);
1265
1266 if (buf != NULL)
1267 VG_(arena_free)(VG_AR_SYMTAB, buf);
1268 buf = n;
1269 }
1270
1271 VG_(memcpy)(&buf[idx], string, len);
1272 idx += len;
1273 if (contdebug) {
1274 buf[idx] = '\0';
1275 VG_(printf)("working buf=\"%s\"\n", buf);
1276 }
1277
1278 i++;
1279 if (i >= n_stab_entries)
1280 break;
1281
1282 if (stab[i].n_un.n_strx) {
1283 string = stabstr + stab[i].n_un.n_strx;
1284 len = VG_(strlen)(string);
1285 } else {
1286 string = NULL;
1287 len = 0;
1288 }
1289 }
1290
1291 if (buf != NULL) {
1292 i--; /* overstepped */
1293 string = VG_(addStr)(si, buf, idx);
1294 VG_(arena_free)(VG_AR_SYMTAB, buf);
1295 if (contdebug)
1296 VG_(printf)("made composite: \"%s\"\n", string);
1297 }
1298 }
1299
1300 switch(st->n_type) {
1301 case N_UNDEF:
1302 /* new string table base */
1303 if (next_stabstr != NULL) {
1304 stabstr_sz -= next_stabstr - stabstr;
1305 stabstr = next_stabstr;
1306 if (stabstr_sz <= 0) {
1307 VG_(printf)(" @@ bad stabstr size %d\n", stabstr_sz);
1308 return;
1309 }
1310 }
1311 next_stabstr = stabstr + st->n_value;
1312 break;
1313
1314 case N_BINCL: {
1315 fileidx++;
1316 addHeader(tab, stabstr + st->n_un.n_strx, st->n_value, fileidx);
1317
1318 if (debug)
1319 VG_(printf)("BINCL: pushed %s fileidx=%d\n",
1320 stabstr + st->n_un.n_strx, fileidx);
1321 break;
1322 }
1323
1324 case N_EINCL:
1325 break;
1326
1327 case N_EXCL:
1328 ++fileidx;
1329
1330 addFileAlias(tab, stabstr + st->n_un.n_strx, st->n_value, fileidx);
1331
1332 if (debug) {
1333 VG_(printf)("reference to excluded include file %s; fileidx=%d\n",
1334 stabstr + st->n_un.n_strx, fileidx);
1335 }
1336 break;
1337
1338 case N_SOL: /* sub-source (include) file */
1339 if (line.ovf != 0)
1340 VG_(message)(Vg_UserMsg,
1341 "Warning: file %s is very big (> 65535 lines) "
1342 "Line numbers and annotation for this file might "
1343 "be wrong. Sorry",
1344 file.name);
1345 /* FALLTHROUGH */
1346
1347 case N_SO: { /* new source file */
1348 UChar *nm = string;
1349 UInt len = VG_(strlen)(nm);
1350 Addr addr = func.start + st->n_value;
1351
1352 if (line.addr != 0) {
1353 /* finish off previous line */
1354 VG_(addLineInfo)(si, file.name, line.addr,
1355 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
1356 }
1357
1358 /* reset line state */
1359 line.ovf = 0;
1360 line.addr = 0;
1361 line.prev = 0;
1362 line.no = 0;
1363 line.jump = True;
1364
1365 if (len > 0 && nm[len-1] != '/') {
1366 file.name = VG_(addStr)(si, nm, -1);
1367 if (debug)
1368 VG_(printf)("new source: %s\n", file.name);
1369 if (st->n_type == N_SO) {
1370 fileidx = 0;
1371 clearStabFiles(tab);
1372 }
1373 } else if (len == 0)
1374 file.name = VG_(addStr)(si, "?1\0", -1);
1375
1376 if (func.start != 0)
1377 line.jump = True;
1378 break;
1379 }
1380
1381 case N_SLINE: { /* line info */
1382 Addr addr = func.start + st->n_value;
1383
1384 if (line.addr != 0) {
1385 /* there was a previous */
1386 VG_(addLineInfo)(si, file.name, line.addr,
1387 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
1388 }
1389
1390 line.addr = addr;
1391 line.prev = line.no;
1392 line.no = (Int)((UShort)st->n_desc);
1393
1394 if (line.prev > line.no + OVERFLOW_DIFFERENCE && file.same) {
1395 VG_(message)(Vg_DebugMsg,
1396 "Line number overflow detected (%d --> %d) in %s",
1397 line.prev, line.no, file.name);
1398 line.ovf++;
1399 }
1400 file.same = True;
1401
1402 /* This is pretty horrible. If this is the first line of
1403 the function, then bind any unbound symbols to the arg
1404 scope, since they're probably arguments. */
1405 if (line.first) {
1406 line.first = False;
1407
1408 if (scope.nsyms != 0) {
1409 addSymsToScope(scope.scope, scope.symlist, scope.nsyms, NULL);
1410 scope.symlist = NULL;
1411 scope.nsyms = 0;
1412 }
1413
1414 /* remember first line of function */
1415 if (func.start != 0) {
1416 func.filename = file.name;
1417 func.line = line.no;
1418 }
1419 } else if (func.start != 0 && (line.no < func.line || func.filename != file.name)) {
1420 /* If we're suddenly in code before the function starts
1421 or in a different file, then it seems like its
1422 probably some inlined code. Should do something
1423 useful with this information. */
1424 //VG_(printf)("possible inline?\n");
1425 line.jump = True;
1426 }
1427 break;
1428 }
1429
1430 case N_FUN: { /* function start/end */
1431 Addr addr = 0; /* end address for prev line/scope */
1432 Bool newfunc = False;
1433
1434 if (scope.nsyms != 0) {
1435 /* clean up any unbound symbols */
1436 addSymsToScope(scope.scope, scope.symlist, scope.nsyms, NULL);
1437 scope.symlist = NULL;
1438 scope.nsyms = 0;
1439 }
1440
1441 /* if this the end of the function or we haven't
1442 previously finished the previous function... */
1443 if (*string == '\0' || func.start != 0) {
1444 /* end of function */
1445 newfunc = False;
1446 line.first = False;
1447
1448 /* end line at end of function */
1449 addr = func.start + st->n_value;
1450
1451 if (debug)
1452 VG_(printf)("ending func %s at %p\n", func.name, addr);
1453
1454 /* now between functions */
1455 func.name = no_fn_name;
1456 func.start = 0;
1457
1458 if (scope.addr != 0) {
1459 /* finish any previous scope range */
1460 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1461 }
1462
1463 /* tidy up arg scope */
1464 /* XXX LEAK: free scope if it or any of its inner scopes was
1465 never added to a scope range */
1466
1467 if (scope.scope->depth == 0) {
1468 VG_(message)(Vg_UserMsg,
1469 "It seems there's more scopes closed than opened...\n");
1470 break;
1471 }
1472
1473 scope.scope = scope.scope->outer;
1474 scope.addr = addr;
1475 scope.addr = 0;
1476 }
1477
1478 if (*string != '\0') {
1479 /* new function */
1480 newfunc = True;
1481 line.first = True;
1482
1483 /* line ends at start of next function */
1484 addr = si->offset + st->n_value;
1485
1486 func.start = addr;
1487 func.name = string;
1488
1489 if (debug)
1490 VG_(printf)("\nnew func %s at %p\n", func.name, func.start);
1491
1492 }
1493
1494 if (line.addr) {
1495 VG_(addLineInfo)(si, file.name, line.addr,
1496 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
1497 line.addr = 0;
1498 }
1499
1500 if (scope.addr) {
1501 /* finish any previous scope range */
1502 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1503 }
1504
1505 if (newfunc) {
1506 /* make little wrapper scope for args */
1507 Scope *sc;
1508 if (scope.addr) {
1509 /* finish any previous scope range */
1510 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1511 }
1512
1513 sc = addSymsToScope(NULL, scope.symlist, scope.nsyms, scope.scope);
1514 scope.scope = sc;
1515 scope.nsyms = 0;
1516 scope.symlist = NULL;
1517 scope.addr = addr;
1518 }
1519 break;
1520 }
1521
1522 case N_LBRAC: {
1523 /* open new scope */
1524 Scope *sc;
1525 Addr addr = func.start + st->n_value;
1526
1527 if (scope.addr) {
1528 /* end previous range */
1529 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1530 }
1531
1532 scope.addr = addr;
1533
1534 if (debug) {
1535 static const Char indent[]=
1536 " "
1537 " ";
1538 Int idx;
1539
1540 idx = sizeof(indent)-1 - (scope.depth * 2);
1541 scope.depth++;
1542 VG_(printf)("%s{\n", &indent[idx >= 0 ? idx : 0]);
1543 }
1544 /* add unbound syms to scope */
1545 sc = addSymsToScope(NULL, scope.symlist, scope.nsyms, scope.scope);
1546 scope.scope = sc;
1547 scope.nsyms = 0;
1548 scope.symlist = NULL;
1549
1550 break;
1551 }
1552
1553 case N_RBRAC: {
1554 /* close scope */
1555 Addr addr = func.start + st->n_value;
1556
1557 if (scope.nsyms != 0) {
1558 /* If there's any unbound symbols, tidy them up */
1559 addSymsToScope(scope.scope, scope.symlist, scope.nsyms, NULL);
1560 scope.symlist = NULL;
1561 scope.nsyms = 0;
1562 }
1563
1564 vg_assert(scope.addr != 0);
1565 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1566
1567 /* XXX LEAK: free scope if it or any of its inner scopes was
1568 never added to a scope range */
1569
1570 if (scope.scope->depth == 0) {
1571 /* complain */
1572 VG_(message)(Vg_UserMsg, "It seems there's more scopes closed than opened...\n");
1573 break;
1574 }
1575
1576 scope.scope = scope.scope->outer;
1577 scope.addr = addr;
1578 if (debug) {
1579 static const Char indent[]=
1580 " "
1581 " ";
1582 Int idx;
1583
1584 scope.depth--;
1585 idx = sizeof(indent)-1 - (scope.depth * 2);
1586 VG_(printf)("%s}\n", &indent[idx >= 0 ? idx : 0]);
1587 }
1588
1589 break;
1590 }
1591
1592 case N_GSYM: /* global variable */
1593 case N_STSYM: /* static in data segment */
1594 case N_LCSYM: /* static in bss segment */
1595 case N_PSYM: /* function parameter */
1596 case N_LSYM: /* stack variable */
1597 case N_RSYM: { /* register variable */
1598 Char *cp = string;
1599 Int val = st->n_value;
1600
1601 /* a single string can have multiple definitions nested in it */
1602 while(*cp != '\0') {
1603 struct symlist *s = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*s));
1604
1605 if (initSym(si, &s->sym, st->n_type, &cp, val)) {
1606 VG_(arena_free)(VG_AR_SYMTAB, s); /* not interesting */
1607 } else {
1608 s->next = scope.symlist;
1609 scope.symlist = s;
1610 scope.nsyms++;
1611 }
1612 switch(*cp) {
1613 case '\0': /* all done */
1614 break;
1615
1616 case '0' ... '9': /* symbol */
1617 case 'A' ... 'Z':
1618 case 'a' ... 'z':
1619 case '_':
1620 break;
1621
1622 case ' ': case ':': /* nameless type */
1623 break;
1624
1625 default:
1626 VG_(printf)(" @@ unlikely looking definition in unparsed remains \"%s\"\n", cp);
1627 break;
1628 }
1629 }
1630 break;
1631 }
1632 }
1633 }
1634
1635 if (scope.nsyms != 0)
1636 addSymsToScope(scope.scope, scope.symlist, scope.nsyms, NULL);
1637}
njn4bbdc972003-10-16 10:10:55 +00001638
1639/*--------------------------------------------------------------------*/
1640/*--- end vg_symtab_stabs.c ---*/
1641/*--------------------------------------------------------------------*/