blob: 4f4b7648e13985be651ca0b6ea5300628f8455fa [file] [log] [blame]
njn4bbdc972003-10-16 10:10:55 +00001/*--------------------------------------------------------------------*/
2/*--- Extract type info from debug info. vg_symtypes.h ---*/
3/*--------------------------------------------------------------------*/
4
jsgfcb1d1c02003-10-14 21:55:10 +00005/*
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_symtypes.h"
32
33typedef enum {
34 TyUnknown, /* unknown type */
35 TyUnresolved, /* unresolved type */
36 TyError, /* error type */
37
38 TyVoid, /* void */
39
40 TyInt, /* integer */
41 TyBool, /* boolean */
42 TyChar, /* character */
43 TyFloat, /* float */
44
45 TyRange, /* type subrange */
46
47 TyEnum, /* enum */
48
49 TyPointer, /* pointer */
50 TyArray, /* array */
51 TyStruct, /* structure/class */
52 TyUnion, /* union */
53
54 TyTypedef /* typedef */
55} TyKind;
56
57static const Char *ppkind(TyKind k)
58{
59 switch(k) {
60#define S(x) case x: return #x
61 S(TyUnknown);
62 S(TyUnresolved);
63 S(TyError);
64 S(TyVoid);
65 S(TyInt);
66 S(TyBool);
67 S(TyChar);
68 S(TyRange);
69 S(TyFloat);
70 S(TyEnum);
71 S(TyPointer);
72 S(TyArray);
73 S(TyStruct);
74 S(TyUnion);
75 S(TyTypedef);
76#undef S
77 default:
78 return "Ty???";
79 }
80}
81
82/* struct/union field */
83typedef struct _StField {
84 UInt offset; /* offset into structure (0 for union) (in bits) */
85 UInt size; /* size (in bits) */
86 SymType *type; /* type of element */
87 Char *name; /* name of element */
88} StField;
89
90/* enum tag */
91typedef struct _EnTag {
92 const Char *name; /* name */
93 UInt val; /* value */
94} EnTag;
95
96struct _SymType {
97 TyKind kind; /* type descriminator */
98 UInt size; /* sizeof(type) */
99 Char *name; /* useful name */
100
101 union {
102 /* TyInt,TyBool,TyChar */
103 struct {
104 Bool issigned; /* signed or not */
105 } t_scalar;
106
107 /* TyFloat */
108 struct {
109 Bool isdouble; /* is double prec */
110 } t_float;
111
112 /* TyRange */
113 struct {
114 Int min;
115 Int max;
116 SymType *type;
117 } t_range;
118
119 /* TyPointer */
120 struct {
121 SymType *type; /* *type */
122 } t_pointer;
123
124 /* TyArray */
125 struct {
126 SymType *idxtype;
127 SymType *type;
128 } t_array;
129
130 /* TyEnum */
131 struct {
132 UInt ntag; /* number of tags */
133 EnTag *tags; /* tags */
134 } t_enum;
135
136 /* TyStruct, TyUnion */
137 struct {
138 UInt nfield; /* number of fields */
139 UInt nfieldalloc; /* number of fields allocated */
140 StField *fields; /* fields */
141 } t_struct;
142
143 /* TyTypedef */
144 struct {
145 SymType *type; /* type */
146 } t_typedef;
147
148 /* TyUnresolved - reference to unresolved type */
149 struct {
150 /* some kind of symtab reference */
151 SymResolver *resolver; /* symtab reader's resolver */
152 void *data; /* data for resolver */
153 } t_unresolved;
mueller5ed88f22004-01-06 16:02:29 +0000154 } u;
jsgfcb1d1c02003-10-14 21:55:10 +0000155};
156
157
158Bool VG_(st_isstruct)(SymType *ty)
159{
160 return ty->kind == TyStruct;
161}
162
163Bool VG_(st_isunion)(SymType *ty)
164{
165 return ty->kind == TyUnion;
166}
167
168Bool VG_(st_isenum)(SymType *ty)
169{
170 return ty->kind == TyEnum;
171}
172
173static inline SymType *alloc(SymType *st)
174{
175 if (st == NULL) {
176 st = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*st));
177 st->kind = TyUnknown;
178 st->name = NULL;
179 }
180
181 return st;
182}
183
184static void resolve(SymType *st)
185{
186 if (st->kind != TyUnresolved)
187 return;
188
mueller5ed88f22004-01-06 16:02:29 +0000189 (*st->u.t_unresolved.resolver)(st, st->u.t_unresolved.data);
jsgfcb1d1c02003-10-14 21:55:10 +0000190
191 if (st->kind == TyUnresolved)
192 st->kind = TyError;
193}
194
195SymType *VG_(st_mkunresolved)(SymType *st, SymResolver *resolver, void *data)
196{
197 st = alloc(st);
198
199 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
200
201 st->kind = TyUnresolved;
202 st->size = 0;
mueller5ed88f22004-01-06 16:02:29 +0000203 st->u.t_unresolved.resolver = resolver;
204 st->u.t_unresolved.data = data;
jsgfcb1d1c02003-10-14 21:55:10 +0000205
206 return st;
207}
208
209void VG_(st_unresolved_setdata)(SymType *st, SymResolver *resolver, void *data)
210{
211 if (st->kind != TyUnresolved)
212 return;
213
mueller5ed88f22004-01-06 16:02:29 +0000214 st->u.t_unresolved.resolver = resolver;
215 st->u.t_unresolved.data = data;
jsgfcb1d1c02003-10-14 21:55:10 +0000216}
217
218Bool VG_(st_isresolved)(SymType *st)
219{
220 return st->kind != TyUnresolved;
221}
222
223void VG_(st_setname)(SymType *st, Char *name)
224{
225 if (st->name != NULL)
226 st->name = name;
227}
228
229SymType *VG_(st_mkvoid)(SymType *st)
230{
231 st = alloc(st);
232
233 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
234
235 st->kind = TyVoid;
236 st->size = 1; /* for address calculations */
237 st->name = "void";
238 return st;
239}
240
241SymType *VG_(st_mkint)(SymType *st, UInt size, Bool isSigned)
242{
243 st = alloc(st);
244
245 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
246
247 st->kind = TyInt;
248 st->size = size;
mueller5ed88f22004-01-06 16:02:29 +0000249 st->u.t_scalar.issigned = isSigned;
jsgfcb1d1c02003-10-14 21:55:10 +0000250
251 return st;
252}
253
254SymType *VG_(st_mkfloat)(SymType *st, UInt size)
255{
256 st = alloc(st);
257
258 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
259
260 st->kind = TyFloat;
261 st->size = size;
mueller5ed88f22004-01-06 16:02:29 +0000262 st->u.t_scalar.issigned = True;
jsgfcb1d1c02003-10-14 21:55:10 +0000263
264 return st;
265}
266
267SymType *VG_(st_mkbool)(SymType *st, UInt size)
268{
269 st = alloc(st);
270
271 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
272
273 st->kind = TyBool;
274 st->size = size;
275
276 return st;
277}
278
279
280SymType *VG_(st_mkpointer)(SymType *st, SymType *ptr)
281{
282 st = alloc(st);
283
284 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
285
286 st->kind = TyPointer;
287 st->size = sizeof(void *);
mueller5ed88f22004-01-06 16:02:29 +0000288 st->u.t_pointer.type = ptr;
jsgfcb1d1c02003-10-14 21:55:10 +0000289
290 return st;
291}
292
293SymType *VG_(st_mkrange)(SymType *st, SymType *ty, Int min, Int max)
294{
295 st = alloc(st);
296
297 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
298
299 st->kind = TyRange;
300 st->size = 0; /* ? */
mueller5ed88f22004-01-06 16:02:29 +0000301 st->u.t_range.type = ty;
302 st->u.t_range.min = min;
303 st->u.t_range.max = max;
jsgfcb1d1c02003-10-14 21:55:10 +0000304
305 return st;
306}
307
308SymType *VG_(st_mkstruct)(SymType *st, UInt size, UInt nfields)
309{
310 st = alloc(st);
311
312 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown || st->kind == TyStruct);
313
mueller5ed88f22004-01-06 16:02:29 +0000314 vg_assert(st->kind != TyStruct || st->u.t_struct.nfield == 0);
jsgfcb1d1c02003-10-14 21:55:10 +0000315
316 st->kind = TyStruct;
317 st->size = size;
mueller5ed88f22004-01-06 16:02:29 +0000318 st->u.t_struct.nfield = 0;
319 st->u.t_struct.nfieldalloc = nfields;
jsgfcb1d1c02003-10-14 21:55:10 +0000320 if (nfields != 0)
mueller5ed88f22004-01-06 16:02:29 +0000321 st->u.t_struct.fields = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(StField) * nfields);
jsgfcb1d1c02003-10-14 21:55:10 +0000322 else
mueller5ed88f22004-01-06 16:02:29 +0000323 st->u.t_struct.fields = NULL;
jsgfcb1d1c02003-10-14 21:55:10 +0000324
325 return st;
326}
327
328SymType *VG_(st_mkunion)(SymType *st, UInt size, UInt nfields)
329{
330 st = alloc(st);
331
332 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown || st->kind == TyUnion);
333
mueller5ed88f22004-01-06 16:02:29 +0000334 vg_assert(st->kind != TyUnion || st->u.t_struct.nfield == 0);
jsgfcb1d1c02003-10-14 21:55:10 +0000335
336 st->kind = TyUnion;
337 st->size = size;
mueller5ed88f22004-01-06 16:02:29 +0000338 st->u.t_struct.nfield = 0;
339 st->u.t_struct.nfieldalloc = nfields;
jsgfcb1d1c02003-10-14 21:55:10 +0000340 if (nfields != 0)
mueller5ed88f22004-01-06 16:02:29 +0000341 st->u.t_struct.fields = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(StField) * nfields);
jsgfcb1d1c02003-10-14 21:55:10 +0000342 else
mueller5ed88f22004-01-06 16:02:29 +0000343 st->u.t_struct.fields = NULL;
jsgfcb1d1c02003-10-14 21:55:10 +0000344
345 return st;
346}
347
348void VG_(st_addfield)(SymType *st, Char *name, SymType *type, UInt off, UInt size)
349{
350 StField *f;
351
352 vg_assert(st->kind == TyStruct || st->kind == TyUnion);
353
mueller5ed88f22004-01-06 16:02:29 +0000354 if (st->u.t_struct.nfieldalloc == st->u.t_struct.nfield) {
jsgfcb1d1c02003-10-14 21:55:10 +0000355 StField *n = VG_(arena_malloc)(VG_AR_SYMTAB,
mueller5ed88f22004-01-06 16:02:29 +0000356 sizeof(StField) * (st->u.t_struct.nfieldalloc + 2));
357 VG_(memcpy)(n, st->u.t_struct.fields, sizeof(*n) * st->u.t_struct.nfield);
358 if (st->u.t_struct.fields != NULL)
359 VG_(arena_free)(VG_AR_SYMTAB, st->u.t_struct.fields);
360 st->u.t_struct.nfieldalloc++;
361 st->u.t_struct.fields = n;
jsgfcb1d1c02003-10-14 21:55:10 +0000362 }
363
mueller5ed88f22004-01-06 16:02:29 +0000364 f = &st->u.t_struct.fields[st->u.t_struct.nfield++];
jsgfcb1d1c02003-10-14 21:55:10 +0000365 f->name = name;
366 f->type = type;
367 f->offset = off;
368 f->size = size;
369}
370
371
372SymType *VG_(st_mkenum)(SymType *st, UInt ntags)
373{
374 st = alloc(st);
375
376 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown || st->kind == TyEnum);
377
378 st->kind = TyEnum;
mueller5ed88f22004-01-06 16:02:29 +0000379 st->u.t_enum.ntag = 0;
380 st->u.t_enum.tags = NULL;
jsgfcb1d1c02003-10-14 21:55:10 +0000381
382 return st;
383}
384
385SymType *VG_(st_mkarray)(SymType *st, SymType *idxtype, SymType *type)
386{
387 st = alloc(st);
388
389 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown);
390
391 st->kind = TyArray;
mueller5ed88f22004-01-06 16:02:29 +0000392 st->u.t_array.type = type;
393 st->u.t_array.idxtype = idxtype;
jsgfcb1d1c02003-10-14 21:55:10 +0000394
395 return st;
396}
397
398SymType *VG_(st_mktypedef)(SymType *st, Char *name, SymType *type)
399{
400 st = alloc(st);
401
thughesb9019d82004-10-07 08:21:38 +0000402 vg_assert(st != type);
jsgfcb1d1c02003-10-14 21:55:10 +0000403 vg_assert(st->kind == TyUnresolved || st->kind == TyUnknown ||
404 st->kind == TyStruct || st->kind == TyUnion ||
405 st->kind == TyTypedef);
406
407 st->kind = TyTypedef;
408 st->name = name;
mueller5ed88f22004-01-06 16:02:29 +0000409 st->u.t_typedef.type = type;
jsgfcb1d1c02003-10-14 21:55:10 +0000410
411 return st;
412}
413
414
415SymType *VG_(st_basetype)(SymType *type, Bool do_resolve)
416{
417 while (type->kind == TyTypedef || (do_resolve && type->kind == TyUnresolved)) {
418 if (do_resolve)
419 resolve(type);
420
421 if (type->kind == TyTypedef)
mueller5ed88f22004-01-06 16:02:29 +0000422 type = type->u.t_typedef.type;
jsgfcb1d1c02003-10-14 21:55:10 +0000423 }
424
425 return type;
426}
427
428UInt VG_(st_sizeof)(SymType *ty)
429{
430 return ty->size;
431}
432
433#ifndef TEST
434/*
435 Hash of visited addresses, so we don't get stuck in loops. It isn't
436 simply enough to keep track of addresses, since we need to interpret
437 the memory according to the type. If a given location has multiple
438 pointers with different types (for example, void * and struct foo *),
439 then we need to look at it under each type.
440*/
441struct visited {
442 Addr a;
443 SymType *ty;
444 struct visited *next;
445};
446
447#define VISIT_HASHSZ 1021
448
449static struct visited *visit_hash[VISIT_HASHSZ];
450
451static inline Bool test_visited(Addr a, SymType *type)
452{
453 struct visited *v;
454 UInt b = (UInt)a % VISIT_HASHSZ;
455 Bool ret = False;
456
457 for(v = visit_hash[b]; v != NULL; v = v->next) {
458 if (v->a == a && v->ty == type) {
459 ret = True;
460 break;
461 }
462 }
463
464 return ret;
465}
466
467static Bool has_visited(Addr a, SymType *type)
468{
469 static const Bool debug = False;
470 Bool ret;
471
472 ret = test_visited(a, type);
473
474 if (!ret) {
475 UInt b = (UInt)a % VISIT_HASHSZ;
476 struct visited * v = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*v));
477
478 v->a = a;
479 v->ty = type;
480 v->next = visit_hash[b];
481 visit_hash[b] = v;
482 }
483
484 if (debug)
485 VG_(printf)("has_visited(a=%p, ty=%p) -> %d\n", a, type, ret);
486
487 return ret;
488}
489
490static void clear_visited(void)
491{
492 UInt i;
493
494 for(i = 0; i < VISIT_HASHSZ; i++) {
495 struct visited *v, *n;
496 for(v = visit_hash[i]; v != NULL; v = n) {
497 n = v->next;
498 VG_(arena_free)(VG_AR_SYMTAB, v);
499 }
500 visit_hash[i] = NULL;
501 }
502}
503
sewardjb5f6f512005-03-10 23:59:00 +0000504static void bprintf(void (*send)(Char, void*), void *send_arg, const Char *fmt, ...)
jsgfcb1d1c02003-10-14 21:55:10 +0000505{
506 va_list vargs;
507
508 va_start(vargs, fmt);
sewardjb5f6f512005-03-10 23:59:00 +0000509 VG_(vprintf)(send, fmt, vargs, send_arg);
jsgfcb1d1c02003-10-14 21:55:10 +0000510 va_end(vargs);
511}
512
513#define SHADOWCHUNK 0 /* no longer have a core allocator */
514
515#if SHADOWCHUNK
516static ShadowChunk *findchunk(Addr a)
517{
518 Bool find(ShadowChunk *sc) {
519 return a >= sc->data && a < (sc->data+sc->size);
520 }
521 return VG_(any_matching_mallocd_ShadowChunks)(find);
522}
523#endif
524
nethercote73b526f2004-10-31 18:48:21 +0000525static struct vki_sigaction sigbus_saved;
526static struct vki_sigaction sigsegv_saved;
527static vki_sigset_t blockmask_saved;
jsgfcb1d1c02003-10-14 21:55:10 +0000528static jmp_buf valid_addr_jmpbuf;
529
530static void valid_addr_handler(int sig)
531{
532 //VG_(printf)("OUCH! %d\n", sig);
533 __builtin_longjmp(valid_addr_jmpbuf, 1);
534}
535
536/* catch badness signals because we're going to be
537 playing around in untrusted memory */
538static void setup_signals(void)
539{
540 Int res;
nethercote73b526f2004-10-31 18:48:21 +0000541 struct vki_sigaction sigbus_new;
542 struct vki_sigaction sigsegv_new;
543 vki_sigset_t unblockmask_new;
jsgfcb1d1c02003-10-14 21:55:10 +0000544
545 /* Temporarily install a new sigsegv and sigbus handler, and make
546 sure SIGBUS, SIGSEGV and SIGTERM are unblocked. (Perhaps the
547 first two can never be blocked anyway?) */
548
549 sigbus_new.ksa_handler = valid_addr_handler;
nethercote73b526f2004-10-31 18:48:21 +0000550 sigbus_new.sa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
551 sigbus_new.sa_restorer = NULL;
552 res = VG_(sigemptyset)( &sigbus_new.sa_mask );
jsgfcb1d1c02003-10-14 21:55:10 +0000553 vg_assert(res == 0);
554
555 sigsegv_new.ksa_handler = valid_addr_handler;
nethercote73b526f2004-10-31 18:48:21 +0000556 sigsegv_new.sa_flags = VKI_SA_ONSTACK | VKI_SA_RESTART;
557 sigsegv_new.sa_restorer = NULL;
558 res = VG_(sigemptyset)( &sigsegv_new.sa_mask );
jsgfcb1d1c02003-10-14 21:55:10 +0000559 vg_assert(res == 0+0);
560
nethercote73b526f2004-10-31 18:48:21 +0000561 res = VG_(sigemptyset)( &unblockmask_new );
562 res |= VG_(sigaddset)( &unblockmask_new, VKI_SIGBUS );
563 res |= VG_(sigaddset)( &unblockmask_new, VKI_SIGSEGV );
564 res |= VG_(sigaddset)( &unblockmask_new, VKI_SIGTERM );
jsgfcb1d1c02003-10-14 21:55:10 +0000565 vg_assert(res == 0+0+0);
566
nethercote73b526f2004-10-31 18:48:21 +0000567 res = VG_(sigaction)( VKI_SIGBUS, &sigbus_new, &sigbus_saved );
jsgfcb1d1c02003-10-14 21:55:10 +0000568 vg_assert(res == 0+0+0+0);
569
nethercote73b526f2004-10-31 18:48:21 +0000570 res = VG_(sigaction)( VKI_SIGSEGV, &sigsegv_new, &sigsegv_saved );
jsgfcb1d1c02003-10-14 21:55:10 +0000571 vg_assert(res == 0+0+0+0+0);
572
nethercote73b526f2004-10-31 18:48:21 +0000573 res = VG_(sigprocmask)( VKI_SIG_UNBLOCK, &unblockmask_new, &blockmask_saved );
jsgfcb1d1c02003-10-14 21:55:10 +0000574 vg_assert(res == 0+0+0+0+0+0);
575}
576
577static void restore_signals(void)
578{
579 Int res;
580
581 /* Restore signal state to whatever it was before. */
nethercote73b526f2004-10-31 18:48:21 +0000582 res = VG_(sigaction)( VKI_SIGBUS, &sigbus_saved, NULL );
jsgfcb1d1c02003-10-14 21:55:10 +0000583 vg_assert(res == 0 +0);
584
nethercote73b526f2004-10-31 18:48:21 +0000585 res = VG_(sigaction)( VKI_SIGSEGV, &sigsegv_saved, NULL );
jsgfcb1d1c02003-10-14 21:55:10 +0000586 vg_assert(res == 0 +0 +0);
587
nethercote73b526f2004-10-31 18:48:21 +0000588 res = VG_(sigprocmask)( VKI_SIG_SETMASK, &blockmask_saved, NULL );
jsgfcb1d1c02003-10-14 21:55:10 +0000589 vg_assert(res == 0 +0 +0 +0);
590}
591
592/* if false, setup and restore signals for every access */
593#define LAZYSIG 1
594
595static Bool is_valid_addr(Addr a)
596{
597 static SymType faulted = { TyError };
598 static const Bool debug = False;
599 volatile Bool ret = False;
600
nethercote55c09082004-11-04 19:33:51 +0000601 if ((a > VKI_PAGE_SIZE) && !test_visited(a, &faulted)) {
jsgfcb1d1c02003-10-14 21:55:10 +0000602 if (!LAZYSIG)
603 setup_signals();
604
605 if (__builtin_setjmp(valid_addr_jmpbuf) == 0) {
606 volatile UInt *volatile ptr = (volatile UInt *)a;
607
608 *ptr;
609
610 ret = True;
611 } else {
612 /* cache bad addresses in visited table */
613 has_visited(a, &faulted);
614 ret = False;
615 }
616
617 if (!LAZYSIG)
618 restore_signals();
619 }
620
621 if (debug)
622 VG_(printf)("is_valid_addr(%p) -> %d\n", a, ret);
623
624 return ret;
625}
626
627static Int free_varlist(Variable *list)
628{
629 Variable *next;
630 Int count = 0;
631
632 for(; list != NULL; list = next) {
633 next = list->next;
634 count++;
635 if (list->name)
636 VG_(arena_free)(VG_AR_SYMTAB, list->name);
637 VG_(arena_free)(VG_AR_SYMTAB, list);
638 }
639 return count;
640}
641
642/* Composite: struct, union, array
643 Non-composite: everything else
644 */
645static inline Bool is_composite(SymType *ty)
646{
647 switch(ty->kind) {
648 case TyUnion:
649 case TyStruct:
650 case TyArray:
651 return True;
652
653 default:
654 return False;
655 }
656}
657
658/* There's something at the end of the rainbow */
659static inline Bool is_followable(SymType *ty)
660{
661 return ty->kind == TyPointer || is_composite(ty);
662}
663
thughes4ad52d02004-06-27 17:37:21 +0000664/* Result buffer */
665static Char *describe_addr_buf;
666static UInt describe_addr_bufidx;
667static UInt describe_addr_bufsz;
668
669/* Add a character to the result buffer */
sewardjb5f6f512005-03-10 23:59:00 +0000670static void describe_addr_addbuf(Char c,void *p) {
thughes4ad52d02004-06-27 17:37:21 +0000671 if ((describe_addr_bufidx+1) >= describe_addr_bufsz) {
672 Char *n;
673
674 if (describe_addr_bufsz == 0)
675 describe_addr_bufsz = 8;
676 else
677 describe_addr_bufsz *= 2;
678
nethercote996901a2004-08-03 13:29:09 +0000679 /* use tool malloc so that the tool can free it */
thughes4ad52d02004-06-27 17:37:21 +0000680 n = VG_(malloc)(describe_addr_bufsz);
681 if (describe_addr_buf != NULL && describe_addr_bufidx != 0)
682 VG_(memcpy)(n, describe_addr_buf, describe_addr_bufidx);
683 if (describe_addr_buf != NULL)
684 VG_(free)(describe_addr_buf);
685 describe_addr_buf = n;
686 }
687 describe_addr_buf[describe_addr_bufidx++] = c;
688 describe_addr_buf[describe_addr_bufidx] = '\0';
689}
690
jsgfcb1d1c02003-10-14 21:55:10 +0000691#define MAX_PLY 7 /* max depth we go */
692#define MAX_ELEMENTS 5000 /* max number of array elements we scan */
693#define MAX_VARS 10000 /* max number of variables total traversed */
694
695Char *VG_(describe_addr)(ThreadId tid, Addr addr)
696{
697 static const Bool debug = False;
698 static const Bool memaccount = False; /* match creates to frees */
699 Addr eip; /* thread's EIP */
700 Variable *list; /* worklist */
701 Variable *keeplist; /* container variables */
702 Variable *found; /* the chain we found */
jsgfcb1d1c02003-10-14 21:55:10 +0000703 Int created=0, freed=0;
704 Int numvars = MAX_VARS;
705
thughes4ad52d02004-06-27 17:37:21 +0000706 describe_addr_buf = NULL;
707 describe_addr_bufidx = 0;
708 describe_addr_bufsz = 0;
jsgfcb1d1c02003-10-14 21:55:10 +0000709
710 clear_visited();
711
712 found = NULL;
713 keeplist = NULL;
714
njn67516132005-03-22 04:02:43 +0000715 eip = VG_(get_IP)(tid);
jsgfcb1d1c02003-10-14 21:55:10 +0000716 list = VG_(get_scope_variables)(tid);
717
718 if (memaccount) {
719 Variable *v;
720
721 for(v = list; v != NULL; v = v->next)
722 created++;
723 }
724
725 if (debug) {
726 Char file[100];
727 Int line;
728 if (!VG_(get_filename_linenum)(eip, file, sizeof(file), &line))
729 file[0] = 0;
730 VG_(printf)("describing address %p for tid=%d @ %s:%d\n", addr, tid, file, line);
731 }
732
733 if (LAZYSIG)
734 setup_signals();
735
736 /* breadth-first traversal of all memory visible to the program at
737 the current point */
738 while(list != NULL && found == NULL) {
739 Variable **prev = &list;
740 Variable *var, *next;
741 Variable *newlist = NULL, *newlistend = NULL;
742
743 if (debug)
744 VG_(printf)("----------------------------------------\n");
745
746 for(var = list; var != NULL; var = next) {
747 SymType *type = var->type;
748 Bool keep = False;
749
750 /* Add a new variable to the list */
njna9c9c9b2005-03-12 15:39:54 +0000751 void newvar(Char *name, SymType *ty, Addr valuep, UInt size) {
jsgfcb1d1c02003-10-14 21:55:10 +0000752 Variable *v;
753
754 /* have we been here before? */
755 if (has_visited(valuep, ty))
756 return;
757
758 /* are we too deep? */
759 if (var->distance > MAX_PLY)
760 return;
761
762 /* have we done too much? */
763 if (numvars-- == 0)
764 return;
765
766 if (memaccount)
767 created++;
768
769 v = VG_(arena_malloc)(VG_AR_SYMTAB, sizeof(*v));
770
771 if (name)
772 v->name = VG_(arena_strdup)(VG_AR_SYMTAB, name);
773 else
774 v->name = NULL;
775 v->type = VG_(st_basetype)(ty, False);
776 v->valuep = valuep;
777 v->size = size == -1 ? ty->size : size;
778 v->container = var;
779 v->distance = var->distance + 1;
780 v->next = NULL;
781
782 if (newlist == NULL)
783 newlist = newlistend = v;
784 else {
785 newlistend->next = v;
786 newlistend = v;
787 }
788
789 if (debug)
790 VG_(printf)(" --> %d: name=%s type=%p(%s %s) container=%p &val=%p\n",
791 v->distance, v->name,
792 v->type, ppkind(v->type->kind),
793 v->type->name ? (char *)v->type->name : "",
794 v->container, v->valuep);
795 keep = True;
796 return;
797 }
798
799 next = var->next;
800
801 if (debug)
802 VG_(printf)(" %d: name=%s type=%p(%s %s) container=%p &val=%p\n",
803 var->distance, var->name,
804 var->type, ppkind(var->type->kind),
805 var->type->name ? (char *)var->type->name : "",
806 var->container, var->valuep);
807
808 if (0 && has_visited(var->valuep, var->type)) {
809 /* advance prev; we're keeping this one on the doomed list */
810 prev = &var->next;
811 continue;
812 }
813
814 if (!is_composite(var->type) &&
815 addr >= var->valuep && addr < (var->valuep + var->size)) {
816 /* at hit - remove it from the list, add it to the
817 keeplist and set found */
818 found = var;
819 *prev = var->next;
820 var->next = keeplist;
821 keeplist = var;
822 break;
823 }
824
825 type = VG_(st_basetype)(type, True);
826
827 switch(type->kind) {
828 case TyUnion:
829 case TyStruct: {
830 Int i;
831
832 if (debug)
mueller5ed88f22004-01-06 16:02:29 +0000833 VG_(printf)(" %d fields\n", type->u.t_struct.nfield);
834 for(i = 0; i < type->u.t_struct.nfield; i++) {
835 StField *f = &type->u.t_struct.fields[i];
jsgfcb1d1c02003-10-14 21:55:10 +0000836 newvar(f->name, f->type, var->valuep + (f->offset / 8), (f->size + 7) / 8);
837 }
838 break;
839 }
840
841 case TyArray: {
842 Int i;
843 Int offset; /* offset of index for non-0-based arrays */
844 Int min, max; /* range of indicies we care about (0 based) */
mueller5ed88f22004-01-06 16:02:29 +0000845 SymType *ty = type->u.t_array.type;
846 vg_assert(type->u.t_array.idxtype->kind == TyRange);
jsgfcb1d1c02003-10-14 21:55:10 +0000847
mueller5ed88f22004-01-06 16:02:29 +0000848 offset = type->u.t_array.idxtype->u.t_range.min;
jsgfcb1d1c02003-10-14 21:55:10 +0000849 min = 0;
mueller5ed88f22004-01-06 16:02:29 +0000850 max = type->u.t_array.idxtype->u.t_range.max - offset;
jsgfcb1d1c02003-10-14 21:55:10 +0000851
852 if ((max-min+1) == 0) {
853#if SHADOWCHUNK
854 /* zero-sized array - look at allocated memory */
855 ShadowChunk *sc = findchunk(var->valuep);
856
857 if (sc != NULL) {
858 max = ((sc->data + sc->size - var->valuep) / ty->size) + min;
859 if (debug)
860 VG_(printf)(" zero sized array: using min=%d max=%d\n",
861 min, max);
862 }
863#endif
864 }
865
866 /* If this array's elements can't take us anywhere useful,
867 just look to see if an element itself is being pointed
868 to; otherwise just skip the whole thing */
869 if (!is_followable(ty)) {
870 UInt sz = ty->size * (max+1);
871
872 if (debug)
873 VG_(printf)(" non-followable array (sz=%d): checking addr %p in range %p-%p\n",
874 sz, addr, var->valuep, (var->valuep + sz));
sewardjb5f6f512005-03-10 23:59:00 +0000875 if (ty->size > 0 && addr >= var->valuep && addr <= (var->valuep + sz))
jsgfcb1d1c02003-10-14 21:55:10 +0000876 min = max = (addr - var->valuep) / ty->size;
877 else
878 break;
879 }
880
881 /* truncate array if it's too big */
882 if (max-min+1 > MAX_ELEMENTS)
883 max = min+MAX_ELEMENTS;
884
885 if (debug)
886 VG_(printf)(" array index %d - %d\n", min, max);
887 for(i = min; i <= max; i++) {
888 Char b[10];
889 VG_(sprintf)(b, "[%d]", i+offset);
890 newvar(b, ty, var->valuep + (i * ty->size), -1);
891 }
892
893 break;
894 }
895
896 case TyPointer:
897 /* follow */
898 /* XXX work out a way of telling whether a pointer is
899 actually a decayed array, and treat it accordingly */
900 if (is_valid_addr(var->valuep))
mueller5ed88f22004-01-06 16:02:29 +0000901 newvar(NULL, type->u.t_pointer.type, *(Addr *)var->valuep, -1);
jsgfcb1d1c02003-10-14 21:55:10 +0000902 break;
903
904 case TyUnresolved:
905 VG_(printf)("var %s is unresolved (type=%p)\n", var->name, type);
906 break;
907
908 default:
909 /* Simple non-composite, non-pointer type */
910 break;
911 }
912
913 if (keep) {
914 /* ironically, keep means remove it from the list */
915 *prev = next;
916
917 /* being kept - add it if not already there */
918 if (keeplist != var) {
919 var->next = keeplist;
920 keeplist = var;
921 }
922 } else {
923 /* advance prev; we're keeping it on the doomed list */
924 prev = &var->next;
925 }
926 }
927
928 /* kill old list */
929 freed += free_varlist(list);
930 list = NULL;
931
932 if (found) {
933 /* kill new list too */
934 freed += free_varlist(newlist);
935 newlist = newlistend = NULL;
936 } else {
937 /* new list becomes old list */
938 list = newlist;
939 }
940 }
941
942 if (LAZYSIG)
943 restore_signals();
944
945 if (found != NULL) {
946 Int len = 0;
947 Char file[100];
948 Int line;
949
950 /* Try to generate an idiomatic C-like expression from what
951 we've found. */
952
953 {
954 Variable *v;
955 for(v = found; v != NULL; v = v->container) {
956 if (debug)
957 VG_(printf)("v=%p (%s) %s\n",
958 v, v->name ? v->name : (Char *)"",
959 ppkind(v->type->kind));
960
961 len += (v->name ? VG_(strlen)(v->name) : 0) + 5;
962 }
963 }
964
965 /* now that we know how long the expression will be
966 (approximately) build it up */
967 {
968 Char expr[len*2];
969 Char *sp = &expr[len]; /* pointer at start of string */
970 Char *ep = sp; /* pointer at end of string */
njna9c9c9b2005-03-12 15:39:54 +0000971 void genstring(Variable *v, Variable *inner) {
jsgfcb1d1c02003-10-14 21:55:10 +0000972 Variable *c = v->container;
973
974 if (c != NULL)
975 genstring(c, v);
976
977 if (v->name != NULL) {
978 len = VG_(strlen)(v->name);
979 VG_(memcpy)(ep, v->name, len);
980 ep += len;
981 }
982
983 switch(v->type->kind) {
984 case TyPointer:
985 /* pointer-to-structure/union handled specially */
986 if (inner == NULL ||
987 !(inner->type->kind == TyStruct || inner->type->kind == TyUnion)) {
988 *--sp = '*';
989 *--sp = '(';
990 *ep++ = ')';
991 }
992 break;
993
994 case TyStruct:
995 case TyUnion:
996 if (c && c->type->kind == TyPointer) {
997 *ep++ = '-';
998 *ep++ = '>';
999 } else
1000 *ep++ = '.';
1001 break;
1002
1003 default:
1004 break;
1005 }
1006 }
1007
1008 {
1009 Bool ptr = True;
1010
1011 /* If the result is already a pointer, just use that as
1012 the value, otherwise generate &(...) around the
1013 expression. */
1014 if (found->container && found->container->type->kind == TyPointer) {
1015 vg_assert(found->name == NULL);
1016
1017 found->name = found->container->name;
1018 found->container->name = NULL;
1019 found->container = found->container->container;
1020 } else {
sewardjb5f6f512005-03-10 23:59:00 +00001021 bprintf(describe_addr_addbuf, 0, "&(");
jsgfcb1d1c02003-10-14 21:55:10 +00001022 ptr = False;
1023 }
1024
1025 genstring(found, NULL);
1026
1027 if (!ptr)
1028 *ep++ = ')';
1029 }
1030
1031 *ep++ = '\0';
1032
sewardjb5f6f512005-03-10 23:59:00 +00001033 bprintf(describe_addr_addbuf, 0, sp);
jsgfcb1d1c02003-10-14 21:55:10 +00001034
1035 if (addr != found->valuep)
sewardjb5f6f512005-03-10 23:59:00 +00001036 bprintf(describe_addr_addbuf, 0, "+%d", addr - found->valuep);
jsgfcb1d1c02003-10-14 21:55:10 +00001037
1038 if (VG_(get_filename_linenum)(eip, file, sizeof(file), &line))
sewardjb5f6f512005-03-10 23:59:00 +00001039 bprintf(describe_addr_addbuf, 0, " at %s:%d", file, line, addr);
jsgfcb1d1c02003-10-14 21:55:10 +00001040 }
1041 }
1042
1043 freed += free_varlist(keeplist);
1044
1045 if (memaccount)
1046 VG_(printf)("created %d, freed %d\n", created, freed);
1047
1048 clear_visited();
1049
1050 if (debug)
thughes4ad52d02004-06-27 17:37:21 +00001051 VG_(printf)("returning buf=%s\n", describe_addr_buf);
jsgfcb1d1c02003-10-14 21:55:10 +00001052
thughes4ad52d02004-06-27 17:37:21 +00001053 return describe_addr_buf;
jsgfcb1d1c02003-10-14 21:55:10 +00001054}
1055#endif /* TEST */
njn4bbdc972003-10-16 10:10:55 +00001056
1057/*--------------------------------------------------------------------*/
1058/*--- end vg_symtypes.c ---*/
1059/*--------------------------------------------------------------------*/