blob: 9171f37f8d46c5a2797602c2b30ce238ca8f65d9 [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
njnda388f42005-03-26 16:10:49 +00001031 /* First first ':' */
thughes4aa03c42004-11-12 23:16:31 +00001032 ty = VG_(strchr)(name, ':');
njnda388f42005-03-26 16:10:49 +00001033
1034 /* Skip '::' */
1035 while (ty && ty[1] == ':')
1036 ty = VG_(strchr)(ty + 2, ':');
1037
1038 if (ty == NULL) {
1039 /* there was no ':' */
1040 *namep += VG_(strlen)(name);
1041 return True; /* skip */
1042 }
jsgfcb1d1c02003-10-14 21:55:10 +00001043
1044 len = ty - name;
1045
1046 if (debug) {
1047 Char buf[len+1];
1048 VG_(strncpy_safely)(buf, name, len+1);
1049 VG_(printf)("\ninitSym name=\"%s\" type=%s\n", buf, ty+1);
1050 }
1051
1052 if (*ty != ':') {
1053 /* no type info */
1054 sym->type = VG_(st_mkvoid)(NULL);
1055 } else {
1056 ty++; /* skip ':' */
1057
1058 /* chew through an initial sequence of
1059 type descriptor type describers */
1060 for(;;) {
1061 switch(*ty) {
1062 case 'a': case 'b': case 'c': case 'C':
1063 case 'd': case 'D': case 'f': case 'F':
1064 case 'G': case 'i': case 'I': case 'J':
1065 case 'L': case 'm': case 'p': case 'P':
1066 case 'Q': case 'R': case 'r': case 'S':
1067 case 's': case 'v': case 'V': case 'x':
1068 case 'X':
1069 break;
1070
1071 case 'T': /* struct/union/enum */
1072 isStruct = True;
1073 break;
1074
1075 case 't': /* typedef handled within stabtype_parser */
1076 isTypedef = True;
1077 /* FALLTHROUGH */
1078 case '(': case '-': case '0' ... '9': /* type reference */
1079 default:
1080 goto out;
1081 }
1082 ty++;
1083 }
1084
1085 out:
1086 sym->type = stabtype_parser(si, NULL, &ty);
1087 base = VG_(st_basetype)(sym->type, False);
jsgfcb1d1c02003-10-14 21:55:10 +00001088 if (isStruct && (VG_(st_isstruct)(base) || VG_(st_isunion)(base))) {
1089 Char *sname = VG_(addStr)(si, name, len);
1090 structDef(si->stab_typetab, base, VG_(st_isstruct)(base), sname);
1091 }
1092
1093 if (isTypedef) {
1094 Char *tname = VG_(addStr)(si, name, len);
1095 vg_assert(sym->type != base);
1096 if (debug)
1097 VG_(printf)(" typedef %p \"%s\"\n", sym->type, tname);
1098 VG_(st_setname)(sym->type, tname);
1099 VG_(st_setname)(base, tname);
1100 }
1101 }
1102 *namep = ty;
1103
1104 switch(kind) {
1105 case N_STSYM:
1106 case N_LCSYM:
1107 sym->kind = SyStatic;
mueller5ed88f22004-01-06 16:02:29 +00001108 sym->u.addr = si->offset + (Addr)val;
jsgfcb1d1c02003-10-14 21:55:10 +00001109 break;
1110
1111 case N_PSYM:
1112 sym->kind = SyEBPrel; /* +ve offset off EBP (erk, or ESP if no frame pointer) */
mueller5ed88f22004-01-06 16:02:29 +00001113 sym->u.offset = val;
jsgfcb1d1c02003-10-14 21:55:10 +00001114 break;
1115
1116 case N_LSYM:
1117 if (val < 0)
1118 sym->kind = SyEBPrel; /* -ve off EBP when there's a frame pointer */
1119 else
1120 sym->kind = SyESPrel; /* +ve off ESP when there's no frame pointer */
mueller5ed88f22004-01-06 16:02:29 +00001121 sym->u.offset = val;
jsgfcb1d1c02003-10-14 21:55:10 +00001122 break;
1123
1124 case N_RSYM:
1125 sym->kind = SyReg;
mueller5ed88f22004-01-06 16:02:29 +00001126 sym->u.regno = val;
jsgfcb1d1c02003-10-14 21:55:10 +00001127 break;
1128
1129 case N_GSYM:
1130 sym->kind = SyGlobal;
mueller5ed88f22004-01-06 16:02:29 +00001131 sym->u.addr = 0; /* XXX should really look up global address */
jsgfcb1d1c02003-10-14 21:55:10 +00001132 break;
1133
1134 default:
1135 VG_(core_panic)("bad sym kind");
1136 }
1137
1138 if (debug)
1139 VG_(printf)(" %s = type=%p\n", (isStruct || isTypedef) ? "skipping" : "adding", sym->type);
1140
1141 if (isStruct || isTypedef) {
1142 return True; /* skip */
1143 } else {
1144 sym->name = VG_(addStr)(si, name, len);
1145 return False; /* don't skip */
1146 }
1147}
1148
1149/* list of unbound symbols for next scope */
1150struct symlist {
1151 Sym sym;
1152 struct symlist *next;
1153};
1154
1155/* XXX TODO: make sure added syms are unique. A lot of syms added to
1156 the global scope are not. On the other hand, skipping type
1157 definitions helps a lot. */
1158static Scope *addSymsToScope(Scope *sc, struct symlist *list, Int nsyms, Scope *outer)
1159{
thughes8c34d522004-10-07 08:22:59 +00001160 static const Bool debug = False || stabs_debug;
jsgfcb1d1c02003-10-14 21:55:10 +00001161 Int j;
1162 struct symlist *n;
1163 Int base;
1164
1165 if (sc == NULL) {
1166 sc = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*sc));
1167 sc->syms = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*sc->syms) * nsyms);
1168 sc->nsyms = nsyms;
1169 base = 0;
1170 sc->outer = outer;
1171 if (outer == NULL)
1172 sc->depth = 0;
1173 else
1174 sc->depth = outer->depth+1;
1175 } else {
1176 Sym *s = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*s) * (sc->nsyms + nsyms));
1177
1178 VG_(memcpy)(s, sc->syms, sc->nsyms * sizeof(*s));
1179 VG_(arena_free)(VG_AR_SYMTAB, sc->syms);
1180 sc->syms = s;
1181 base = sc->nsyms;
1182 sc->nsyms += nsyms;
1183 }
1184
1185 /* bind any unbound syms to new scope */
1186 for(j = 0; j < nsyms; j++, list = n) {
1187 if (debug)
1188 VG_(printf)(" adding (%p) %s to scope %p depth %d\n",
1189 list->sym.name, list->sym.name, sc, sc->depth);
1190 n = list->next;
1191 sc->syms[base+j] = list->sym;
1192 VG_(arena_free)(VG_AR_SYMTAB, list);
1193 }
1194 vg_assert(list == NULL);
1195
1196 return sc;
1197}
1198
1199/* Read stabs-format debug info. This is all rather horrible because
1200 stabs is a underspecified, kludgy hack.
1201*/
1202void VG_(read_debuginfo_stabs) ( SegInfo* si,
1203 UChar* stabC, Int stab_sz,
1204 UChar* stabstr, Int stabstr_sz )
1205{
thughes8c34d522004-10-07 08:22:59 +00001206 static const Bool debug = False || stabs_debug;
jsgfcb1d1c02003-10-14 21:55:10 +00001207 Int i;
1208 Int n_stab_entries;
1209 struct nlist* stab = (struct nlist*)stabC;
1210 UChar *next_stabstr = NULL;
1211 /* state for various things */
1212 struct {
1213 Addr start; /* start address */
1214 Addr end; /* end address */
1215 Char *name; /* name */
1216 Char *filename; /* source file name */
1217 Int line; /* first line */
1218 } func = { 0, 0, NULL, NULL, -1 };
1219 struct {
1220 Char *name;
1221 Bool same;
1222 } file = { NULL, True };
1223 struct {
1224 Int prev; /* prev line */
1225 Int no; /* current line */
1226 Int ovf; /* line wrap */
1227 Addr addr; /* start of this line */
1228 Bool first; /* first line in function */
1229 Bool jump; /* was a jump from prev line (inline?) */
1230 } line = { 0, 0, 0, 0, False };
1231 struct {
1232 Scope *scope; /* current scope */
1233 struct symlist *symlist; /* unbound symbols */
1234 Int nsyms; /* number of unbound scopes */
1235 Addr addr; /* start of range */
1236 Int depth;
1237 } scope = { NULL, NULL, 0, 0 };
1238 Scope *global;
1239 Int fileidx = 0;
1240 StabTypeTab *tab;
1241
1242 if (si->stab_typetab == NULL) {
1243 si->stab_typetab = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(StabTypeTab));
1244 VG_(memset)(si->stab_typetab, 0, sizeof(StabTypeTab));
1245 }
1246 tab = si->stab_typetab;
1247
1248 /* Ok. It all looks plausible. Go on and read debug data.
1249 stab kinds: 100 N_SO a source file name
1250 68 N_SLINE a source line number
1251 36 N_FUN start of a function
1252
1253 In this loop, we maintain a current file name, updated as
1254 N_SO/N_SOLs appear, and a current function base address,
1255 updated as N_FUNs appear. Based on that, address ranges for
1256 N_SLINEs are calculated, and stuffed into the line info table.
1257
1258 Finding the instruction address range covered by an N_SLINE is
1259 complicated; see the N_SLINE case below.
1260 */
1261 file.name = VG_(addStr)(si,"???", -1);
1262
1263 n_stab_entries = stab_sz/(int)sizeof(struct nlist);
1264
1265 /* empty initial file-wide scope */
1266 global = addSymsToScope(NULL, NULL, 0, NULL);
1267 scope.scope = global;
1268
1269 for (i = 0; i < n_stab_entries; i++) {
1270 const struct nlist *st = &stab[i];
1271 Char *no_fn_name = "???";
1272 Char *string;
1273
1274 if (debug && 1) {
1275 VG_(printf) ( "%2d type=%d othr=%d desc=%d value=0x%x strx=%d %s\n", i,
1276 st->n_type, st->n_other, st->n_desc,
1277 (int)st->n_value,
1278 (int)st->n_un.n_strx,
1279 stabstr + st->n_un.n_strx );
1280 }
1281
1282 /* handle continued string stabs */
1283 {
thughes8c34d522004-10-07 08:22:59 +00001284 static const Bool contdebug = False || stabs_debug;
jsgfcb1d1c02003-10-14 21:55:10 +00001285 Int buflen = 0;
1286 Int idx = 0;
1287 Char *buf = NULL;
1288 Int len;
1289 Bool continuing = False;
1290 UInt stringidx;
1291
1292 stringidx = st->n_un.n_strx;
1293 string = stabstr + stringidx;
1294 len = VG_(strlen)(string);
1295
1296 while(string && len > 0 && (continuing || string[len-1] == '\\')) {
1297 /* Gak, we have a continuation. Skip forward through
1298 subsequent stabs to gather all the parts of the
1299 continuation. Increment i, but keep st pointing at
1300 current stab. */
1301
1302 continuing = string[len-1] == '\\';
1303
1304 /* remove trailing \ */
1305 while(string[len-1] == '\\' && len > 0)
1306 len--;
1307
1308 if (contdebug)
1309 VG_(printf)("found extension string: \"%s\" len=%d(%c) idx=%d buflen=%d\n",
1310 string, len, string[len-1], idx, buflen);
1311
1312 /* XXX this is silly. The si->strtab should have a way of
1313 appending to the last added string... */
1314 if ((idx + len) >= buflen) {
1315 Char *n;
1316
1317 if (buflen == 0)
1318 buflen = 16;
1319 while((idx + len) >= buflen)
1320 buflen *= 2;
1321 n = VG_(arena_malloc)(VG_AR_SYMTAB, buflen);
1322 VG_(memcpy)(n, buf, idx);
1323
1324 if (buf != NULL)
1325 VG_(arena_free)(VG_AR_SYMTAB, buf);
1326 buf = n;
1327 }
1328
1329 VG_(memcpy)(&buf[idx], string, len);
1330 idx += len;
1331 if (contdebug) {
1332 buf[idx] = '\0';
1333 VG_(printf)("working buf=\"%s\"\n", buf);
1334 }
1335
1336 i++;
1337 if (i >= n_stab_entries)
1338 break;
1339
1340 if (stab[i].n_un.n_strx) {
1341 string = stabstr + stab[i].n_un.n_strx;
1342 len = VG_(strlen)(string);
1343 } else {
1344 string = NULL;
1345 len = 0;
1346 }
1347 }
1348
1349 if (buf != NULL) {
1350 i--; /* overstepped */
1351 string = VG_(addStr)(si, buf, idx);
1352 VG_(arena_free)(VG_AR_SYMTAB, buf);
1353 if (contdebug)
1354 VG_(printf)("made composite: \"%s\"\n", string);
1355 }
1356 }
1357
1358 switch(st->n_type) {
1359 case N_UNDEF:
1360 /* new string table base */
1361 if (next_stabstr != NULL) {
1362 stabstr_sz -= next_stabstr - stabstr;
1363 stabstr = next_stabstr;
1364 if (stabstr_sz <= 0) {
1365 VG_(printf)(" @@ bad stabstr size %d\n", stabstr_sz);
1366 return;
1367 }
1368 }
1369 next_stabstr = stabstr + st->n_value;
1370 break;
1371
1372 case N_BINCL: {
1373 fileidx++;
1374 addHeader(tab, stabstr + st->n_un.n_strx, st->n_value, fileidx);
1375
1376 if (debug)
1377 VG_(printf)("BINCL: pushed %s fileidx=%d\n",
1378 stabstr + st->n_un.n_strx, fileidx);
1379 break;
1380 }
1381
1382 case N_EINCL:
1383 break;
1384
1385 case N_EXCL:
1386 ++fileidx;
1387
1388 addFileAlias(tab, stabstr + st->n_un.n_strx, st->n_value, fileidx);
1389
1390 if (debug) {
1391 VG_(printf)("reference to excluded include file %s; fileidx=%d\n",
1392 stabstr + st->n_un.n_strx, fileidx);
1393 }
1394 break;
1395
1396 case N_SOL: /* sub-source (include) file */
1397 if (line.ovf != 0)
1398 VG_(message)(Vg_UserMsg,
1399 "Warning: file %s is very big (> 65535 lines) "
1400 "Line numbers and annotation for this file might "
1401 "be wrong. Sorry",
1402 file.name);
1403 /* FALLTHROUGH */
1404
1405 case N_SO: { /* new source file */
1406 UChar *nm = string;
1407 UInt len = VG_(strlen)(nm);
1408 Addr addr = func.start + st->n_value;
1409
1410 if (line.addr != 0) {
1411 /* finish off previous line */
1412 VG_(addLineInfo)(si, file.name, line.addr,
1413 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
1414 }
1415
1416 /* reset line state */
1417 line.ovf = 0;
1418 line.addr = 0;
1419 line.prev = 0;
1420 line.no = 0;
1421 line.jump = True;
1422
1423 if (len > 0 && nm[len-1] != '/') {
1424 file.name = VG_(addStr)(si, nm, -1);
1425 if (debug)
1426 VG_(printf)("new source: %s\n", file.name);
1427 if (st->n_type == N_SO) {
1428 fileidx = 0;
1429 clearStabFiles(tab);
1430 }
1431 } else if (len == 0)
1432 file.name = VG_(addStr)(si, "?1\0", -1);
1433
1434 if (func.start != 0)
1435 line.jump = True;
1436 break;
1437 }
1438
1439 case N_SLINE: { /* line info */
1440 Addr addr = func.start + st->n_value;
1441
1442 if (line.addr != 0) {
1443 /* there was a previous */
1444 VG_(addLineInfo)(si, file.name, line.addr,
1445 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
1446 }
1447
1448 line.addr = addr;
1449 line.prev = line.no;
1450 line.no = (Int)((UShort)st->n_desc);
1451
1452 if (line.prev > line.no + OVERFLOW_DIFFERENCE && file.same) {
1453 VG_(message)(Vg_DebugMsg,
1454 "Line number overflow detected (%d --> %d) in %s",
1455 line.prev, line.no, file.name);
1456 line.ovf++;
1457 }
1458 file.same = True;
1459
1460 /* This is pretty horrible. If this is the first line of
1461 the function, then bind any unbound symbols to the arg
1462 scope, since they're probably arguments. */
1463 if (line.first) {
1464 line.first = False;
1465
1466 if (scope.nsyms != 0) {
1467 addSymsToScope(scope.scope, scope.symlist, scope.nsyms, NULL);
1468 scope.symlist = NULL;
1469 scope.nsyms = 0;
1470 }
1471
1472 /* remember first line of function */
1473 if (func.start != 0) {
1474 func.filename = file.name;
1475 func.line = line.no;
1476 }
1477 } else if (func.start != 0 && (line.no < func.line || func.filename != file.name)) {
1478 /* If we're suddenly in code before the function starts
1479 or in a different file, then it seems like its
1480 probably some inlined code. Should do something
1481 useful with this information. */
1482 //VG_(printf)("possible inline?\n");
1483 line.jump = True;
1484 }
1485 break;
1486 }
1487
1488 case N_FUN: { /* function start/end */
1489 Addr addr = 0; /* end address for prev line/scope */
1490 Bool newfunc = False;
1491
1492 if (scope.nsyms != 0) {
1493 /* clean up any unbound symbols */
1494 addSymsToScope(scope.scope, scope.symlist, scope.nsyms, NULL);
1495 scope.symlist = NULL;
1496 scope.nsyms = 0;
1497 }
1498
1499 /* if this the end of the function or we haven't
1500 previously finished the previous function... */
1501 if (*string == '\0' || func.start != 0) {
1502 /* end of function */
1503 newfunc = False;
1504 line.first = False;
1505
1506 /* end line at end of function */
1507 addr = func.start + st->n_value;
1508
1509 if (debug)
1510 VG_(printf)("ending func %s at %p\n", func.name, addr);
1511
1512 /* now between functions */
1513 func.name = no_fn_name;
1514 func.start = 0;
1515
1516 if (scope.addr != 0) {
1517 /* finish any previous scope range */
1518 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1519 }
1520
1521 /* tidy up arg scope */
1522 /* XXX LEAK: free scope if it or any of its inner scopes was
1523 never added to a scope range */
1524
1525 if (scope.scope->depth == 0) {
1526 VG_(message)(Vg_UserMsg,
1527 "It seems there's more scopes closed than opened...\n");
1528 break;
1529 }
1530
1531 scope.scope = scope.scope->outer;
1532 scope.addr = addr;
1533 scope.addr = 0;
1534 }
1535
1536 if (*string != '\0') {
1537 /* new function */
1538 newfunc = True;
1539 line.first = True;
1540
1541 /* line ends at start of next function */
1542 addr = si->offset + st->n_value;
1543
1544 func.start = addr;
1545 func.name = string;
1546
1547 if (debug)
1548 VG_(printf)("\nnew func %s at %p\n", func.name, func.start);
1549
1550 }
1551
1552 if (line.addr) {
1553 VG_(addLineInfo)(si, file.name, line.addr,
1554 addr, line.no + line.ovf * LINENO_OVERFLOW, i);
1555 line.addr = 0;
1556 }
1557
1558 if (scope.addr) {
1559 /* finish any previous scope range */
1560 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1561 }
1562
1563 if (newfunc) {
1564 /* make little wrapper scope for args */
1565 Scope *sc;
1566 if (scope.addr) {
1567 /* finish any previous scope range */
1568 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1569 }
1570
1571 sc = addSymsToScope(NULL, scope.symlist, scope.nsyms, scope.scope);
1572 scope.scope = sc;
1573 scope.nsyms = 0;
1574 scope.symlist = NULL;
1575 scope.addr = addr;
1576 }
1577 break;
1578 }
1579
1580 case N_LBRAC: {
1581 /* open new scope */
1582 Scope *sc;
1583 Addr addr = func.start + st->n_value;
1584
1585 if (scope.addr) {
1586 /* end previous range */
1587 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1588 }
1589
1590 scope.addr = addr;
1591
1592 if (debug) {
1593 static const Char indent[]=
1594 " "
1595 " ";
1596 Int idx;
1597
1598 idx = sizeof(indent)-1 - (scope.depth * 2);
1599 scope.depth++;
1600 VG_(printf)("%s{\n", &indent[idx >= 0 ? idx : 0]);
1601 }
1602 /* add unbound syms to scope */
1603 sc = addSymsToScope(NULL, scope.symlist, scope.nsyms, scope.scope);
1604 scope.scope = sc;
1605 scope.nsyms = 0;
1606 scope.symlist = NULL;
1607
1608 break;
1609 }
1610
1611 case N_RBRAC: {
1612 /* close scope */
1613 Addr addr = func.start + st->n_value;
1614
1615 if (scope.nsyms != 0) {
1616 /* If there's any unbound symbols, tidy them up */
1617 addSymsToScope(scope.scope, scope.symlist, scope.nsyms, NULL);
1618 scope.symlist = NULL;
1619 scope.nsyms = 0;
1620 }
1621
1622 vg_assert(scope.addr != 0);
1623 VG_(addScopeInfo)(si, scope.addr, addr, scope.scope);
1624
1625 /* XXX LEAK: free scope if it or any of its inner scopes was
1626 never added to a scope range */
1627
1628 if (scope.scope->depth == 0) {
1629 /* complain */
1630 VG_(message)(Vg_UserMsg, "It seems there's more scopes closed than opened...\n");
1631 break;
1632 }
1633
1634 scope.scope = scope.scope->outer;
1635 scope.addr = addr;
1636 if (debug) {
1637 static const Char indent[]=
1638 " "
1639 " ";
1640 Int idx;
1641
1642 scope.depth--;
1643 idx = sizeof(indent)-1 - (scope.depth * 2);
1644 VG_(printf)("%s}\n", &indent[idx >= 0 ? idx : 0]);
1645 }
1646
1647 break;
1648 }
1649
1650 case N_GSYM: /* global variable */
1651 case N_STSYM: /* static in data segment */
1652 case N_LCSYM: /* static in bss segment */
1653 case N_PSYM: /* function parameter */
1654 case N_LSYM: /* stack variable */
1655 case N_RSYM: { /* register variable */
1656 Char *cp = string;
1657 Int val = st->n_value;
1658
1659 /* a single string can have multiple definitions nested in it */
1660 while(*cp != '\0') {
1661 struct symlist *s = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*s));
1662
1663 if (initSym(si, &s->sym, st->n_type, &cp, val)) {
1664 VG_(arena_free)(VG_AR_SYMTAB, s); /* not interesting */
1665 } else {
1666 s->next = scope.symlist;
1667 scope.symlist = s;
1668 scope.nsyms++;
1669 }
1670 switch(*cp) {
1671 case '\0': /* all done */
1672 break;
1673
1674 case '0' ... '9': /* symbol */
1675 case 'A' ... 'Z':
1676 case 'a' ... 'z':
1677 case '_':
1678 break;
1679
1680 case ' ': case ':': /* nameless type */
1681 break;
1682
1683 default:
1684 VG_(printf)(" @@ unlikely looking definition in unparsed remains \"%s\"\n", cp);
1685 break;
1686 }
1687 }
1688 break;
1689 }
1690 }
1691 }
1692
1693 if (scope.nsyms != 0)
1694 addSymsToScope(scope.scope, scope.symlist, scope.nsyms, NULL);
1695}
njn4bbdc972003-10-16 10:10:55 +00001696
1697/*--------------------------------------------------------------------*/
nethercote0febe082004-08-04 09:57:31 +00001698/*--- end ---*/
njn4bbdc972003-10-16 10:10:55 +00001699/*--------------------------------------------------------------------*/