blob: 01f574cddd859649526245b02ca1dceaab2d3458 [file] [log] [blame]
njn25e49d8e72002-09-23 09:36:25 +00001
2/*--------------------------------------------------------------------*/
3/*--- Part of the MemCheck skin: management of memory error ---*/
4/*--- messages. ---*/
njn25cac76cb2002-09-23 11:21:57 +00005/*--- mc_errcontext.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00006/*--------------------------------------------------------------------*/
7
8/*
9 This file is part of Valgrind, an x86 protected-mode emulator
10 designed for debugging and profiling binaries on x86-Unixes.
11
12 Copyright (C) 2000-2002 Julian Seward
13 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
njn25cac76cb2002-09-23 11:21:57 +000033#include "mc_include.h"
njn25e49d8e72002-09-23 09:36:25 +000034
35/*------------------------------------------------------------*/
36/*--- Defns ---*/
37/*------------------------------------------------------------*/
38
39/* These many bytes below %ESP are considered addressible if we're
40 doing the --workaround-gcc296-bugs hack. */
41#define VG_GCC296_BUG_STACK_SLOP 1024
42
43
44typedef
45 enum {
46 /* Bad syscall params */
47 ParamSupp,
48 /* Memory errors in core (pthread ops, signal handling) */
49 CoreMemSupp,
50 /* Use of invalid values of given size */
51 Value0Supp, Value1Supp, Value2Supp, Value4Supp, Value8Supp,
52 /* Invalid read/write attempt at given size */
53 Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp,
54 /* Invalid or mismatching free */
55 FreeSupp
56 }
57 MemCheckSuppKind;
58
59/* What kind of error it is. */
60typedef
61 enum { ValueErr,
62 CoreMemErr,
63 AddrErr,
64 ParamErr, UserErr, /* behaves like an anonymous ParamErr */
65 FreeErr, FreeMismatchErr
66 }
67 MemCheckErrorKind;
68
69/* What kind of memory access is involved in the error? */
70typedef
71 enum { ReadAxs, WriteAxs, ExecAxs }
72 AxsKind;
73
74/* Extra context for memory errors */
75typedef
76 struct {
77 /* AddrErr */
78 AxsKind axskind;
79 /* AddrErr, ValueErr */
80 Int size;
81 /* AddrErr, FreeErr, FreeMismatchErr, ParamErr, UserErr */
82 AddrInfo addrinfo;
83 /* ParamErr, UserErr, CoreMemErr */
84 Bool isWrite;
85 }
86 MemCheckError;
87
88/*------------------------------------------------------------*/
89/*--- Comparing and printing errors ---*/
90/*------------------------------------------------------------*/
91
92static __inline__
93void clear_AddrInfo ( AddrInfo* ai )
94{
95 ai->akind = Unknown;
96 ai->blksize = 0;
97 ai->rwoffset = 0;
98 ai->lastchange = NULL;
99 ai->stack_tid = VG_INVALID_THREADID;
100 ai->maybe_gcc = False;
101}
102
103static __inline__
104void clear_MemCheckError ( MemCheckError* err_extra )
105{
106 err_extra->axskind = ReadAxs;
107 err_extra->size = 0;
108 clear_AddrInfo ( &err_extra->addrinfo );
109 err_extra->isWrite = False;
110}
111
112__attribute__ ((unused))
113static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
114{
115 if (ai1->akind != Undescribed
116 && ai2->akind != Undescribed
117 && ai1->akind != ai2->akind)
118 return False;
119 if (ai1->akind == Freed || ai1->akind == Mallocd) {
120 if (ai1->blksize != ai2->blksize)
121 return False;
122 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
123 return False;
124 }
125 return True;
126}
127
128/* Compare error contexts, to detect duplicates. Note that if they
129 are otherwise the same, the faulting addrs and associated rwoffsets
130 are allowed to be different. */
131
132Bool SK_(eq_SkinError) ( VgRes res,
133 SkinError* e1, SkinError* e2 )
134{
135 MemCheckError* e1_extra = e1->extra;
136 MemCheckError* e2_extra = e2->extra;
137
138 switch (e1->ekind) {
139 case CoreMemErr:
140 if (e1_extra->isWrite != e2_extra->isWrite) return False;
141 if (e2->ekind != CoreMemErr) return False;
142 if (e1->string == e2->string) return True;
143 if (0 == VG_(strcmp)(e1->string, e2->string)) return True;
144 return False;
145
146 case UserErr:
147 case ParamErr:
148 if (e1_extra->isWrite != e2_extra->isWrite)
149 return False;
150 if (e1->ekind == ParamErr
151 && 0 != VG_(strcmp)(e1->string, e2->string))
152 return False;
153 return True;
154
155 case FreeErr:
156 case FreeMismatchErr:
157 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
158 cause excessive duplication of errors. Not even AddrErr
159 below does that. So don't compare either the .addr field
160 or the .addrinfo fields. */
161 /* if (e1->addr != e2->addr) return False; */
162 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
163 return False;
164 */
165 return True;
166
167 case AddrErr:
168 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
169 if (e1_extra->size != e2_extra->size) return False;
170 /*
171 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
172 return False;
173 */
174 return True;
175
176 case ValueErr:
177 if (e1_extra->size != e2_extra->size) return False;
178 return True;
179
180 default:
181 VG_(printf)("Error:\n unknown MemCheck error code %d\n", e1->ekind);
182 VG_(panic)("unknown error code in SK_(eq_SkinError)");
183 }
184}
185
186static void pp_AddrInfo ( Addr a, AddrInfo* ai )
187{
188 switch (ai->akind) {
189 case Stack:
190 VG_(message)(Vg_UserMsg,
191 " Address 0x%x is on thread %d's stack",
192 a, ai->stack_tid);
193 break;
194 case Unknown:
195 if (ai->maybe_gcc) {
196 VG_(message)(Vg_UserMsg,
197 " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
198 a);
199 VG_(message)(Vg_UserMsg,
200 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
201 } else {
202 VG_(message)(Vg_UserMsg,
203 " Address 0x%x is not stack'd, malloc'd or free'd", a);
204 }
205 break;
206 case Freed: case Mallocd: case UserG: case UserS: {
207 UInt delta;
208 UChar* relative;
209 if (ai->rwoffset < 0) {
210 delta = (UInt)(- ai->rwoffset);
211 relative = "before";
212 } else if (ai->rwoffset >= ai->blksize) {
213 delta = ai->rwoffset - ai->blksize;
214 relative = "after";
215 } else {
216 delta = ai->rwoffset;
217 relative = "inside";
218 }
219 if (ai->akind == UserS) {
220 VG_(message)(Vg_UserMsg,
221 " Address 0x%x is %d bytes %s a %d-byte stack red-zone created",
222 a, delta, relative,
223 ai->blksize );
224 } else {
225 VG_(message)(Vg_UserMsg,
226 " Address 0x%x is %d bytes %s a block of size %d %s",
227 a, delta, relative,
228 ai->blksize,
229 ai->akind==Mallocd ? "alloc'd"
230 : ai->akind==Freed ? "free'd"
231 : "client-defined");
232 }
233 VG_(pp_ExeContext)(ai->lastchange);
234 break;
235 }
236 default:
237 VG_(panic)("pp_AddrInfo");
238 }
239}
240
241void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
242{
243 MemCheckError* err_extra = err->extra;
244
245 switch (err->ekind) {
246 case CoreMemErr:
247 if (err_extra->isWrite) {
248 VG_(message)(Vg_UserMsg,
249 "%s contains unaddressable byte(s)", err->string );
250 } else {
251 VG_(message)(Vg_UserMsg,
252 "%s contains uninitialised or unaddressable byte(s)",
253 err->string);
254 }
255 pp_ExeContext();
256 break;
257
258 case ValueErr:
259 if (err_extra->size == 0) {
260 VG_(message)(
261 Vg_UserMsg,
262 "Conditional jump or move depends on uninitialised value(s)");
263 } else {
264 VG_(message)(Vg_UserMsg,
265 "Use of uninitialised value of size %d",
266 err_extra->size);
267 }
268 pp_ExeContext();
269 break;
270
271 case AddrErr:
272 switch (err_extra->axskind) {
273 case ReadAxs:
274 VG_(message)(Vg_UserMsg, "Invalid read of size %d",
275 err_extra->size );
276 break;
277 case WriteAxs:
278 VG_(message)(Vg_UserMsg, "Invalid write of size %d",
279 err_extra->size );
280 break;
281 case ExecAxs:
282 VG_(message)(Vg_UserMsg, "Jump to the invalid address "
283 "stated on the next line");
284 break;
285 default:
286 VG_(panic)("pp_SkinError(axskind)");
287 }
288 pp_ExeContext();
289 pp_AddrInfo(err->addr, &err_extra->addrinfo);
290 break;
291
292 case FreeErr:
293 VG_(message)(Vg_UserMsg,"Invalid free() / delete / delete[]");
294 /* fall through */
295 case FreeMismatchErr:
296 if (err->ekind == FreeMismatchErr)
297 VG_(message)(Vg_UserMsg,
298 "Mismatched free() / delete / delete []");
299 pp_ExeContext();
300 pp_AddrInfo(err->addr, &err_extra->addrinfo);
301 break;
302
303 case ParamErr:
304 if (err_extra->isWrite) {
305 VG_(message)(Vg_UserMsg,
306 "Syscall param %s contains unaddressable byte(s)",
307 err->string );
308 } else {
309 VG_(message)(Vg_UserMsg,
310 "Syscall param %s contains uninitialised or "
311 "unaddressable byte(s)",
312 err->string);
313 }
314 pp_ExeContext();
315 pp_AddrInfo(err->addr, &err_extra->addrinfo);
316 break;
317
318 case UserErr:
319 if (err_extra->isWrite) {
320 VG_(message)(Vg_UserMsg,
321 "Unaddressable byte(s) found during client check request");
322 } else {
323 VG_(message)(Vg_UserMsg,
324 "Uninitialised or "
325 "unaddressable byte(s) found during client check request");
326 }
327 pp_ExeContext();
328 pp_AddrInfo(err->addr, &err_extra->addrinfo);
329 break;
330
331 default:
332 VG_(printf)("Error:\n unknown MemCheck error code %d\n", err->ekind);
333 VG_(panic)("unknown error code in SK_(pp_SkinError)");
334 }
335}
336
337/*------------------------------------------------------------*/
338/*--- Recording errors ---*/
339/*------------------------------------------------------------*/
340
341/* Describe an address as best you can, for error messages,
342 putting the result in ai. */
343
344static void describe_addr ( Addr a, AddrInfo* ai )
345{
346 ShadowChunk* sc;
347 Bool ok;
348 ThreadId tid;
349
350 /* Nested functions, yeah. Need the lexical scoping of 'a'. */
351
352 /* Closure for searching thread stacks */
353 Bool addr_is_in_bounds(Addr stack_min, Addr stack_max)
354 {
355 return (stack_min <= a && a <= stack_max);
356 }
357 /* Closure for searching malloc'd and free'd lists */
358 Bool addr_is_in_block(ShadowChunk *sh_ch)
359 {
360 return VG_(addr_is_in_block) ( a, sh_ch->data, sh_ch->size );
361 }
362
363 /* Perhaps it's a user-def'd block ? */
364 ok = SK_(client_perm_maybe_describe)( a, ai );
365 if (ok)
366 return;
367 /* Perhaps it's on a thread's stack? */
368 tid = VG_(any_matching_thread_stack)(addr_is_in_bounds);
369 if (tid != VG_INVALID_THREADID) {
370 ai->akind = Stack;
371 ai->stack_tid = tid;
372 return;
373 }
374 /* Search for a recently freed block which might bracket it. */
375 sc = SK_(any_matching_freed_ShadowChunks)(addr_is_in_block);
376 if (NULL != sc) {
377 ai->akind = Freed;
378 ai->blksize = sc->size;
379 ai->rwoffset = (Int)(a) - (Int)(sc->data);
380 ai->lastchange = (ExeContext*)sc->skin_extra[0];
381 return;
382 }
383 /* Search for a currently malloc'd block which might bracket it. */
384 sc = VG_(any_matching_mallocd_ShadowChunks)(addr_is_in_block);
385 if (NULL != sc) {
386 ai->akind = Mallocd;
387 ai->blksize = sc->size;
388 ai->rwoffset = (Int)(a) - (Int)(sc->data);
389 ai->lastchange = (ExeContext*)sc->skin_extra[0];
390 return;
391 }
392 /* Clueless ... */
393 ai->akind = Unknown;
394 return;
395}
396
397
398/* Creates a copy of the err_extra, updates the copy with address info if
399 necessary, sticks the copy into the SkinError. */
400void SK_(dup_extra_and_update)(SkinError* err)
401{
402 MemCheckError* err_extra;
403
404 err_extra = VG_(malloc)(sizeof(MemCheckError));
405 *err_extra = *((MemCheckError*)err->extra);
406
407 if (err_extra->addrinfo.akind == Undescribed)
408 describe_addr ( err->addr, &(err_extra->addrinfo) );
409
410 err->extra = err_extra;
411}
412
413/* These two are called from generated code. */
414void SK_(record_value_error) ( Int size )
415{
416 MemCheckError err_extra;
417
418 clear_MemCheckError( &err_extra );
419 err_extra.size = size;
420 VG_(maybe_record_error)( NULL, ValueErr, /*addr*/0, /*s*/NULL, &err_extra );
421}
422
423/* Is this address within some small distance below %ESP? Used only
424 for the --workaround-gcc296-bugs kludge. */
425Bool VG_(is_just_below_ESP)( Addr esp, Addr aa )
426{
427 if ((UInt)esp > (UInt)aa
428 && ((UInt)esp - (UInt)aa) <= VG_GCC296_BUG_STACK_SLOP)
429 return True;
430 else
431 return False;
432}
433
434void SK_(record_address_error) ( Addr a, Int size, Bool isWrite )
435{
436 MemCheckError err_extra;
437 Bool just_below_esp;
438
439 just_below_esp
440 = VG_(is_just_below_ESP)( VG_(get_stack_pointer)(), a );
441
442 /* If this is caused by an access immediately below %ESP, and the
443 user asks nicely, we just ignore it. */
444 if (SK_(clo_workaround_gcc296_bugs) && just_below_esp)
445 return;
446
447 clear_MemCheckError( &err_extra );
448 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
449 err_extra.size = size;
450 err_extra.addrinfo.akind = Undescribed;
451 err_extra.addrinfo.maybe_gcc = just_below_esp;
452 VG_(maybe_record_error)( NULL, AddrErr, a, /*s*/NULL, &err_extra );
453}
454
455/* These ones are called from non-generated code */
456
457/* This is for memory errors in pthread functions, as opposed to pthread API
458 errors which are found by the core. */
459void SK_(record_core_mem_error) ( ThreadState* tst, Bool isWrite, Char* msg )
460{
461 MemCheckError err_extra;
462
463 clear_MemCheckError( &err_extra );
464 err_extra.isWrite = isWrite;
465 VG_(maybe_record_error)( tst, CoreMemErr, /*addr*/0, msg, &err_extra );
466}
467
468void SK_(record_param_error) ( ThreadState* tst, Addr a, Bool isWrite,
469 Char* msg )
470{
471 MemCheckError err_extra;
472
473 vg_assert(NULL != tst);
474 clear_MemCheckError( &err_extra );
475 err_extra.addrinfo.akind = Undescribed;
476 err_extra.isWrite = isWrite;
477 VG_(maybe_record_error)( tst, ParamErr, a, msg, &err_extra );
478}
479
480void SK_(record_jump_error) ( ThreadState* tst, Addr a )
481{
482 MemCheckError err_extra;
483
484 vg_assert(NULL != tst);
485
486 clear_MemCheckError( &err_extra );
487 err_extra.axskind = ExecAxs;
488 err_extra.addrinfo.akind = Undescribed;
489 VG_(maybe_record_error)( tst, AddrErr, a, /*s*/NULL, &err_extra );
490}
491
492void SK_(record_free_error) ( ThreadState* tst, Addr a )
493{
494 MemCheckError err_extra;
495
496 vg_assert(NULL != tst);
497
498 clear_MemCheckError( &err_extra );
499 err_extra.addrinfo.akind = Undescribed;
500 VG_(maybe_record_error)( tst, FreeErr, a, /*s*/NULL, &err_extra );
501}
502
503void SK_(record_freemismatch_error) ( ThreadState* tst, Addr a )
504{
505 MemCheckError err_extra;
506
507 vg_assert(NULL != tst);
508
509 clear_MemCheckError( &err_extra );
510 err_extra.addrinfo.akind = Undescribed;
511 VG_(maybe_record_error)( tst, FreeMismatchErr, a, /*s*/NULL, &err_extra );
512}
513
514void SK_(record_user_error) ( ThreadState* tst, Addr a, Bool isWrite )
515{
516 MemCheckError err_extra;
517
518 vg_assert(NULL != tst);
519
520 clear_MemCheckError( &err_extra );
521 err_extra.addrinfo.akind = Undescribed;
522 err_extra.isWrite = isWrite;
523 VG_(maybe_record_error)( tst, UserErr, a, /*s*/NULL, &err_extra );
524}
525
526
527/*------------------------------------------------------------*/
528/*--- Suppressions ---*/
529/*------------------------------------------------------------*/
530
531#define STREQ(s1,s2) (s1 != NULL && s2 != NULL \
532 && VG_(strcmp)((s1),(s2))==0)
533
534Bool SK_(recognised_suppression) ( Char* name, SuppKind *skind )
535{
536 if (STREQ(name, "Param")) *skind = ParamSupp;
537 else if (STREQ(name, "CoreMem")) *skind = CoreMemSupp;
538 else if (STREQ(name, "Value0")) *skind = Value0Supp; /* backwards compat */
539 else if (STREQ(name, "Cond")) *skind = Value0Supp;
540 else if (STREQ(name, "Value1")) *skind = Value1Supp;
541 else if (STREQ(name, "Value2")) *skind = Value2Supp;
542 else if (STREQ(name, "Value4")) *skind = Value4Supp;
543 else if (STREQ(name, "Value8")) *skind = Value8Supp;
544 else if (STREQ(name, "Addr1")) *skind = Addr1Supp;
545 else if (STREQ(name, "Addr2")) *skind = Addr2Supp;
546 else if (STREQ(name, "Addr4")) *skind = Addr4Supp;
547 else if (STREQ(name, "Addr8")) *skind = Addr8Supp;
548 else if (STREQ(name, "Free")) *skind = FreeSupp;
549 else
550 return False;
551
552 return True;
553}
554
555Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf,
556 SkinSupp *s )
557{
558 Bool eof;
559
560 if (s->skind == ParamSupp) {
561 eof = VG_(getLine) ( fd, buf, nBuf );
562 if (eof) return False;
563 s->string = VG_(strdup)(buf);
564 }
565 return True;
566}
567
568extern Bool SK_(error_matches_suppression)(SkinError* err, SkinSupp* su)
569{
570 UInt su_size;
571 MemCheckError* err_extra = err->extra;
572
573 switch (su->skind) {
574 case ParamSupp:
575 return (err->ekind == ParamErr && STREQ(su->string, err->string));
576
577 case CoreMemSupp:
578 return (err->ekind == CoreMemErr && STREQ(su->string, err->string));
579
580 case Value0Supp: su_size = 0; goto value_case;
581 case Value1Supp: su_size = 1; goto value_case;
582 case Value2Supp: su_size = 2; goto value_case;
583 case Value4Supp: su_size = 4; goto value_case;
584 case Value8Supp: su_size = 8; goto value_case;
585 value_case:
586 return (err->ekind == ValueErr && err_extra->size == su_size);
587
588 case Addr1Supp: su_size = 1; goto addr_case;
589 case Addr2Supp: su_size = 2; goto addr_case;
590 case Addr4Supp: su_size = 4; goto addr_case;
591 case Addr8Supp: su_size = 8; goto addr_case;
592 addr_case:
593 return (err->ekind == AddrErr && err_extra->size != su_size);
594
595 case FreeSupp:
596 return (err->ekind == FreeErr || err->ekind == FreeMismatchErr);
597
598 default:
599 VG_(printf)("Error:\n"
600 " unknown MemCheck suppression type %d\n", su->skind);
601 VG_(panic)("unknown suppression type in "
602 "SK_(error_matches_suppression)");
603 }
604}
605
606# undef STREQ
607
608/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +0000609/*--- end mc_errcontext.c ---*/
njn25e49d8e72002-09-23 09:36:25 +0000610/*--------------------------------------------------------------------*/