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