blob: edc123ae044499390797668aed8e00abab1d105d [file] [log] [blame]
sewardj7ce71662008-05-02 10:33:15 +00001
2/*--------------------------------------------------------------------*/
3/*--- Management, printing, etc, of errors and suppressions. ---*/
4/*--- mc_errors.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of MemCheck, a heavyweight Valgrind tool for
9 detecting memory errors.
10
njn9f207462009-03-10 22:02:09 +000011 Copyright (C) 2000-2009 Julian Seward
sewardj7ce71662008-05-02 10:33:15 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32#include "pub_tool_basics.h"
sewardj7ce71662008-05-02 10:33:15 +000033#include "pub_tool_hashtable.h" // For mc_include.h
34#include "pub_tool_libcbase.h"
35#include "pub_tool_libcassert.h"
36#include "pub_tool_libcprint.h"
37#include "pub_tool_machine.h"
38#include "pub_tool_mallocfree.h"
39#include "pub_tool_options.h"
sewardj7ce71662008-05-02 10:33:15 +000040#include "pub_tool_replacemalloc.h"
41#include "pub_tool_tooliface.h"
42#include "pub_tool_threadstate.h"
sewardj7ce71662008-05-02 10:33:15 +000043#include "pub_tool_debuginfo.h" // VG_(get_dataname_and_offset)
44
45#include "mc_include.h"
sewardj7ce71662008-05-02 10:33:15 +000046
47
48/*------------------------------------------------------------*/
49/*--- Error types ---*/
50/*------------------------------------------------------------*/
51
52/* See comment in mc_include.h */
53Bool MC_(any_value_errors) = False;
54
55
56// Different kinds of blocks.
57typedef enum {
58 Block_Mallocd = 111,
59 Block_Freed,
60 Block_Mempool,
61 Block_MempoolChunk,
62 Block_UserG
63} BlockKind;
64
65/* ------------------ Addresses -------------------- */
66
67/* The classification of a faulting address. */
68typedef
69 enum {
70 Addr_Undescribed, // as-yet unclassified
71 Addr_Unknown, // classification yielded nothing useful
72 Addr_Block, // in malloc'd/free'd block
73 Addr_Stack, // on a thread's stack
74 Addr_DataSym, // in a global data sym
75 Addr_Variable, // variable described by the debug info
76 Addr_SectKind // last-ditch classification attempt
77 }
78 AddrTag;
79
80typedef
81 struct _AddrInfo
82 AddrInfo;
83
84struct _AddrInfo {
85 AddrTag tag;
86 union {
87 // As-yet unclassified.
88 struct { } Undescribed;
89
90 // On a stack.
91 struct {
92 ThreadId tid; // Which thread's stack?
93 } Stack;
94
95 // This covers heap blocks (normal and from mempools) and user-defined
96 // blocks.
97 struct {
98 BlockKind block_kind;
99 Char* block_desc; // "block", "mempool" or user-defined
100 SizeT block_szB;
njnc4431bf2009-01-15 21:29:24 +0000101 PtrdiffT rwoffset;
sewardj7ce71662008-05-02 10:33:15 +0000102 ExeContext* lastchange;
103 } Block;
104
njnc4431bf2009-01-15 21:29:24 +0000105 // In a global .data symbol. This holds the first 127 chars of
106 // the variable's name (zero terminated), plus a (memory) offset.
sewardj7ce71662008-05-02 10:33:15 +0000107 struct {
njnc4431bf2009-01-15 21:29:24 +0000108 Char name[128];
109 PtrdiffT offset;
sewardj7ce71662008-05-02 10:33:15 +0000110 } DataSym;
111
112 // Is described by Dwarf debug info. Arbitrary strings. Must
113 // be the same length.
114 struct {
115 Char descr1[96];
116 Char descr2[96];
117 } Variable;
118
119 // Could only narrow it down to be the PLT/GOT/etc of a given
120 // object. Better than nothing, perhaps.
121 struct {
122 Char objname[128];
123 VgSectKind kind;
124 } SectKind;
125
126 // Classification yielded nothing useful.
127 struct { } Unknown;
128
129 } Addr;
130};
131
132/* ------------------ Errors ----------------------- */
133
134/* What kind of error it is. */
135typedef
136 enum {
137 Err_Value,
138 Err_Cond,
139 Err_CoreMem,
140 Err_Addr,
141 Err_Jump,
142 Err_RegParam,
143 Err_MemParam,
144 Err_User,
145 Err_Free,
146 Err_FreeMismatch,
147 Err_Overlap,
148 Err_Leak,
149 Err_IllegalMempool,
150 }
151 MC_ErrorTag;
152
153
154typedef struct _MC_Error MC_Error;
155
156struct _MC_Error {
157 // Nb: we don't need the tag here, as it's stored in the Error type! Yuk.
158 //MC_ErrorTag tag;
159
160 union {
161 // Use of an undefined value:
162 // - as a pointer in a load or store
163 // - as a jump target
164 struct {
165 SizeT szB; // size of value in bytes
166 // Origin info
167 UInt otag; // origin tag
168 ExeContext* origin_ec; // filled in later
169 } Value;
170
171 // Use of an undefined value in a conditional branch or move.
172 struct {
173 // Origin info
174 UInt otag; // origin tag
175 ExeContext* origin_ec; // filled in later
176 } Cond;
177
178 // Addressability error in core (signal-handling) operation.
179 // It would be good to get rid of this error kind, merge it with
180 // another one somehow.
181 struct {
182 } CoreMem;
183
184 // Use of an unaddressable memory location in a load or store.
185 struct {
186 Bool isWrite; // read or write?
187 SizeT szB; // not used for exec (jump) errors
188 Bool maybe_gcc; // True if just below %esp -- could be a gcc bug
189 AddrInfo ai;
190 } Addr;
191
192 // Jump to an unaddressable memory location.
193 struct {
194 AddrInfo ai;
195 } Jump;
196
197 // System call register input contains undefined bytes.
198 struct {
199 // Origin info
200 UInt otag; // origin tag
201 ExeContext* origin_ec; // filled in later
202 } RegParam;
203
204 // System call memory input contains undefined/unaddressable bytes
205 struct {
206 Bool isAddrErr; // Addressability or definedness error?
207 AddrInfo ai;
208 // Origin info
209 UInt otag; // origin tag
210 ExeContext* origin_ec; // filled in later
211 } MemParam;
212
213 // Problem found from a client request like CHECK_MEM_IS_ADDRESSABLE.
214 struct {
215 Bool isAddrErr; // Addressability or definedness error?
216 AddrInfo ai;
217 // Origin info
218 UInt otag; // origin tag
219 ExeContext* origin_ec; // filled in later
220 } User;
221
222 // Program tried to free() something that's not a heap block (this
223 // covers double-frees). */
224 struct {
225 AddrInfo ai;
226 } Free;
227
228 // Program allocates heap block with one function
229 // (malloc/new/new[]/custom) and deallocates with not the matching one.
230 struct {
231 AddrInfo ai;
232 } FreeMismatch;
233
234 // Call to strcpy, memcpy, etc, with overlapping blocks.
235 struct {
236 Addr src; // Source block
237 Addr dst; // Destination block
238 Int szB; // Size in bytes; 0 if unused.
239 } Overlap;
240
241 // A memory leak.
242 struct {
243 UInt n_this_record;
244 UInt n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000245 LossRecord* lr;
sewardj7ce71662008-05-02 10:33:15 +0000246 } Leak;
247
248 // A memory pool error.
249 struct {
250 AddrInfo ai;
251 } IllegalMempool;
252
253 } Err;
254};
255
256
257/*------------------------------------------------------------*/
258/*--- Printing errors ---*/
259/*------------------------------------------------------------*/
260
261static void mc_pp_AddrInfo ( Addr a, AddrInfo* ai, Bool maybe_gcc )
262{
263 HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
264 HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
265
266 switch (ai->tag) {
267 case Addr_Unknown:
268 if (maybe_gcc) {
269 VG_(message)(Vg_UserMsg,
270 "%sAddress 0x%llx is just below the stack ptr. "
njnf76d27a2009-05-28 01:53:07 +0000271 "To suppress, use: --workaround-gcc296-bugs=yes%s",
sewardj7ce71662008-05-02 10:33:15 +0000272 xpre, (ULong)a, xpost
273 );
274 } else {
275 VG_(message)(Vg_UserMsg,
276 "%sAddress 0x%llx "
277 "is not stack'd, malloc'd or (recently) free'd%s",
278 xpre, (ULong)a, xpost);
279 }
280 break;
281
282 case Addr_Stack:
283 VG_(message)(Vg_UserMsg,
284 "%sAddress 0x%llx is on thread %d's stack%s",
285 xpre, (ULong)a, ai->Addr.Stack.tid, xpost);
286 break;
287
288 case Addr_Block: {
njnc4431bf2009-01-15 21:29:24 +0000289 SizeT block_szB = ai->Addr.Block.block_szB;
290 PtrdiffT rwoffset = ai->Addr.Block.rwoffset;
291 SizeT delta;
292 const Char* relative;
sewardj7ce71662008-05-02 10:33:15 +0000293
294 if (rwoffset < 0) {
295 delta = (SizeT)(-rwoffset);
296 relative = "before";
297 } else if (rwoffset >= block_szB) {
298 delta = rwoffset - block_szB;
299 relative = "after";
300 } else {
301 delta = rwoffset;
302 relative = "inside";
303 }
304 VG_(message)(Vg_UserMsg,
barta0b6b2c2008-07-07 06:49:24 +0000305 "%sAddress 0x%lx is %'lu bytes %s a %s of size %'lu %s%s",
sewardj7ce71662008-05-02 10:33:15 +0000306 xpre,
307 a, delta, relative, ai->Addr.Block.block_desc,
308 block_szB,
309 ai->Addr.Block.block_kind==Block_Mallocd ? "alloc'd"
310 : ai->Addr.Block.block_kind==Block_Freed ? "free'd"
311 : "client-defined",
312 xpost);
313 VG_(pp_ExeContext)(ai->Addr.Block.lastchange);
314 break;
315 }
316
317 case Addr_DataSym:
barta0b6b2c2008-07-07 06:49:24 +0000318 VG_(message_no_f_c)(Vg_UserMsg,
319 "%sAddress 0x%llx is %llu bytes "
320 "inside data symbol \"%t\"%s",
321 xpre,
322 (ULong)a,
323 (ULong)ai->Addr.DataSym.offset,
324 ai->Addr.DataSym.name,
325 xpost);
sewardj7ce71662008-05-02 10:33:15 +0000326 break;
327
328 case Addr_Variable:
329 if (ai->Addr.Variable.descr1[0] != '\0')
330 VG_(message)(Vg_UserMsg, "%s%s%s",
331 xpre, ai->Addr.Variable.descr1, xpost);
332 if (ai->Addr.Variable.descr2[0] != '\0')
333 VG_(message)(Vg_UserMsg, "%s%s%s",
334 xpre, ai->Addr.Variable.descr2, xpost);
335 break;
336
337 case Addr_SectKind:
barta0b6b2c2008-07-07 06:49:24 +0000338 VG_(message_no_f_c)(Vg_UserMsg,
339 "%sAddress 0x%llx is in the %t segment of %t%s",
340 xpre,
341 (ULong)a,
342 VG_(pp_SectKind)(ai->Addr.SectKind.kind),
343 ai->Addr.SectKind.objname,
344 xpost);
sewardj7ce71662008-05-02 10:33:15 +0000345 break;
346
347 default:
348 VG_(tool_panic)("mc_pp_AddrInfo");
349 }
350}
351
352static const HChar* str_leak_lossmode ( Reachedness lossmode )
353{
354 const HChar *loss = "?";
355 switch (lossmode) {
356 case Unreached: loss = "definitely lost"; break;
357 case IndirectLeak: loss = "indirectly lost"; break;
njn8225cc02009-03-09 22:52:24 +0000358 case Possible: loss = "possibly lost"; break;
359 case Reachable: loss = "still reachable"; break;
sewardj7ce71662008-05-02 10:33:15 +0000360 }
361 return loss;
362}
363
364static const HChar* xml_leak_kind ( Reachedness lossmode )
365{
366 const HChar *loss = "?";
367 switch (lossmode) {
368 case Unreached: loss = "Leak_DefinitelyLost"; break;
369 case IndirectLeak: loss = "Leak_IndirectlyLost"; break;
njn8225cc02009-03-09 22:52:24 +0000370 case Possible: loss = "Leak_PossiblyLost"; break;
371 case Reachable: loss = "Leak_StillReachable"; break;
sewardj7ce71662008-05-02 10:33:15 +0000372 }
373 return loss;
374}
375
376static void mc_pp_msg( Char* xml_name, Error* err, const HChar* format, ... )
377{
378 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
379 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
380 Char buf[256];
381 va_list vargs;
382
383 if (VG_(clo_xml))
384 VG_(message)(Vg_UserMsg, " <kind>%s</kind>", xml_name);
385 // Stick xpre and xpost on the front and back of the format string.
386 VG_(snprintf)(buf, 256, "%s%s%s", xpre, format, xpost);
387 va_start(vargs, format);
388 VG_(vmessage) ( Vg_UserMsg, buf, vargs );
389 va_end(vargs);
390 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
391}
392
393static void mc_pp_origin ( ExeContext* ec, UInt okind )
394{
395 HChar* src = NULL;
396 HChar* xpre = VG_(clo_xml) ? " <what>" : " ";
397 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
398 tl_assert(ec);
399
400 switch (okind) {
401 case MC_OKIND_STACK: src = " by a stack allocation"; break;
402 case MC_OKIND_HEAP: src = " by a heap allocation"; break;
403 case MC_OKIND_USER: src = " by a client request"; break;
404 case MC_OKIND_UNKNOWN: src = ""; break;
405 }
406 tl_assert(src); /* guards against invalid 'okind' */
407
408 if (VG_(clo_xml)) {
409 VG_(message)(Vg_UserMsg, " <origin>");
410 }
411
412 VG_(message)(Vg_UserMsg, "%sUninitialised value was created%s%s",
413 xpre, src, xpost);
414 VG_(pp_ExeContext)( ec );
415 if (VG_(clo_xml)) {
416 VG_(message)(Vg_UserMsg, " </origin>");
417 }
418}
419
420void MC_(pp_Error) ( Error* err )
421{
422 MC_Error* extra = VG_(get_error_extra)(err);
423
424 switch (VG_(get_error_kind)(err)) {
425 case Err_CoreMem: {
426 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
427 /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
428 signal handler frame. --njn */
429 mc_pp_msg("CoreMemError", err,
430 "%s contains unaddressable byte(s)",
431 VG_(get_error_string)(err));
432 break;
433 }
434
435 case Err_Value:
436 MC_(any_value_errors) = True;
437 if (1 || extra->Err.Value.otag == 0) {
438 mc_pp_msg("UninitValue", err,
439 "Use of uninitialised value of size %d",
440 extra->Err.Value.szB);
441 } else {
442 mc_pp_msg("UninitValue", err,
443 "Use of uninitialised value of size %d (otag %u)",
444 extra->Err.Value.szB, extra->Err.Value.otag);
445 }
446 if (extra->Err.Value.origin_ec)
447 mc_pp_origin( extra->Err.Value.origin_ec,
448 extra->Err.Value.otag & 3 );
449 break;
450
451 case Err_Cond:
452 MC_(any_value_errors) = True;
453 if (1 || extra->Err.Cond.otag == 0) {
454 mc_pp_msg("UninitCondition", err,
455 "Conditional jump or move depends"
456 " on uninitialised value(s)");
457 } else {
458 mc_pp_msg("UninitCondition", err,
459 "Conditional jump or move depends"
460 " on uninitialised value(s) (otag %u)",
461 extra->Err.Cond.otag);
462 }
463 if (extra->Err.Cond.origin_ec)
464 mc_pp_origin( extra->Err.Cond.origin_ec,
465 extra->Err.Cond.otag & 3 );
466 break;
467
468 case Err_RegParam:
469 MC_(any_value_errors) = True;
470 mc_pp_msg("SyscallParam", err,
471 "Syscall param %s contains uninitialised byte(s)",
472 VG_(get_error_string)(err));
473 if (extra->Err.RegParam.origin_ec)
474 mc_pp_origin( extra->Err.RegParam.origin_ec,
475 extra->Err.RegParam.otag & 3 );
476 break;
477
478 case Err_MemParam:
479 if (!extra->Err.MemParam.isAddrErr)
480 MC_(any_value_errors) = True;
481 mc_pp_msg("SyscallParam", err,
482 "Syscall param %s points to %s byte(s)",
483 VG_(get_error_string)(err),
484 ( extra->Err.MemParam.isAddrErr
485 ? "unaddressable" : "uninitialised" ));
486 mc_pp_AddrInfo(VG_(get_error_address)(err),
487 &extra->Err.MemParam.ai, False);
488 if (extra->Err.MemParam.origin_ec && !extra->Err.MemParam.isAddrErr)
489 mc_pp_origin( extra->Err.MemParam.origin_ec,
490 extra->Err.MemParam.otag & 3 );
491 break;
492
493 case Err_User:
494 if (!extra->Err.User.isAddrErr)
495 MC_(any_value_errors) = True;
496 mc_pp_msg("ClientCheck", err,
497 "%s byte(s) found during client check request",
498 ( extra->Err.User.isAddrErr
499 ? "Unaddressable" : "Uninitialised" ));
500 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.User.ai,
501 False);
502 if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
503 mc_pp_origin( extra->Err.User.origin_ec,
504 extra->Err.User.otag & 3 );
505 break;
506
507 case Err_Free:
508 mc_pp_msg("InvalidFree", err,
509 "Invalid free() / delete / delete[]");
510 mc_pp_AddrInfo(VG_(get_error_address)(err),
511 &extra->Err.Free.ai, False);
512 break;
513
514 case Err_FreeMismatch:
515 mc_pp_msg("MismatchedFree", err,
516 "Mismatched free() / delete / delete []");
517 mc_pp_AddrInfo(VG_(get_error_address)(err),
518 &extra->Err.FreeMismatch.ai, False);
519 break;
520
521 case Err_Addr:
522 if (extra->Err.Addr.isWrite) {
523 mc_pp_msg("InvalidWrite", err,
524 "Invalid write of size %d",
525 extra->Err.Addr.szB);
526 } else {
527 mc_pp_msg("InvalidRead", err,
528 "Invalid read of size %d",
529 extra->Err.Addr.szB);
530 }
531 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Addr.ai,
532 extra->Err.Addr.maybe_gcc);
533 break;
534
535 case Err_Jump:
536 mc_pp_msg("InvalidJump", err,
537 "Jump to the invalid address stated on the next line");
538 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Jump.ai,
539 False);
540 break;
541
542 case Err_Overlap:
543 if (extra->Err.Overlap.szB == 0)
544 mc_pp_msg("Overlap", err,
545 "Source and destination overlap in %s(%p, %p)",
546 VG_(get_error_string)(err),
547 extra->Err.Overlap.dst, extra->Err.Overlap.src);
548 else
549 mc_pp_msg("Overlap", err,
550 "Source and destination overlap in %s(%p, %p, %d)",
551 VG_(get_error_string)(err),
552 extra->Err.Overlap.dst, extra->Err.Overlap.src,
553 extra->Err.Overlap.szB);
554 break;
555
556 case Err_IllegalMempool:
557 mc_pp_msg("InvalidMemPool", err,
558 "Illegal memory pool address");
559 mc_pp_AddrInfo(VG_(get_error_address)(err),
560 &extra->Err.IllegalMempool.ai, False);
561 break;
562
563 case Err_Leak: {
564 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
565 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
566 UInt n_this_record = extra->Err.Leak.n_this_record;
567 UInt n_total_records = extra->Err.Leak.n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000568 LossRecord* lr = extra->Err.Leak.lr;
sewardj7ce71662008-05-02 10:33:15 +0000569
570 if (VG_(clo_xml)) {
barta0b6b2c2008-07-07 06:49:24 +0000571 VG_(message_no_f_c)(Vg_UserMsg, " <kind>%t</kind>",
njn29a5c012009-05-06 06:15:55 +0000572 xml_leak_kind(lr->key.state));
sewardj7ce71662008-05-02 10:33:15 +0000573 } else {
574 VG_(message)(Vg_UserMsg, "");
575 }
576
njnb7a4e2e2009-05-01 00:30:43 +0000577 if (lr->indirect_szB > 0) {
sewardj7ce71662008-05-02 10:33:15 +0000578 VG_(message)(Vg_UserMsg,
barta0b6b2c2008-07-07 06:49:24 +0000579 "%s%'lu (%'lu direct, %'lu indirect) bytes in %'u blocks"
580 " are %s in loss record %'u of %'u%s",
sewardj7ce71662008-05-02 10:33:15 +0000581 xpre,
njnb7a4e2e2009-05-01 00:30:43 +0000582 lr->szB + lr->indirect_szB, lr->szB, lr->indirect_szB,
583 lr->num_blocks,
njn29a5c012009-05-06 06:15:55 +0000584 str_leak_lossmode(lr->key.state), n_this_record, n_total_records,
sewardj7ce71662008-05-02 10:33:15 +0000585 xpost
586 );
587 if (VG_(clo_xml)) {
588 // Nb: don't put commas in these XML numbers
589 VG_(message)(Vg_UserMsg, " <leakedbytes>%lu</leakedbytes>",
njnb7a4e2e2009-05-01 00:30:43 +0000590 lr->szB + lr->indirect_szB);
sewardj7ce71662008-05-02 10:33:15 +0000591 VG_(message)(Vg_UserMsg, " <leakedblocks>%u</leakedblocks>",
njnb7a4e2e2009-05-01 00:30:43 +0000592 lr->num_blocks);
sewardj7ce71662008-05-02 10:33:15 +0000593 }
594 } else {
595 VG_(message)(
596 Vg_UserMsg,
barta0b6b2c2008-07-07 06:49:24 +0000597 "%s%'lu bytes in %'u blocks are %s in loss record %'u of %'u%s",
sewardj7ce71662008-05-02 10:33:15 +0000598 xpre,
njnb7a4e2e2009-05-01 00:30:43 +0000599 lr->szB, lr->num_blocks,
njn29a5c012009-05-06 06:15:55 +0000600 str_leak_lossmode(lr->key.state), n_this_record, n_total_records,
sewardj7ce71662008-05-02 10:33:15 +0000601 xpost
602 );
603 if (VG_(clo_xml)) {
barta0b6b2c2008-07-07 06:49:24 +0000604 VG_(message)(Vg_UserMsg, " <leakedbytes>%ld</leakedbytes>",
njnb7a4e2e2009-05-01 00:30:43 +0000605 lr->szB);
sewardj7ce71662008-05-02 10:33:15 +0000606 VG_(message)(Vg_UserMsg, " <leakedblocks>%d</leakedblocks>",
njnb7a4e2e2009-05-01 00:30:43 +0000607 lr->num_blocks);
sewardj7ce71662008-05-02 10:33:15 +0000608 }
609 }
njn29a5c012009-05-06 06:15:55 +0000610 VG_(pp_ExeContext)(lr->key.allocated_at);
sewardj7ce71662008-05-02 10:33:15 +0000611 break;
612 }
613
614 default:
615 VG_(printf)("Error:\n unknown Memcheck error code %d\n",
616 VG_(get_error_kind)(err));
617 VG_(tool_panic)("unknown error code in mc_pp_Error)");
618 }
619}
620
621/*------------------------------------------------------------*/
622/*--- Recording errors ---*/
623/*------------------------------------------------------------*/
624
625/* These many bytes below %ESP are considered addressible if we're
626 doing the --workaround-gcc296-bugs hack. */
627#define VG_GCC296_BUG_STACK_SLOP 1024
628
629/* Is this address within some small distance below %ESP? Used only
630 for the --workaround-gcc296-bugs kludge. */
631static Bool is_just_below_ESP( Addr esp, Addr aa )
632{
633 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
634 return True;
635 else
636 return False;
637}
638
639/* --- Called from generated and non-generated code --- */
640
641void MC_(record_address_error) ( ThreadId tid, Addr a, Int szB,
642 Bool isWrite )
643{
644 MC_Error extra;
645 Bool just_below_esp;
646
647 if (MC_(in_ignored_range)(a))
648 return;
649
650# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
651 /* AIX zero-page handling. On AIX, reads from page zero are,
652 bizarrely enough, legitimate. Writes to page zero aren't,
653 though. Since memcheck can't distinguish reads from writes, the
654 best we can do is to 'act normal' and mark the A bits in the
655 normal way as noaccess, but then hide any reads from that page
656 that get reported here. */
657 if ((!isWrite) && a >= 0 && a < 4096 && a+szB <= 4096)
658 return;
659
660 /* Appalling AIX hack. It suppresses reads done by glink
661 fragments. Getting rid of this would require figuring out
662 somehow where the referenced data areas are (and their
663 sizes). */
664 if ((!isWrite) && szB == sizeof(Word)) {
665 UInt i1, i2;
666 UInt* pc = (UInt*)VG_(get_IP)(tid);
667 if (sizeof(Word) == 4) {
668 i1 = 0x800c0000; /* lwz r0,0(r12) */
669 i2 = 0x804c0004; /* lwz r2,4(r12) */
670 } else {
671 i1 = 0xe80c0000; /* ld r0,0(r12) */
672 i2 = 0xe84c0008; /* ld r2,8(r12) */
673 }
674 if (pc[0] == i1 && pc[1] == i2) return;
675 if (pc[0] == i2 && pc[-1] == i1) return;
676 }
677# endif
678
679 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
680
681 /* If this is caused by an access immediately below %ESP, and the
682 user asks nicely, we just ignore it. */
683 if (MC_(clo_workaround_gcc296_bugs) && just_below_esp)
684 return;
685
686 extra.Err.Addr.isWrite = isWrite;
687 extra.Err.Addr.szB = szB;
688 extra.Err.Addr.maybe_gcc = just_below_esp;
689 extra.Err.Addr.ai.tag = Addr_Undescribed;
690 VG_(maybe_record_error)( tid, Err_Addr, a, /*s*/NULL, &extra );
691}
692
693void MC_(record_value_error) ( ThreadId tid, Int szB, UInt otag )
694{
695 MC_Error extra;
696 tl_assert( MC_(clo_mc_level) >= 2 );
697 if (otag > 0)
698 tl_assert( MC_(clo_mc_level) == 3 );
699 extra.Err.Value.szB = szB;
700 extra.Err.Value.otag = otag;
701 extra.Err.Value.origin_ec = NULL; /* Filled in later */
702 VG_(maybe_record_error)( tid, Err_Value, /*addr*/0, /*s*/NULL, &extra );
703}
704
705void MC_(record_cond_error) ( ThreadId tid, UInt otag )
706{
707 MC_Error extra;
708 tl_assert( MC_(clo_mc_level) >= 2 );
709 if (otag > 0)
710 tl_assert( MC_(clo_mc_level) == 3 );
711 extra.Err.Cond.otag = otag;
712 extra.Err.Cond.origin_ec = NULL; /* Filled in later */
713 VG_(maybe_record_error)( tid, Err_Cond, /*addr*/0, /*s*/NULL, &extra );
714}
715
716/* --- Called from non-generated code --- */
717
njn1dcee092009-02-24 03:07:37 +0000718/* This is for memory errors in signal-related memory. */
719void MC_(record_core_mem_error) ( ThreadId tid, Char* msg )
sewardj7ce71662008-05-02 10:33:15 +0000720{
721 VG_(maybe_record_error)( tid, Err_CoreMem, /*addr*/0, msg, /*extra*/NULL );
722}
723
724void MC_(record_regparam_error) ( ThreadId tid, Char* msg, UInt otag )
725{
726 MC_Error extra;
727 tl_assert(VG_INVALID_THREADID != tid);
728 if (otag > 0)
729 tl_assert( MC_(clo_mc_level) == 3 );
730 extra.Err.RegParam.otag = otag;
731 extra.Err.RegParam.origin_ec = NULL; /* Filled in later */
732 VG_(maybe_record_error)( tid, Err_RegParam, /*addr*/0, msg, &extra );
733}
734
735void MC_(record_memparam_error) ( ThreadId tid, Addr a,
736 Bool isAddrErr, Char* msg, UInt otag )
737{
738 MC_Error extra;
739 tl_assert(VG_INVALID_THREADID != tid);
740 if (!isAddrErr)
741 tl_assert( MC_(clo_mc_level) >= 2 );
742 if (otag != 0) {
743 tl_assert( MC_(clo_mc_level) == 3 );
744 tl_assert( !isAddrErr );
745 }
746 extra.Err.MemParam.isAddrErr = isAddrErr;
747 extra.Err.MemParam.ai.tag = Addr_Undescribed;
748 extra.Err.MemParam.otag = otag;
749 extra.Err.MemParam.origin_ec = NULL; /* Filled in later */
750 VG_(maybe_record_error)( tid, Err_MemParam, a, msg, &extra );
751}
752
753void MC_(record_jump_error) ( ThreadId tid, Addr a )
754{
755 MC_Error extra;
756 tl_assert(VG_INVALID_THREADID != tid);
757 extra.Err.Jump.ai.tag = Addr_Undescribed;
758 VG_(maybe_record_error)( tid, Err_Jump, a, /*s*/NULL, &extra );
759}
760
761void MC_(record_free_error) ( ThreadId tid, Addr a )
762{
763 MC_Error extra;
764 tl_assert(VG_INVALID_THREADID != tid);
765 extra.Err.Free.ai.tag = Addr_Undescribed;
766 VG_(maybe_record_error)( tid, Err_Free, a, /*s*/NULL, &extra );
767}
768
769void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* mc )
770{
771 MC_Error extra;
772 AddrInfo* ai = &extra.Err.FreeMismatch.ai;
773 tl_assert(VG_INVALID_THREADID != tid);
774 ai->tag = Addr_Block;
775 ai->Addr.Block.block_kind = Block_Mallocd; // Nb: Not 'Block_Freed'
776 ai->Addr.Block.block_desc = "block";
777 ai->Addr.Block.block_szB = mc->szB;
778 ai->Addr.Block.rwoffset = 0;
779 ai->Addr.Block.lastchange = mc->where;
780 VG_(maybe_record_error)( tid, Err_FreeMismatch, mc->data, /*s*/NULL,
781 &extra );
782}
783
784void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
785{
786 MC_Error extra;
787 tl_assert(VG_INVALID_THREADID != tid);
788 extra.Err.IllegalMempool.ai.tag = Addr_Undescribed;
789 VG_(maybe_record_error)( tid, Err_IllegalMempool, a, /*s*/NULL, &extra );
790}
791
792void MC_(record_overlap_error) ( ThreadId tid, Char* function,
793 Addr src, Addr dst, SizeT szB )
794{
795 MC_Error extra;
796 tl_assert(VG_INVALID_THREADID != tid);
797 extra.Err.Overlap.src = src;
798 extra.Err.Overlap.dst = dst;
799 extra.Err.Overlap.szB = szB;
800 VG_(maybe_record_error)(
801 tid, Err_Overlap, /*addr*/0, /*s*/function, &extra );
802}
803
804Bool MC_(record_leak_error) ( ThreadId tid, UInt n_this_record,
njnb7a4e2e2009-05-01 00:30:43 +0000805 UInt n_total_records, LossRecord* lr,
sewardj7ce71662008-05-02 10:33:15 +0000806 Bool print_record )
807{
808 MC_Error extra;
809 extra.Err.Leak.n_this_record = n_this_record;
810 extra.Err.Leak.n_total_records = n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000811 extra.Err.Leak.lr = lr;
sewardj7ce71662008-05-02 10:33:15 +0000812 return
813 VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
njn29a5c012009-05-06 06:15:55 +0000814 lr->key.allocated_at, print_record,
sewardj7ce71662008-05-02 10:33:15 +0000815 /*allow_GDB_attach*/False, /*count_error*/False );
816}
817
818void MC_(record_user_error) ( ThreadId tid, Addr a,
819 Bool isAddrErr, UInt otag )
820{
821 MC_Error extra;
822 if (otag != 0) {
823 tl_assert(!isAddrErr);
824 tl_assert( MC_(clo_mc_level) == 3 );
825 }
826 if (!isAddrErr) {
827 tl_assert( MC_(clo_mc_level) >= 2 );
828 }
829 tl_assert(VG_INVALID_THREADID != tid);
830 extra.Err.User.isAddrErr = isAddrErr;
831 extra.Err.User.ai.tag = Addr_Undescribed;
832 extra.Err.User.otag = otag;
833 extra.Err.User.origin_ec = NULL; /* Filled in later */
834 VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra );
835}
836
837/*------------------------------------------------------------*/
838/*--- Other error operations ---*/
839/*------------------------------------------------------------*/
840
841/* Compare error contexts, to detect duplicates. Note that if they
842 are otherwise the same, the faulting addrs and associated rwoffsets
843 are allowed to be different. */
844Bool MC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
845{
846 MC_Error* extra1 = VG_(get_error_extra)(e1);
847 MC_Error* extra2 = VG_(get_error_extra)(e2);
848
849 /* Guaranteed by calling function */
850 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
851
852 switch (VG_(get_error_kind)(e1)) {
853 case Err_CoreMem: {
854 Char *e1s, *e2s;
855 e1s = VG_(get_error_string)(e1);
856 e2s = VG_(get_error_string)(e2);
857 if (e1s == e2s) return True;
858 if (VG_STREQ(e1s, e2s)) return True;
859 return False;
860 }
861
862 case Err_RegParam:
863 return VG_STREQ(VG_(get_error_string)(e1), VG_(get_error_string)(e2));
864
865 // Perhaps we should also check the addrinfo.akinds for equality.
866 // That would result in more error reports, but only in cases where
867 // a register contains uninitialised bytes and points to memory
868 // containing uninitialised bytes. Currently, the 2nd of those to be
869 // detected won't be reported. That is (nearly?) always the memory
870 // error, which is good.
871 case Err_MemParam:
872 if (!VG_STREQ(VG_(get_error_string)(e1),
873 VG_(get_error_string)(e2))) return False;
874 // fall through
875 case Err_User:
876 return ( extra1->Err.User.isAddrErr == extra2->Err.User.isAddrErr
877 ? True : False );
878
879 case Err_Free:
880 case Err_FreeMismatch:
881 case Err_Jump:
882 case Err_IllegalMempool:
883 case Err_Overlap:
884 case Err_Cond:
885 return True;
886
887 case Err_Addr:
888 return ( extra1->Err.Addr.szB == extra2->Err.Addr.szB
889 ? True : False );
890
891 case Err_Value:
892 return ( extra1->Err.Value.szB == extra2->Err.Value.szB
893 ? True : False );
894
895 case Err_Leak:
896 VG_(tool_panic)("Shouldn't get Err_Leak in mc_eq_Error,\n"
897 "since it's handled with VG_(unique_error)()!");
898
899 default:
900 VG_(printf)("Error:\n unknown error code %d\n",
901 VG_(get_error_kind)(e1));
902 VG_(tool_panic)("unknown error code in mc_eq_Error");
903 }
904}
905
906/* Function used when searching MC_Chunk lists */
907static Bool addr_is_in_MC_Chunk(MC_Chunk* mc, Addr a)
908{
909 // Nb: this is not quite right! It assumes that the heap block has
910 // a redzone of size MC_MALLOC_REDZONE_SZB. That's true for malloc'd
911 // blocks, but not necessarily true for custom-alloc'd blocks. So
912 // in some cases this could result in an incorrect description (eg.
913 // saying "12 bytes after block A" when really it's within block B.
914 // Fixing would require adding redzone size to MC_Chunks, though.
915 return VG_(addr_is_in_block)( a, mc->data, mc->szB,
916 MC_MALLOC_REDZONE_SZB );
917}
918
919// Forward declaration
920static Bool client_block_maybe_describe( Addr a, AddrInfo* ai );
921
922
923/* Describe an address as best you can, for error messages,
924 putting the result in ai. */
925static void describe_addr ( Addr a, /*OUT*/AddrInfo* ai )
926{
927 MC_Chunk* mc;
928 ThreadId tid;
929 Addr stack_min, stack_max;
930 VgSectKind sect;
931
932 tl_assert(Addr_Undescribed == ai->tag);
933
934 /* Perhaps it's a user-def'd block? */
935 if (client_block_maybe_describe( a, ai )) {
936 return;
937 }
938 /* Search for a recently freed block which might bracket it. */
939 mc = MC_(get_freed_list_head)();
940 while (mc) {
941 if (addr_is_in_MC_Chunk(mc, a)) {
942 ai->tag = Addr_Block;
943 ai->Addr.Block.block_kind = Block_Freed;
944 ai->Addr.Block.block_desc = "block";
945 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +0000946 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +0000947 ai->Addr.Block.lastchange = mc->where;
948 return;
949 }
950 mc = mc->next;
951 }
952 /* Search for a currently malloc'd block which might bracket it. */
953 VG_(HT_ResetIter)(MC_(malloc_list));
954 while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
955 if (addr_is_in_MC_Chunk(mc, a)) {
956 ai->tag = Addr_Block;
957 ai->Addr.Block.block_kind = Block_Mallocd;
958 ai->Addr.Block.block_desc = "block";
959 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +0000960 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +0000961 ai->Addr.Block.lastchange = mc->where;
962 return;
963 }
964 }
965 /* Perhaps the variable type/location data describes it? */
966 tl_assert(sizeof(ai->Addr.Variable.descr1)
967 == sizeof(ai->Addr.Variable.descr2));
968 VG_(memset)( &ai->Addr.Variable.descr1,
969 0, sizeof(ai->Addr.Variable.descr1));
970 VG_(memset)( &ai->Addr.Variable.descr2,
971 0, sizeof(ai->Addr.Variable.descr2));
972 if (VG_(get_data_description)(
973 &ai->Addr.Variable.descr1[0],
974 &ai->Addr.Variable.descr2[0],
975 sizeof(ai->Addr.Variable.descr1)-1,
976 a )) {
977 ai->tag = Addr_Variable;
978 tl_assert( ai->Addr.Variable.descr1
979 [ sizeof(ai->Addr.Variable.descr1)-1 ] == 0);
980 tl_assert( ai->Addr.Variable.descr2
981 [ sizeof(ai->Addr.Variable.descr2)-1 ] == 0);
982 return;
983 }
984 /* Have a look at the low level data symbols - perhaps it's in
985 there. */
986 VG_(memset)( &ai->Addr.DataSym.name,
987 0, sizeof(ai->Addr.DataSym.name));
988 if (VG_(get_datasym_and_offset)(
989 a, &ai->Addr.DataSym.name[0],
990 sizeof(ai->Addr.DataSym.name)-1,
991 &ai->Addr.DataSym.offset )) {
992 ai->tag = Addr_DataSym;
993 tl_assert( ai->Addr.DataSym.name
994 [ sizeof(ai->Addr.DataSym.name)-1 ] == 0);
995 return;
996 }
997 /* Perhaps it's on a thread's stack? */
998 VG_(thread_stack_reset_iter)(&tid);
999 while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
1000 if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
1001 ai->tag = Addr_Stack;
1002 ai->Addr.Stack.tid = tid;
1003 return;
1004 }
1005 }
1006 /* last ditch attempt at classification */
1007 tl_assert( sizeof(ai->Addr.SectKind.objname) > 4 );
1008 VG_(memset)( &ai->Addr.SectKind.objname,
1009 0, sizeof(ai->Addr.SectKind.objname));
1010 VG_(strcpy)( ai->Addr.SectKind.objname, "???" );
1011 sect = VG_(seginfo_sect_kind)( &ai->Addr.SectKind.objname[0],
1012 sizeof(ai->Addr.SectKind.objname)-1, a);
1013 if (sect != Vg_SectUnknown) {
1014 ai->tag = Addr_SectKind;
1015 ai->Addr.SectKind.kind = sect;
1016 tl_assert( ai->Addr.SectKind.objname
1017 [ sizeof(ai->Addr.SectKind.objname)-1 ] == 0);
1018 return;
1019 }
1020 /* Clueless ... */
1021 ai->tag = Addr_Unknown;
1022 return;
1023}
1024
1025/* Fill in *origin_ec as specified by otag, or NULL it out if otag
1026 does not refer to a known origin. */
1027static void update_origin ( /*OUT*/ExeContext** origin_ec,
1028 UInt otag )
1029{
1030 UInt ecu = otag & ~3;
1031 *origin_ec = NULL;
1032 if (VG_(is_plausible_ECU)(ecu)) {
1033 *origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
1034 }
1035}
1036
1037/* Updates the copy with address info if necessary (but not for all errors). */
1038UInt MC_(update_Error_extra)( Error* err )
1039{
1040 MC_Error* extra = VG_(get_error_extra)(err);
1041
1042 switch (VG_(get_error_kind)(err)) {
1043 // These ones don't have addresses associated with them, and so don't
1044 // need any updating.
1045 case Err_CoreMem:
1046 //case Err_Value:
1047 //case Err_Cond:
1048 case Err_Overlap:
1049 // For Err_Leaks the returned size does not matter -- they are always
1050 // shown with VG_(unique_error)() so they 'extra' not copied. But
1051 // we make it consistent with the others.
1052 case Err_Leak:
1053 return sizeof(MC_Error);
1054
1055 // For value errors, get the ExeContext corresponding to the
1056 // origin tag. Note that it is a kludge to assume that
1057 // a length-1 trace indicates a stack origin. FIXME.
1058 case Err_Value:
1059 update_origin( &extra->Err.Value.origin_ec,
1060 extra->Err.Value.otag );
1061 return sizeof(MC_Error);
1062 case Err_Cond:
1063 update_origin( &extra->Err.Cond.origin_ec,
1064 extra->Err.Cond.otag );
1065 return sizeof(MC_Error);
1066 case Err_RegParam:
1067 update_origin( &extra->Err.RegParam.origin_ec,
1068 extra->Err.RegParam.otag );
1069 return sizeof(MC_Error);
1070
1071 // These ones always involve a memory address.
1072 case Err_Addr:
1073 describe_addr ( VG_(get_error_address)(err),
1074 &extra->Err.Addr.ai );
1075 return sizeof(MC_Error);
1076 case Err_MemParam:
1077 describe_addr ( VG_(get_error_address)(err),
1078 &extra->Err.MemParam.ai );
1079 update_origin( &extra->Err.MemParam.origin_ec,
1080 extra->Err.MemParam.otag );
1081 return sizeof(MC_Error);
1082 case Err_Jump:
1083 describe_addr ( VG_(get_error_address)(err),
1084 &extra->Err.Jump.ai );
1085 return sizeof(MC_Error);
1086 case Err_User:
1087 describe_addr ( VG_(get_error_address)(err),
1088 &extra->Err.User.ai );
1089 update_origin( &extra->Err.User.origin_ec,
1090 extra->Err.User.otag );
1091 return sizeof(MC_Error);
1092 case Err_Free:
1093 describe_addr ( VG_(get_error_address)(err),
1094 &extra->Err.Free.ai );
1095 return sizeof(MC_Error);
1096 case Err_IllegalMempool:
1097 describe_addr ( VG_(get_error_address)(err),
1098 &extra->Err.IllegalMempool.ai );
1099 return sizeof(MC_Error);
1100
1101 // Err_FreeMismatches have already had their address described; this is
1102 // possible because we have the MC_Chunk on hand when the error is
1103 // detected. However, the address may be part of a user block, and if so
1104 // we override the pre-determined description with a user block one.
1105 case Err_FreeMismatch: {
1106 tl_assert(extra && Block_Mallocd ==
1107 extra->Err.FreeMismatch.ai.Addr.Block.block_kind);
1108 (void)client_block_maybe_describe( VG_(get_error_address)(err),
1109 &extra->Err.FreeMismatch.ai );
1110 return sizeof(MC_Error);
1111 }
1112
1113 default: VG_(tool_panic)("mc_update_extra: bad errkind");
1114 }
1115}
1116
1117// FIXME: does this perhaps want to live somewhere else
1118// in this file?
1119static Bool client_block_maybe_describe( Addr a,
1120 /*OUT*/AddrInfo* ai )
1121{
sewardj56adc352008-05-02 11:25:17 +00001122 UWord i;
sewardj7ce71662008-05-02 10:33:15 +00001123 CGenBlock* cgbs = NULL;
1124 UWord cgb_used = 0;
sewardj56adc352008-05-02 11:25:17 +00001125
sewardj7ce71662008-05-02 10:33:15 +00001126 MC_(get_ClientBlock_array)( &cgbs, &cgb_used );
1127 if (cgbs == NULL)
1128 tl_assert(cgb_used == 0);
1129
1130 /* Perhaps it's a general block ? */
1131 for (i = 0; i < cgb_used; i++) {
1132 if (cgbs[i].start == 0 && cgbs[i].size == 0)
1133 continue;
1134 // Use zero as the redzone for client blocks.
1135 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
1136 /* OK - maybe it's a mempool, too? */
1137 MC_Mempool* mp = VG_(HT_lookup)(MC_(mempool_list),
1138 (UWord)cgbs[i].start);
1139 if (mp != NULL) {
1140 if (mp->chunks != NULL) {
1141 MC_Chunk* mc;
1142 VG_(HT_ResetIter)(mp->chunks);
1143 while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
1144 if (addr_is_in_MC_Chunk(mc, a)) {
1145 ai->tag = Addr_Block;
1146 ai->Addr.Block.block_kind = Block_MempoolChunk;
1147 ai->Addr.Block.block_desc = "block";
1148 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +00001149 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +00001150 ai->Addr.Block.lastchange = mc->where;
1151 return True;
1152 }
1153 }
1154 }
1155 ai->tag = Addr_Block;
1156 ai->Addr.Block.block_kind = Block_Mempool;
1157 ai->Addr.Block.block_desc = "mempool";
1158 ai->Addr.Block.block_szB = cgbs[i].size;
sewardj56adc352008-05-02 11:25:17 +00001159 ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
sewardj7ce71662008-05-02 10:33:15 +00001160 ai->Addr.Block.lastchange = cgbs[i].where;
1161 return True;
1162 }
1163 ai->tag = Addr_Block;
1164 ai->Addr.Block.block_kind = Block_UserG;
1165 ai->Addr.Block.block_desc = cgbs[i].desc;
1166 ai->Addr.Block.block_szB = cgbs[i].size;
sewardj56adc352008-05-02 11:25:17 +00001167 ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
sewardj7ce71662008-05-02 10:33:15 +00001168 ai->Addr.Block.lastchange = cgbs[i].where;
1169 return True;
1170 }
1171 }
1172 return False;
1173}
1174
1175
1176/*------------------------------------------------------------*/
1177/*--- Suppressions ---*/
1178/*------------------------------------------------------------*/
1179
1180typedef
1181 enum {
1182 ParamSupp, // Bad syscall params
1183 UserSupp, // Errors arising from client-request checks
1184 CoreMemSupp, // Memory errors in core (pthread ops, signal handling)
1185
1186 // Undefined value errors of given size
1187 Value1Supp, Value2Supp, Value4Supp, Value8Supp, Value16Supp,
1188
1189 // Undefined value error in conditional.
1190 CondSupp,
1191
1192 // Unaddressable read/write attempt at given size
1193 Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp, Addr16Supp,
1194
1195 JumpSupp, // Jump to unaddressable target
1196 FreeSupp, // Invalid or mismatching free
1197 OverlapSupp, // Overlapping blocks in memcpy(), strcpy(), etc
1198 LeakSupp, // Something to be suppressed in a leak check.
1199 MempoolSupp, // Memory pool suppression.
1200 }
1201 MC_SuppKind;
1202
1203Bool MC_(is_recognised_suppression) ( Char* name, Supp* su )
1204{
1205 SuppKind skind;
1206
1207 if (VG_STREQ(name, "Param")) skind = ParamSupp;
1208 else if (VG_STREQ(name, "User")) skind = UserSupp;
1209 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
1210 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
1211 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
1212 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
1213 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
1214 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
1215 else if (VG_STREQ(name, "Jump")) skind = JumpSupp;
1216 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
1217 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
1218 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
1219 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
1220 else if (VG_STREQ(name, "Cond")) skind = CondSupp;
1221 else if (VG_STREQ(name, "Value0")) skind = CondSupp; /* backwards compat */
1222 else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
1223 else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
1224 else if (VG_STREQ(name, "Value4")) skind = Value4Supp;
1225 else if (VG_STREQ(name, "Value8")) skind = Value8Supp;
1226 else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
1227 else
1228 return False;
1229
1230 VG_(set_supp_kind)(su, skind);
1231 return True;
1232}
1233
1234Bool MC_(read_extra_suppression_info) ( Int fd, Char* buf,
1235 Int nBuf, Supp *su )
1236{
1237 Bool eof;
1238
1239 if (VG_(get_supp_kind)(su) == ParamSupp) {
1240 eof = VG_(get_line) ( fd, buf, nBuf );
1241 if (eof) return False;
sewardj9c606bd2008-09-18 18:12:50 +00001242 VG_(set_supp_string)(su, VG_(strdup)("mc.resi.1", buf));
sewardj7ce71662008-05-02 10:33:15 +00001243 }
1244 return True;
1245}
1246
1247Bool MC_(error_matches_suppression) ( Error* err, Supp* su )
1248{
1249 Int su_szB;
1250 MC_Error* extra = VG_(get_error_extra)(err);
1251 ErrorKind ekind = VG_(get_error_kind )(err);
1252
1253 switch (VG_(get_supp_kind)(su)) {
1254 case ParamSupp:
1255 return ((ekind == Err_RegParam || ekind == Err_MemParam)
1256 && VG_STREQ(VG_(get_error_string)(err),
1257 VG_(get_supp_string)(su)));
1258
1259 case UserSupp:
1260 return (ekind == Err_User);
1261
1262 case CoreMemSupp:
1263 return (ekind == Err_CoreMem
1264 && VG_STREQ(VG_(get_error_string)(err),
1265 VG_(get_supp_string)(su)));
1266
1267 case Value1Supp: su_szB = 1; goto value_case;
1268 case Value2Supp: su_szB = 2; goto value_case;
1269 case Value4Supp: su_szB = 4; goto value_case;
1270 case Value8Supp: su_szB = 8; goto value_case;
1271 case Value16Supp:su_szB =16; goto value_case;
1272 value_case:
1273 return (ekind == Err_Value && extra->Err.Value.szB == su_szB);
1274
1275 case CondSupp:
1276 return (ekind == Err_Cond);
1277
1278 case Addr1Supp: su_szB = 1; goto addr_case;
1279 case Addr2Supp: su_szB = 2; goto addr_case;
1280 case Addr4Supp: su_szB = 4; goto addr_case;
1281 case Addr8Supp: su_szB = 8; goto addr_case;
1282 case Addr16Supp:su_szB =16; goto addr_case;
1283 addr_case:
1284 return (ekind == Err_Addr && extra->Err.Addr.szB == su_szB);
1285
1286 case JumpSupp:
1287 return (ekind == Err_Jump);
1288
1289 case FreeSupp:
1290 return (ekind == Err_Free || ekind == Err_FreeMismatch);
1291
1292 case OverlapSupp:
1293 return (ekind == Err_Overlap);
1294
1295 case LeakSupp:
1296 return (ekind == Err_Leak);
1297
1298 case MempoolSupp:
1299 return (ekind == Err_IllegalMempool);
1300
1301 default:
1302 VG_(printf)("Error:\n"
1303 " unknown suppression type %d\n",
1304 VG_(get_supp_kind)(su));
1305 VG_(tool_panic)("unknown suppression type in "
1306 "MC_(error_matches_suppression)");
1307 }
1308}
1309
1310Char* MC_(get_error_name) ( Error* err )
1311{
1312 switch (VG_(get_error_kind)(err)) {
1313 case Err_RegParam: return "Param";
1314 case Err_MemParam: return "Param";
1315 case Err_User: return "User";
1316 case Err_FreeMismatch: return "Free";
1317 case Err_IllegalMempool: return "Mempool";
1318 case Err_Free: return "Free";
1319 case Err_Jump: return "Jump";
1320 case Err_CoreMem: return "CoreMem";
1321 case Err_Overlap: return "Overlap";
1322 case Err_Leak: return "Leak";
1323 case Err_Cond: return "Cond";
1324 case Err_Addr: {
1325 MC_Error* extra = VG_(get_error_extra)(err);
1326 switch ( extra->Err.Addr.szB ) {
1327 case 1: return "Addr1";
1328 case 2: return "Addr2";
1329 case 4: return "Addr4";
1330 case 8: return "Addr8";
1331 case 16: return "Addr16";
1332 default: VG_(tool_panic)("unexpected size for Addr");
1333 }
1334 }
1335 case Err_Value: {
1336 MC_Error* extra = VG_(get_error_extra)(err);
1337 switch ( extra->Err.Value.szB ) {
1338 case 1: return "Value1";
1339 case 2: return "Value2";
1340 case 4: return "Value4";
1341 case 8: return "Value8";
1342 case 16: return "Value16";
1343 default: VG_(tool_panic)("unexpected size for Value");
1344 }
1345 }
1346 default: VG_(tool_panic)("get_error_name: unexpected type");
1347 }
1348}
1349
1350void MC_(print_extra_suppression_info) ( Error* err )
1351{
1352 ErrorKind ekind = VG_(get_error_kind )(err);
1353 if (Err_RegParam == ekind || Err_MemParam == ekind) {
1354 VG_(printf)(" %s\n", VG_(get_error_string)(err));
1355 }
1356}
1357
1358
1359/*--------------------------------------------------------------------*/
1360/*--- end mc_errors.c ---*/
1361/*--------------------------------------------------------------------*/