blob: 00f09fcecca8c3654b504d0824ee063de9fa12f0 [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
sewardj9eecbbb2010-05-03 21:37:12 +000011 Copyright (C) 2000-2010 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)
sewardj6b523cd2009-07-15 14:49:40 +000044#include "pub_tool_xarray.h"
sewardj7ce71662008-05-02 10:33:15 +000045
46#include "mc_include.h"
sewardj7ce71662008-05-02 10:33:15 +000047
48
49/*------------------------------------------------------------*/
50/*--- Error types ---*/
51/*------------------------------------------------------------*/
52
53/* See comment in mc_include.h */
54Bool MC_(any_value_errors) = False;
55
56
57// Different kinds of blocks.
58typedef enum {
59 Block_Mallocd = 111,
60 Block_Freed,
61 Block_Mempool,
62 Block_MempoolChunk,
63 Block_UserG
64} BlockKind;
65
66/* ------------------ Addresses -------------------- */
67
68/* The classification of a faulting address. */
69typedef
70 enum {
71 Addr_Undescribed, // as-yet unclassified
72 Addr_Unknown, // classification yielded nothing useful
73 Addr_Block, // in malloc'd/free'd block
74 Addr_Stack, // on a thread's stack
75 Addr_DataSym, // in a global data sym
76 Addr_Variable, // variable described by the debug info
77 Addr_SectKind // last-ditch classification attempt
78 }
79 AddrTag;
80
81typedef
82 struct _AddrInfo
83 AddrInfo;
84
85struct _AddrInfo {
86 AddrTag tag;
87 union {
88 // As-yet unclassified.
89 struct { } Undescribed;
90
91 // On a stack.
92 struct {
93 ThreadId tid; // Which thread's stack?
94 } Stack;
95
96 // This covers heap blocks (normal and from mempools) and user-defined
97 // blocks.
98 struct {
99 BlockKind block_kind;
100 Char* block_desc; // "block", "mempool" or user-defined
101 SizeT block_szB;
njnc4431bf2009-01-15 21:29:24 +0000102 PtrdiffT rwoffset;
sewardj7ce71662008-05-02 10:33:15 +0000103 ExeContext* lastchange;
104 } Block;
105
njnc4431bf2009-01-15 21:29:24 +0000106 // In a global .data symbol. This holds the first 127 chars of
107 // the variable's name (zero terminated), plus a (memory) offset.
sewardj7ce71662008-05-02 10:33:15 +0000108 struct {
njnc4431bf2009-01-15 21:29:24 +0000109 Char name[128];
110 PtrdiffT offset;
sewardj7ce71662008-05-02 10:33:15 +0000111 } DataSym;
112
sewardj6b523cd2009-07-15 14:49:40 +0000113 // Is described by Dwarf debug info. XArray*s of HChar.
sewardj7ce71662008-05-02 10:33:15 +0000114 struct {
sewardj6b523cd2009-07-15 14:49:40 +0000115 XArray* /* of HChar */ descr1;
116 XArray* /* of HChar */ descr2;
sewardj7ce71662008-05-02 10:33:15 +0000117 } 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
sewardj6b523cd2009-07-15 14:49:40 +0000261/* This is the "this error is due to be printed shortly; so have a
262 look at it any print any preamble you want" function. Which, in
263 Memcheck, we don't use. Hence a no-op.
264*/
265void MC_(before_pp_Error) ( Error* err ) {
266}
267
268/* Do a printf-style operation on either the XML or normal output
269 channel, depending on the setting of VG_(clo_xml).
270*/
271static void emit_WRK ( HChar* format, va_list vargs )
272{
273 if (VG_(clo_xml)) {
274 VG_(vprintf_xml)(format, vargs);
275 } else {
276 VG_(vmessage)(Vg_UserMsg, format, vargs);
277 }
278}
279static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
280static void emit ( HChar* format, ... )
281{
282 va_list vargs;
283 va_start(vargs, format);
284 emit_WRK(format, vargs);
285 va_end(vargs);
286}
287static void emiN ( HChar* format, ... ) /* NO FORMAT CHECK */
288{
289 va_list vargs;
290 va_start(vargs, format);
291 emit_WRK(format, vargs);
292 va_end(vargs);
293}
294
295
sewardj7ce71662008-05-02 10:33:15 +0000296static void mc_pp_AddrInfo ( Addr a, AddrInfo* ai, Bool maybe_gcc )
297{
298 HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
299 HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
300
301 switch (ai->tag) {
302 case Addr_Unknown:
303 if (maybe_gcc) {
sewardj6b523cd2009-07-15 14:49:40 +0000304 emit( "%sAddress 0x%llx is just below the stack ptr. "
305 "To suppress, use: --workaround-gcc296-bugs=yes%s\n",
306 xpre, (ULong)a, xpost );
sewardj7ce71662008-05-02 10:33:15 +0000307 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000308 emit( "%sAddress 0x%llx "
309 "is not stack'd, malloc'd or (recently) free'd%s\n",
310 xpre, (ULong)a, xpost );
sewardj7ce71662008-05-02 10:33:15 +0000311 }
312 break;
313
314 case Addr_Stack:
sewardj6b523cd2009-07-15 14:49:40 +0000315 emit( "%sAddress 0x%llx is on thread %d's stack%s\n",
316 xpre, (ULong)a, ai->Addr.Stack.tid, xpost );
sewardj7ce71662008-05-02 10:33:15 +0000317 break;
318
319 case Addr_Block: {
njnc4431bf2009-01-15 21:29:24 +0000320 SizeT block_szB = ai->Addr.Block.block_szB;
321 PtrdiffT rwoffset = ai->Addr.Block.rwoffset;
322 SizeT delta;
323 const Char* relative;
sewardj7ce71662008-05-02 10:33:15 +0000324
325 if (rwoffset < 0) {
326 delta = (SizeT)(-rwoffset);
327 relative = "before";
328 } else if (rwoffset >= block_szB) {
329 delta = rwoffset - block_szB;
330 relative = "after";
331 } else {
332 delta = rwoffset;
333 relative = "inside";
334 }
sewardj6b523cd2009-07-15 14:49:40 +0000335 emit(
336 "%sAddress 0x%lx is %'lu bytes %s a %s of size %'lu %s%s\n",
sewardj7ce71662008-05-02 10:33:15 +0000337 xpre,
338 a, delta, relative, ai->Addr.Block.block_desc,
339 block_szB,
340 ai->Addr.Block.block_kind==Block_Mallocd ? "alloc'd"
341 : ai->Addr.Block.block_kind==Block_Freed ? "free'd"
342 : "client-defined",
sewardj6b523cd2009-07-15 14:49:40 +0000343 xpost
344 );
sewardj7ce71662008-05-02 10:33:15 +0000345 VG_(pp_ExeContext)(ai->Addr.Block.lastchange);
346 break;
347 }
348
349 case Addr_DataSym:
sewardj6b523cd2009-07-15 14:49:40 +0000350 emiN( "%sAddress 0x%llx is %llu bytes "
351 "inside data symbol \"%t\"%s\n",
352 xpre,
353 (ULong)a,
354 (ULong)ai->Addr.DataSym.offset,
355 ai->Addr.DataSym.name,
356 xpost );
sewardj7ce71662008-05-02 10:33:15 +0000357 break;
358
359 case Addr_Variable:
sewardj6b523cd2009-07-15 14:49:40 +0000360 /* Note, no need for XML tags here, because descr1/2 will
361 already have <auxwhat> or <xauxwhat>s on them, in XML
362 mode. */
363 if (ai->Addr.Variable.descr1)
364 emit( "%s%s\n",
365 VG_(clo_xml) ? " " : " ",
366 (HChar*)VG_(indexXA)(ai->Addr.Variable.descr1, 0) );
367 if (ai->Addr.Variable.descr2)
368 emit( "%s%s\n",
369 VG_(clo_xml) ? " " : " ",
370 (HChar*)VG_(indexXA)(ai->Addr.Variable.descr2, 0) );
sewardj7ce71662008-05-02 10:33:15 +0000371 break;
372
373 case Addr_SectKind:
sewardj6b523cd2009-07-15 14:49:40 +0000374 emiN( "%sAddress 0x%llx is in the %t segment of %t%s\n",
375 xpre,
376 (ULong)a,
377 VG_(pp_SectKind)(ai->Addr.SectKind.kind),
378 ai->Addr.SectKind.objname,
379 xpost );
sewardj7ce71662008-05-02 10:33:15 +0000380 break;
381
382 default:
383 VG_(tool_panic)("mc_pp_AddrInfo");
384 }
385}
386
387static const HChar* str_leak_lossmode ( Reachedness lossmode )
388{
389 const HChar *loss = "?";
390 switch (lossmode) {
391 case Unreached: loss = "definitely lost"; break;
392 case IndirectLeak: loss = "indirectly lost"; break;
njn8225cc02009-03-09 22:52:24 +0000393 case Possible: loss = "possibly lost"; break;
394 case Reachable: loss = "still reachable"; break;
sewardj7ce71662008-05-02 10:33:15 +0000395 }
396 return loss;
397}
398
399static const HChar* xml_leak_kind ( Reachedness lossmode )
400{
401 const HChar *loss = "?";
402 switch (lossmode) {
403 case Unreached: loss = "Leak_DefinitelyLost"; break;
404 case IndirectLeak: loss = "Leak_IndirectlyLost"; break;
njn8225cc02009-03-09 22:52:24 +0000405 case Possible: loss = "Leak_PossiblyLost"; break;
406 case Reachable: loss = "Leak_StillReachable"; break;
sewardj7ce71662008-05-02 10:33:15 +0000407 }
408 return loss;
409}
410
sewardj7ce71662008-05-02 10:33:15 +0000411static void mc_pp_origin ( ExeContext* ec, UInt okind )
412{
sewardj6b523cd2009-07-15 14:49:40 +0000413 HChar* src = NULL;
sewardj7ce71662008-05-02 10:33:15 +0000414 tl_assert(ec);
415
416 switch (okind) {
417 case MC_OKIND_STACK: src = " by a stack allocation"; break;
418 case MC_OKIND_HEAP: src = " by a heap allocation"; break;
419 case MC_OKIND_USER: src = " by a client request"; break;
420 case MC_OKIND_UNKNOWN: src = ""; break;
421 }
422 tl_assert(src); /* guards against invalid 'okind' */
423
424 if (VG_(clo_xml)) {
sewardj6b523cd2009-07-15 14:49:40 +0000425 emit( " <auxwhat>Uninitialised value was created%s</auxwhat>\n",
426 src);
427 VG_(pp_ExeContext)( ec );
428 } else {
429 emit( " Uninitialised value was created%s\n", src);
430 VG_(pp_ExeContext)( ec );
sewardj7ce71662008-05-02 10:33:15 +0000431 }
432}
433
434void MC_(pp_Error) ( Error* err )
435{
sewardj6b523cd2009-07-15 14:49:40 +0000436 const Bool xml = VG_(clo_xml); /* a shorthand */
sewardj7ce71662008-05-02 10:33:15 +0000437 MC_Error* extra = VG_(get_error_extra)(err);
438
439 switch (VG_(get_error_kind)(err)) {
sewardj6b523cd2009-07-15 14:49:40 +0000440 case Err_CoreMem:
sewardj7ce71662008-05-02 10:33:15 +0000441 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
442 /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
443 signal handler frame. --njn */
sewardj6b523cd2009-07-15 14:49:40 +0000444 // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
445 // the following code is untested. Bad.
446 if (xml) {
447 emit( " <kind>CoreMemError</kind>\n" );
448 emiN( " <what>%t contains unaddressable byte(s)</what>\n",
449 VG_(get_error_string)(err));
450 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
451 } else {
452 emit( "%s contains unaddressable byte(s)\n",
453 VG_(get_error_string)(err));
454 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
455 }
sewardj7ce71662008-05-02 10:33:15 +0000456 break;
sewardj7ce71662008-05-02 10:33:15 +0000457
458 case Err_Value:
459 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000460 if (xml) {
461 emit( " <kind>UninitValue</kind>\n" );
462 emit( " <what>Use of uninitialised value of size %ld</what>\n",
463 extra->Err.Value.szB );
464 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
465 if (extra->Err.Value.origin_ec)
466 mc_pp_origin( extra->Err.Value.origin_ec,
467 extra->Err.Value.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000468 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000469 /* Could also show extra->Err.Cond.otag if debugging origin
470 tracking */
471 emit( "Use of uninitialised value of size %ld\n",
472 extra->Err.Value.szB );
473 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
474 if (extra->Err.Value.origin_ec)
475 mc_pp_origin( extra->Err.Value.origin_ec,
476 extra->Err.Value.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000477 }
sewardj7ce71662008-05-02 10:33:15 +0000478 break;
479
480 case Err_Cond:
481 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000482 if (xml) {
483 emit( " <kind>UninitCondition</kind>\n" );
484 emit( " <what>Conditional jump or move depends"
485 " on uninitialised value(s)</what>\n" );
486 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
487 if (extra->Err.Cond.origin_ec)
488 mc_pp_origin( extra->Err.Cond.origin_ec,
489 extra->Err.Cond.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000490 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000491 /* Could also show extra->Err.Cond.otag if debugging origin
492 tracking */
493 emit( "Conditional jump or move depends"
494 " on uninitialised value(s)\n" );
495 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
496 if (extra->Err.Cond.origin_ec)
497 mc_pp_origin( extra->Err.Cond.origin_ec,
498 extra->Err.Cond.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000499 }
sewardj7ce71662008-05-02 10:33:15 +0000500 break;
501
502 case Err_RegParam:
503 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000504 if (xml) {
505 emit( " <kind>SyscallParam</kind>\n" );
506 emiN( " <what>Syscall param %t contains "
507 "uninitialised byte(s)</what>\n",
508 VG_(get_error_string)(err) );
509 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
510 if (extra->Err.RegParam.origin_ec)
511 mc_pp_origin( extra->Err.RegParam.origin_ec,
512 extra->Err.RegParam.otag & 3 );
513 } else {
514 emit( "Syscall param %s contains uninitialised byte(s)\n",
515 VG_(get_error_string)(err) );
516 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
517 if (extra->Err.RegParam.origin_ec)
518 mc_pp_origin( extra->Err.RegParam.origin_ec,
519 extra->Err.RegParam.otag & 3 );
520 }
sewardj7ce71662008-05-02 10:33:15 +0000521 break;
522
523 case Err_MemParam:
524 if (!extra->Err.MemParam.isAddrErr)
525 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000526 if (xml) {
527 emit( " <kind>SyscallParam</kind>\n" );
528 emiN( " <what>Syscall param %t points to %s byte(s)</what>\n",
529 VG_(get_error_string)(err),
530 extra->Err.MemParam.isAddrErr
531 ? "unaddressable" : "uninitialised" );
532 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
533 mc_pp_AddrInfo(VG_(get_error_address)(err),
534 &extra->Err.MemParam.ai, False);
535 if (extra->Err.MemParam.origin_ec
536 && !extra->Err.MemParam.isAddrErr)
537 mc_pp_origin( extra->Err.MemParam.origin_ec,
538 extra->Err.MemParam.otag & 3 );
539 } else {
540 emit( "Syscall param %s points to %s byte(s)\n",
541 VG_(get_error_string)(err),
542 extra->Err.MemParam.isAddrErr
543 ? "unaddressable" : "uninitialised" );
544 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
545 mc_pp_AddrInfo(VG_(get_error_address)(err),
546 &extra->Err.MemParam.ai, False);
547 if (extra->Err.MemParam.origin_ec
548 && !extra->Err.MemParam.isAddrErr)
549 mc_pp_origin( extra->Err.MemParam.origin_ec,
550 extra->Err.MemParam.otag & 3 );
551 }
sewardj7ce71662008-05-02 10:33:15 +0000552 break;
553
554 case Err_User:
555 if (!extra->Err.User.isAddrErr)
556 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000557 if (xml) {
558 emit( " <kind>ClientCheck</kind>\n" );
559 emit( " <what>%s byte(s) found "
560 "during client check request</what>\n",
561 extra->Err.User.isAddrErr
562 ? "Unaddressable" : "Uninitialised" );
563 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
564 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.User.ai,
565 False);
566 if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
567 mc_pp_origin( extra->Err.User.origin_ec,
568 extra->Err.User.otag & 3 );
569 } else {
570 emit( "%s byte(s) found during client check request\n",
571 extra->Err.User.isAddrErr
572 ? "Unaddressable" : "Uninitialised" );
573 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
574 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.User.ai,
575 False);
576 if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
577 mc_pp_origin( extra->Err.User.origin_ec,
578 extra->Err.User.otag & 3 );
579 }
sewardj7ce71662008-05-02 10:33:15 +0000580 break;
581
582 case Err_Free:
sewardj6b523cd2009-07-15 14:49:40 +0000583 if (xml) {
584 emit( " <kind>InvalidFree</kind>\n" );
585 emit( " <what>Invalid free() / delete / delete[]</what>\n" );
586 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
587 mc_pp_AddrInfo( VG_(get_error_address)(err),
588 &extra->Err.Free.ai, False );
589 } else {
590 emit( "Invalid free() / delete / delete[]\n" );
591 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
592 mc_pp_AddrInfo( VG_(get_error_address)(err),
593 &extra->Err.Free.ai, False );
594 }
sewardj7ce71662008-05-02 10:33:15 +0000595 break;
596
597 case Err_FreeMismatch:
sewardj6b523cd2009-07-15 14:49:40 +0000598 if (xml) {
599 emit( " <kind>MismatchedFree</kind>\n" );
600 emit( " <what>Mismatched free() / delete / delete []</what>\n" );
601 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
602 mc_pp_AddrInfo(VG_(get_error_address)(err),
603 &extra->Err.FreeMismatch.ai, False);
604 } else {
605 emit( "Mismatched free() / delete / delete []\n" );
606 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
607 mc_pp_AddrInfo(VG_(get_error_address)(err),
608 &extra->Err.FreeMismatch.ai, False);
609 }
sewardj7ce71662008-05-02 10:33:15 +0000610 break;
611
612 case Err_Addr:
sewardj6b523cd2009-07-15 14:49:40 +0000613 if (xml) {
614 emit( " <kind>Invalid%s</kind>\n",
615 extra->Err.Addr.isWrite ? "Write" : "Read" );
616 emit( " <what>Invalid %s of size %ld</what>\n",
617 extra->Err.Addr.isWrite ? "write" : "read",
618 extra->Err.Addr.szB );
619 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
620 mc_pp_AddrInfo( VG_(get_error_address)(err),
621 &extra->Err.Addr.ai,
622 extra->Err.Addr.maybe_gcc );
sewardj7ce71662008-05-02 10:33:15 +0000623 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000624 emit( "Invalid %s of size %ld\n",
625 extra->Err.Addr.isWrite ? "write" : "read",
626 extra->Err.Addr.szB );
627 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
628
629 mc_pp_AddrInfo( VG_(get_error_address)(err),
630 &extra->Err.Addr.ai,
631 extra->Err.Addr.maybe_gcc );
sewardj7ce71662008-05-02 10:33:15 +0000632 }
sewardj7ce71662008-05-02 10:33:15 +0000633 break;
634
635 case Err_Jump:
sewardj6b523cd2009-07-15 14:49:40 +0000636 if (xml) {
637 emit( " <kind>InvalidJump</kind>\n" );
638 emit( " <what>Jump to the invalid address stated "
639 "on the next line</what>\n" );
640 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
641 mc_pp_AddrInfo( VG_(get_error_address)(err), &extra->Err.Jump.ai,
642 False );
643 } else {
644 emit( "Jump to the invalid address stated on the next line\n" );
645 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
646 mc_pp_AddrInfo( VG_(get_error_address)(err), &extra->Err.Jump.ai,
647 False );
648 }
sewardj7ce71662008-05-02 10:33:15 +0000649 break;
650
651 case Err_Overlap:
sewardj6b523cd2009-07-15 14:49:40 +0000652 if (xml) {
653 emit( " <kind>Overlap</kind>\n" );
654 if (extra->Err.Overlap.szB == 0) {
655 emiN( " <what>Source and destination overlap "
656 "in %t(%#lx, %#lx)\n</what>\n",
657 VG_(get_error_string)(err),
658 extra->Err.Overlap.dst, extra->Err.Overlap.src );
659 } else {
660 emit( " <what>Source and destination overlap "
661 "in %s(%#lx, %#lx, %d)</what>\n",
662 VG_(get_error_string)(err),
663 extra->Err.Overlap.dst, extra->Err.Overlap.src,
664 extra->Err.Overlap.szB );
665 }
666 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
667 } else {
668 if (extra->Err.Overlap.szB == 0) {
669 emiN( "Source and destination overlap in %t(%#lx, %#lx)\n",
670 VG_(get_error_string)(err),
671 extra->Err.Overlap.dst, extra->Err.Overlap.src );
672 } else {
673 emit( "Source and destination overlap in %s(%#lx, %#lx, %d)\n",
674 VG_(get_error_string)(err),
675 extra->Err.Overlap.dst, extra->Err.Overlap.src,
676 extra->Err.Overlap.szB );
677 }
678 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
679 }
sewardj7ce71662008-05-02 10:33:15 +0000680 break;
681
682 case Err_IllegalMempool:
sewardj6b523cd2009-07-15 14:49:40 +0000683 // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
684 // the following code is untested. Bad.
685 if (xml) {
686 emit( " <kind>InvalidMemPool</kind>\n" );
687 emit( " <what>Illegal memory pool address</what>\n" );
688 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
689 mc_pp_AddrInfo( VG_(get_error_address)(err),
690 &extra->Err.IllegalMempool.ai, False );
691 } else {
692 emit( "Illegal memory pool address\n" );
693 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
694 mc_pp_AddrInfo( VG_(get_error_address)(err),
695 &extra->Err.IllegalMempool.ai, False );
696 }
sewardj7ce71662008-05-02 10:33:15 +0000697 break;
698
699 case Err_Leak: {
sewardj7ce71662008-05-02 10:33:15 +0000700 UInt n_this_record = extra->Err.Leak.n_this_record;
701 UInt n_total_records = extra->Err.Leak.n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000702 LossRecord* lr = extra->Err.Leak.lr;
sewardj6b523cd2009-07-15 14:49:40 +0000703 if (xml) {
704 emit(" <kind>%s</kind>\n", xml_leak_kind(lr->key.state));
705 if (lr->indirect_szB > 0) {
706 emit( " <xwhat>\n" );
707 emit( " <text>%'lu (%'lu direct, %'lu indirect) bytes "
708 "in %'u blocks"
709 " are %s in loss record %'u of %'u</text>\n",
710 lr->szB + lr->indirect_szB, lr->szB, lr->indirect_szB,
711 lr->num_blocks,
712 str_leak_lossmode(lr->key.state),
713 n_this_record, n_total_records );
sewardj7ce71662008-05-02 10:33:15 +0000714 // Nb: don't put commas in these XML numbers
sewardj6b523cd2009-07-15 14:49:40 +0000715 emit( " <leakedbytes>%lu</leakedbytes>\n",
716 lr->szB + lr->indirect_szB );
717 emit( " <leakedblocks>%u</leakedblocks>\n", lr->num_blocks );
718 emit( " </xwhat>\n" );
719 } else {
720 emit( " <xwhat>\n" );
721 emit( " <text>%'lu bytes in %'u blocks"
722 " are %s in loss record %'u of %'u</text>\n",
723 lr->szB, lr->num_blocks,
724 str_leak_lossmode(lr->key.state),
725 n_this_record, n_total_records );
726 emit( " <leakedbytes>%ld</leakedbytes>\n", lr->szB);
727 emit( " <leakedblocks>%d</leakedblocks>\n", lr->num_blocks);
728 emit( " </xwhat>\n" );
sewardj7ce71662008-05-02 10:33:15 +0000729 }
sewardj6b523cd2009-07-15 14:49:40 +0000730 VG_(pp_ExeContext)(lr->key.allocated_at);
731 } else { /* ! if (xml) */
sewardj6b523cd2009-07-15 14:49:40 +0000732 if (lr->indirect_szB > 0) {
733 emit(
734 "%'lu (%'lu direct, %'lu indirect) bytes in %'u blocks"
735 " are %s in loss record %'u of %'u\n",
736 lr->szB + lr->indirect_szB, lr->szB, lr->indirect_szB,
737 lr->num_blocks, str_leak_lossmode(lr->key.state),
738 n_this_record, n_total_records
739 );
740 } else {
741 emit(
742 "%'lu bytes in %'u blocks are %s in loss record %'u of %'u\n",
743 lr->szB, lr->num_blocks, str_leak_lossmode(lr->key.state),
744 n_this_record, n_total_records
745 );
sewardj7ce71662008-05-02 10:33:15 +0000746 }
sewardj6b523cd2009-07-15 14:49:40 +0000747 VG_(pp_ExeContext)(lr->key.allocated_at);
748 } /* if (xml) */
sewardj7ce71662008-05-02 10:33:15 +0000749 break;
750 }
751
752 default:
753 VG_(printf)("Error:\n unknown Memcheck error code %d\n",
754 VG_(get_error_kind)(err));
755 VG_(tool_panic)("unknown error code in mc_pp_Error)");
756 }
757}
758
759/*------------------------------------------------------------*/
760/*--- Recording errors ---*/
761/*------------------------------------------------------------*/
762
763/* These many bytes below %ESP are considered addressible if we're
764 doing the --workaround-gcc296-bugs hack. */
765#define VG_GCC296_BUG_STACK_SLOP 1024
766
767/* Is this address within some small distance below %ESP? Used only
768 for the --workaround-gcc296-bugs kludge. */
769static Bool is_just_below_ESP( Addr esp, Addr aa )
770{
sewardj7d751b22010-07-21 12:46:44 +0000771 esp -= VG_STACK_REDZONE_SZB;
sewardj7ce71662008-05-02 10:33:15 +0000772 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
773 return True;
774 else
775 return False;
776}
777
778/* --- Called from generated and non-generated code --- */
779
780void MC_(record_address_error) ( ThreadId tid, Addr a, Int szB,
781 Bool isWrite )
782{
783 MC_Error extra;
784 Bool just_below_esp;
785
786 if (MC_(in_ignored_range)(a))
787 return;
788
789# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
790 /* AIX zero-page handling. On AIX, reads from page zero are,
791 bizarrely enough, legitimate. Writes to page zero aren't,
792 though. Since memcheck can't distinguish reads from writes, the
793 best we can do is to 'act normal' and mark the A bits in the
794 normal way as noaccess, but then hide any reads from that page
795 that get reported here. */
796 if ((!isWrite) && a >= 0 && a < 4096 && a+szB <= 4096)
797 return;
798
799 /* Appalling AIX hack. It suppresses reads done by glink
800 fragments. Getting rid of this would require figuring out
801 somehow where the referenced data areas are (and their
802 sizes). */
803 if ((!isWrite) && szB == sizeof(Word)) {
804 UInt i1, i2;
805 UInt* pc = (UInt*)VG_(get_IP)(tid);
806 if (sizeof(Word) == 4) {
807 i1 = 0x800c0000; /* lwz r0,0(r12) */
808 i2 = 0x804c0004; /* lwz r2,4(r12) */
809 } else {
810 i1 = 0xe80c0000; /* ld r0,0(r12) */
811 i2 = 0xe84c0008; /* ld r2,8(r12) */
812 }
813 if (pc[0] == i1 && pc[1] == i2) return;
814 if (pc[0] == i2 && pc[-1] == i1) return;
815 }
816# endif
817
818 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
819
820 /* If this is caused by an access immediately below %ESP, and the
821 user asks nicely, we just ignore it. */
822 if (MC_(clo_workaround_gcc296_bugs) && just_below_esp)
823 return;
824
825 extra.Err.Addr.isWrite = isWrite;
826 extra.Err.Addr.szB = szB;
827 extra.Err.Addr.maybe_gcc = just_below_esp;
828 extra.Err.Addr.ai.tag = Addr_Undescribed;
829 VG_(maybe_record_error)( tid, Err_Addr, a, /*s*/NULL, &extra );
830}
831
832void MC_(record_value_error) ( ThreadId tid, Int szB, UInt otag )
833{
834 MC_Error extra;
835 tl_assert( MC_(clo_mc_level) >= 2 );
836 if (otag > 0)
837 tl_assert( MC_(clo_mc_level) == 3 );
838 extra.Err.Value.szB = szB;
839 extra.Err.Value.otag = otag;
840 extra.Err.Value.origin_ec = NULL; /* Filled in later */
841 VG_(maybe_record_error)( tid, Err_Value, /*addr*/0, /*s*/NULL, &extra );
842}
843
844void MC_(record_cond_error) ( ThreadId tid, UInt otag )
845{
846 MC_Error extra;
847 tl_assert( MC_(clo_mc_level) >= 2 );
848 if (otag > 0)
849 tl_assert( MC_(clo_mc_level) == 3 );
850 extra.Err.Cond.otag = otag;
851 extra.Err.Cond.origin_ec = NULL; /* Filled in later */
852 VG_(maybe_record_error)( tid, Err_Cond, /*addr*/0, /*s*/NULL, &extra );
853}
854
855/* --- Called from non-generated code --- */
856
njn1dcee092009-02-24 03:07:37 +0000857/* This is for memory errors in signal-related memory. */
858void MC_(record_core_mem_error) ( ThreadId tid, Char* msg )
sewardj7ce71662008-05-02 10:33:15 +0000859{
860 VG_(maybe_record_error)( tid, Err_CoreMem, /*addr*/0, msg, /*extra*/NULL );
861}
862
863void MC_(record_regparam_error) ( ThreadId tid, Char* msg, UInt otag )
864{
865 MC_Error extra;
866 tl_assert(VG_INVALID_THREADID != tid);
867 if (otag > 0)
868 tl_assert( MC_(clo_mc_level) == 3 );
869 extra.Err.RegParam.otag = otag;
870 extra.Err.RegParam.origin_ec = NULL; /* Filled in later */
871 VG_(maybe_record_error)( tid, Err_RegParam, /*addr*/0, msg, &extra );
872}
873
874void MC_(record_memparam_error) ( ThreadId tid, Addr a,
875 Bool isAddrErr, Char* msg, UInt otag )
876{
877 MC_Error extra;
878 tl_assert(VG_INVALID_THREADID != tid);
879 if (!isAddrErr)
880 tl_assert( MC_(clo_mc_level) >= 2 );
881 if (otag != 0) {
882 tl_assert( MC_(clo_mc_level) == 3 );
883 tl_assert( !isAddrErr );
884 }
885 extra.Err.MemParam.isAddrErr = isAddrErr;
886 extra.Err.MemParam.ai.tag = Addr_Undescribed;
887 extra.Err.MemParam.otag = otag;
888 extra.Err.MemParam.origin_ec = NULL; /* Filled in later */
889 VG_(maybe_record_error)( tid, Err_MemParam, a, msg, &extra );
890}
891
892void MC_(record_jump_error) ( ThreadId tid, Addr a )
893{
894 MC_Error extra;
895 tl_assert(VG_INVALID_THREADID != tid);
896 extra.Err.Jump.ai.tag = Addr_Undescribed;
897 VG_(maybe_record_error)( tid, Err_Jump, a, /*s*/NULL, &extra );
898}
899
900void MC_(record_free_error) ( ThreadId tid, Addr a )
901{
902 MC_Error extra;
903 tl_assert(VG_INVALID_THREADID != tid);
904 extra.Err.Free.ai.tag = Addr_Undescribed;
905 VG_(maybe_record_error)( tid, Err_Free, a, /*s*/NULL, &extra );
906}
907
908void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* mc )
909{
910 MC_Error extra;
911 AddrInfo* ai = &extra.Err.FreeMismatch.ai;
912 tl_assert(VG_INVALID_THREADID != tid);
913 ai->tag = Addr_Block;
914 ai->Addr.Block.block_kind = Block_Mallocd; // Nb: Not 'Block_Freed'
915 ai->Addr.Block.block_desc = "block";
916 ai->Addr.Block.block_szB = mc->szB;
917 ai->Addr.Block.rwoffset = 0;
918 ai->Addr.Block.lastchange = mc->where;
919 VG_(maybe_record_error)( tid, Err_FreeMismatch, mc->data, /*s*/NULL,
920 &extra );
921}
922
923void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
924{
925 MC_Error extra;
926 tl_assert(VG_INVALID_THREADID != tid);
927 extra.Err.IllegalMempool.ai.tag = Addr_Undescribed;
928 VG_(maybe_record_error)( tid, Err_IllegalMempool, a, /*s*/NULL, &extra );
929}
930
931void MC_(record_overlap_error) ( ThreadId tid, Char* function,
932 Addr src, Addr dst, SizeT szB )
933{
934 MC_Error extra;
935 tl_assert(VG_INVALID_THREADID != tid);
936 extra.Err.Overlap.src = src;
937 extra.Err.Overlap.dst = dst;
938 extra.Err.Overlap.szB = szB;
939 VG_(maybe_record_error)(
940 tid, Err_Overlap, /*addr*/0, /*s*/function, &extra );
941}
942
943Bool MC_(record_leak_error) ( ThreadId tid, UInt n_this_record,
njnb7a4e2e2009-05-01 00:30:43 +0000944 UInt n_total_records, LossRecord* lr,
njn18afe5d2009-08-10 08:25:39 +0000945 Bool print_record, Bool count_error )
sewardj7ce71662008-05-02 10:33:15 +0000946{
947 MC_Error extra;
948 extra.Err.Leak.n_this_record = n_this_record;
949 extra.Err.Leak.n_total_records = n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000950 extra.Err.Leak.lr = lr;
sewardj7ce71662008-05-02 10:33:15 +0000951 return
952 VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
njn29a5c012009-05-06 06:15:55 +0000953 lr->key.allocated_at, print_record,
njn18afe5d2009-08-10 08:25:39 +0000954 /*allow_GDB_attach*/False, count_error );
sewardj7ce71662008-05-02 10:33:15 +0000955}
956
957void MC_(record_user_error) ( ThreadId tid, Addr a,
958 Bool isAddrErr, UInt otag )
959{
960 MC_Error extra;
961 if (otag != 0) {
962 tl_assert(!isAddrErr);
963 tl_assert( MC_(clo_mc_level) == 3 );
964 }
965 if (!isAddrErr) {
966 tl_assert( MC_(clo_mc_level) >= 2 );
967 }
968 tl_assert(VG_INVALID_THREADID != tid);
969 extra.Err.User.isAddrErr = isAddrErr;
970 extra.Err.User.ai.tag = Addr_Undescribed;
971 extra.Err.User.otag = otag;
972 extra.Err.User.origin_ec = NULL; /* Filled in later */
973 VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra );
974}
975
976/*------------------------------------------------------------*/
977/*--- Other error operations ---*/
978/*------------------------------------------------------------*/
979
980/* Compare error contexts, to detect duplicates. Note that if they
981 are otherwise the same, the faulting addrs and associated rwoffsets
982 are allowed to be different. */
983Bool MC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
984{
985 MC_Error* extra1 = VG_(get_error_extra)(e1);
986 MC_Error* extra2 = VG_(get_error_extra)(e2);
987
988 /* Guaranteed by calling function */
989 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
990
991 switch (VG_(get_error_kind)(e1)) {
992 case Err_CoreMem: {
993 Char *e1s, *e2s;
994 e1s = VG_(get_error_string)(e1);
995 e2s = VG_(get_error_string)(e2);
996 if (e1s == e2s) return True;
997 if (VG_STREQ(e1s, e2s)) return True;
998 return False;
999 }
1000
1001 case Err_RegParam:
1002 return VG_STREQ(VG_(get_error_string)(e1), VG_(get_error_string)(e2));
1003
1004 // Perhaps we should also check the addrinfo.akinds for equality.
1005 // That would result in more error reports, but only in cases where
1006 // a register contains uninitialised bytes and points to memory
1007 // containing uninitialised bytes. Currently, the 2nd of those to be
1008 // detected won't be reported. That is (nearly?) always the memory
1009 // error, which is good.
1010 case Err_MemParam:
1011 if (!VG_STREQ(VG_(get_error_string)(e1),
1012 VG_(get_error_string)(e2))) return False;
1013 // fall through
1014 case Err_User:
1015 return ( extra1->Err.User.isAddrErr == extra2->Err.User.isAddrErr
1016 ? True : False );
1017
1018 case Err_Free:
1019 case Err_FreeMismatch:
1020 case Err_Jump:
1021 case Err_IllegalMempool:
1022 case Err_Overlap:
1023 case Err_Cond:
1024 return True;
1025
1026 case Err_Addr:
1027 return ( extra1->Err.Addr.szB == extra2->Err.Addr.szB
1028 ? True : False );
1029
1030 case Err_Value:
1031 return ( extra1->Err.Value.szB == extra2->Err.Value.szB
1032 ? True : False );
1033
1034 case Err_Leak:
1035 VG_(tool_panic)("Shouldn't get Err_Leak in mc_eq_Error,\n"
1036 "since it's handled with VG_(unique_error)()!");
1037
1038 default:
1039 VG_(printf)("Error:\n unknown error code %d\n",
1040 VG_(get_error_kind)(e1));
1041 VG_(tool_panic)("unknown error code in mc_eq_Error");
1042 }
1043}
1044
1045/* Function used when searching MC_Chunk lists */
1046static Bool addr_is_in_MC_Chunk(MC_Chunk* mc, Addr a)
1047{
1048 // Nb: this is not quite right! It assumes that the heap block has
1049 // a redzone of size MC_MALLOC_REDZONE_SZB. That's true for malloc'd
1050 // blocks, but not necessarily true for custom-alloc'd blocks. So
1051 // in some cases this could result in an incorrect description (eg.
1052 // saying "12 bytes after block A" when really it's within block B.
1053 // Fixing would require adding redzone size to MC_Chunks, though.
1054 return VG_(addr_is_in_block)( a, mc->data, mc->szB,
1055 MC_MALLOC_REDZONE_SZB );
1056}
1057
1058// Forward declaration
1059static Bool client_block_maybe_describe( Addr a, AddrInfo* ai );
1060
1061
1062/* Describe an address as best you can, for error messages,
1063 putting the result in ai. */
1064static void describe_addr ( Addr a, /*OUT*/AddrInfo* ai )
1065{
1066 MC_Chunk* mc;
1067 ThreadId tid;
1068 Addr stack_min, stack_max;
1069 VgSectKind sect;
1070
1071 tl_assert(Addr_Undescribed == ai->tag);
1072
sewardj6b523cd2009-07-15 14:49:40 +00001073 /* -- Perhaps it's a user-def'd block? -- */
sewardj7ce71662008-05-02 10:33:15 +00001074 if (client_block_maybe_describe( a, ai )) {
1075 return;
1076 }
sewardj6b523cd2009-07-15 14:49:40 +00001077 /* -- Search for a recently freed block which might bracket it. -- */
sewardj7ce71662008-05-02 10:33:15 +00001078 mc = MC_(get_freed_list_head)();
1079 while (mc) {
1080 if (addr_is_in_MC_Chunk(mc, a)) {
1081 ai->tag = Addr_Block;
1082 ai->Addr.Block.block_kind = Block_Freed;
1083 ai->Addr.Block.block_desc = "block";
1084 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +00001085 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +00001086 ai->Addr.Block.lastchange = mc->where;
1087 return;
1088 }
1089 mc = mc->next;
1090 }
sewardj6b523cd2009-07-15 14:49:40 +00001091 /* -- Search for a currently malloc'd block which might bracket it. -- */
sewardj7ce71662008-05-02 10:33:15 +00001092 VG_(HT_ResetIter)(MC_(malloc_list));
1093 while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
1094 if (addr_is_in_MC_Chunk(mc, a)) {
1095 ai->tag = Addr_Block;
1096 ai->Addr.Block.block_kind = Block_Mallocd;
1097 ai->Addr.Block.block_desc = "block";
1098 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +00001099 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +00001100 ai->Addr.Block.lastchange = mc->where;
1101 return;
1102 }
1103 }
sewardj6b523cd2009-07-15 14:49:40 +00001104 /* -- Perhaps the variable type/location data describes it? -- */
1105 ai->Addr.Variable.descr1
1106 = VG_(newXA)( VG_(malloc), "mc.da.descr1",
1107 VG_(free), sizeof(HChar) );
1108 ai->Addr.Variable.descr2
1109 = VG_(newXA)( VG_(malloc), "mc.da.descr2",
1110 VG_(free), sizeof(HChar) );
1111
1112 (void) VG_(get_data_description)( ai->Addr.Variable.descr1,
1113 ai->Addr.Variable.descr2, a );
1114 /* If there's nothing in descr1/2, free them. Why is it safe to to
1115 VG_(indexXA) at zero here? Because VG_(get_data_description)
1116 guarantees to zero terminate descr1/2 regardless of the outcome
1117 of the call. So there's always at least one element in each XA
1118 after the call.
1119 */
1120 if (0 == VG_(strlen)( VG_(indexXA)( ai->Addr.Variable.descr1, 0 ))) {
1121 VG_(deleteXA)( ai->Addr.Variable.descr1 );
1122 ai->Addr.Variable.descr1 = NULL;
1123 }
1124 if (0 == VG_(strlen)( VG_(indexXA)( ai->Addr.Variable.descr2, 0 ))) {
1125 VG_(deleteXA)( ai->Addr.Variable.descr2 );
1126 ai->Addr.Variable.descr2 = NULL;
1127 }
1128 /* Assume (assert) that VG_(get_data_description) fills in descr1
1129 before it fills in descr2 */
1130 if (ai->Addr.Variable.descr1 == NULL)
1131 tl_assert(ai->Addr.Variable.descr2 == NULL);
1132 /* So did we get lucky? */
1133 if (ai->Addr.Variable.descr1 != NULL) {
sewardj7ce71662008-05-02 10:33:15 +00001134 ai->tag = Addr_Variable;
sewardj7ce71662008-05-02 10:33:15 +00001135 return;
1136 }
sewardj6b523cd2009-07-15 14:49:40 +00001137 /* -- Have a look at the low level data symbols - perhaps it's in
1138 there. -- */
sewardj7ce71662008-05-02 10:33:15 +00001139 VG_(memset)( &ai->Addr.DataSym.name,
1140 0, sizeof(ai->Addr.DataSym.name));
1141 if (VG_(get_datasym_and_offset)(
1142 a, &ai->Addr.DataSym.name[0],
1143 sizeof(ai->Addr.DataSym.name)-1,
1144 &ai->Addr.DataSym.offset )) {
1145 ai->tag = Addr_DataSym;
1146 tl_assert( ai->Addr.DataSym.name
1147 [ sizeof(ai->Addr.DataSym.name)-1 ] == 0);
1148 return;
1149 }
sewardj6b523cd2009-07-15 14:49:40 +00001150 /* -- Perhaps it's on a thread's stack? -- */
sewardj7ce71662008-05-02 10:33:15 +00001151 VG_(thread_stack_reset_iter)(&tid);
1152 while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
1153 if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
1154 ai->tag = Addr_Stack;
1155 ai->Addr.Stack.tid = tid;
1156 return;
1157 }
1158 }
sewardj6b523cd2009-07-15 14:49:40 +00001159 /* -- last ditch attempt at classification -- */
sewardj7ce71662008-05-02 10:33:15 +00001160 tl_assert( sizeof(ai->Addr.SectKind.objname) > 4 );
1161 VG_(memset)( &ai->Addr.SectKind.objname,
1162 0, sizeof(ai->Addr.SectKind.objname));
1163 VG_(strcpy)( ai->Addr.SectKind.objname, "???" );
sewardje3f1e592009-07-31 09:41:29 +00001164 sect = VG_(DebugInfo_sect_kind)( &ai->Addr.SectKind.objname[0],
1165 sizeof(ai->Addr.SectKind.objname)-1, a);
sewardj7ce71662008-05-02 10:33:15 +00001166 if (sect != Vg_SectUnknown) {
1167 ai->tag = Addr_SectKind;
1168 ai->Addr.SectKind.kind = sect;
1169 tl_assert( ai->Addr.SectKind.objname
1170 [ sizeof(ai->Addr.SectKind.objname)-1 ] == 0);
1171 return;
1172 }
sewardj6b523cd2009-07-15 14:49:40 +00001173 /* -- Clueless ... -- */
sewardj7ce71662008-05-02 10:33:15 +00001174 ai->tag = Addr_Unknown;
1175 return;
1176}
1177
1178/* Fill in *origin_ec as specified by otag, or NULL it out if otag
1179 does not refer to a known origin. */
1180static void update_origin ( /*OUT*/ExeContext** origin_ec,
1181 UInt otag )
1182{
1183 UInt ecu = otag & ~3;
1184 *origin_ec = NULL;
1185 if (VG_(is_plausible_ECU)(ecu)) {
1186 *origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
1187 }
1188}
1189
1190/* Updates the copy with address info if necessary (but not for all errors). */
1191UInt MC_(update_Error_extra)( Error* err )
1192{
1193 MC_Error* extra = VG_(get_error_extra)(err);
1194
1195 switch (VG_(get_error_kind)(err)) {
1196 // These ones don't have addresses associated with them, and so don't
1197 // need any updating.
1198 case Err_CoreMem:
1199 //case Err_Value:
1200 //case Err_Cond:
1201 case Err_Overlap:
1202 // For Err_Leaks the returned size does not matter -- they are always
1203 // shown with VG_(unique_error)() so they 'extra' not copied. But
1204 // we make it consistent with the others.
1205 case Err_Leak:
1206 return sizeof(MC_Error);
1207
1208 // For value errors, get the ExeContext corresponding to the
1209 // origin tag. Note that it is a kludge to assume that
1210 // a length-1 trace indicates a stack origin. FIXME.
1211 case Err_Value:
1212 update_origin( &extra->Err.Value.origin_ec,
1213 extra->Err.Value.otag );
1214 return sizeof(MC_Error);
1215 case Err_Cond:
1216 update_origin( &extra->Err.Cond.origin_ec,
1217 extra->Err.Cond.otag );
1218 return sizeof(MC_Error);
1219 case Err_RegParam:
1220 update_origin( &extra->Err.RegParam.origin_ec,
1221 extra->Err.RegParam.otag );
1222 return sizeof(MC_Error);
1223
1224 // These ones always involve a memory address.
1225 case Err_Addr:
1226 describe_addr ( VG_(get_error_address)(err),
1227 &extra->Err.Addr.ai );
1228 return sizeof(MC_Error);
1229 case Err_MemParam:
1230 describe_addr ( VG_(get_error_address)(err),
1231 &extra->Err.MemParam.ai );
1232 update_origin( &extra->Err.MemParam.origin_ec,
1233 extra->Err.MemParam.otag );
1234 return sizeof(MC_Error);
1235 case Err_Jump:
1236 describe_addr ( VG_(get_error_address)(err),
1237 &extra->Err.Jump.ai );
1238 return sizeof(MC_Error);
1239 case Err_User:
1240 describe_addr ( VG_(get_error_address)(err),
1241 &extra->Err.User.ai );
1242 update_origin( &extra->Err.User.origin_ec,
1243 extra->Err.User.otag );
1244 return sizeof(MC_Error);
1245 case Err_Free:
1246 describe_addr ( VG_(get_error_address)(err),
1247 &extra->Err.Free.ai );
1248 return sizeof(MC_Error);
1249 case Err_IllegalMempool:
1250 describe_addr ( VG_(get_error_address)(err),
1251 &extra->Err.IllegalMempool.ai );
1252 return sizeof(MC_Error);
1253
1254 // Err_FreeMismatches have already had their address described; this is
1255 // possible because we have the MC_Chunk on hand when the error is
1256 // detected. However, the address may be part of a user block, and if so
1257 // we override the pre-determined description with a user block one.
1258 case Err_FreeMismatch: {
1259 tl_assert(extra && Block_Mallocd ==
1260 extra->Err.FreeMismatch.ai.Addr.Block.block_kind);
1261 (void)client_block_maybe_describe( VG_(get_error_address)(err),
1262 &extra->Err.FreeMismatch.ai );
1263 return sizeof(MC_Error);
1264 }
1265
1266 default: VG_(tool_panic)("mc_update_extra: bad errkind");
1267 }
1268}
1269
1270// FIXME: does this perhaps want to live somewhere else
1271// in this file?
1272static Bool client_block_maybe_describe( Addr a,
1273 /*OUT*/AddrInfo* ai )
1274{
sewardj56adc352008-05-02 11:25:17 +00001275 UWord i;
sewardj7ce71662008-05-02 10:33:15 +00001276 CGenBlock* cgbs = NULL;
1277 UWord cgb_used = 0;
sewardj56adc352008-05-02 11:25:17 +00001278
sewardj7ce71662008-05-02 10:33:15 +00001279 MC_(get_ClientBlock_array)( &cgbs, &cgb_used );
1280 if (cgbs == NULL)
1281 tl_assert(cgb_used == 0);
1282
1283 /* Perhaps it's a general block ? */
1284 for (i = 0; i < cgb_used; i++) {
1285 if (cgbs[i].start == 0 && cgbs[i].size == 0)
1286 continue;
1287 // Use zero as the redzone for client blocks.
1288 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
1289 /* OK - maybe it's a mempool, too? */
1290 MC_Mempool* mp = VG_(HT_lookup)(MC_(mempool_list),
1291 (UWord)cgbs[i].start);
1292 if (mp != NULL) {
1293 if (mp->chunks != NULL) {
1294 MC_Chunk* mc;
1295 VG_(HT_ResetIter)(mp->chunks);
1296 while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
1297 if (addr_is_in_MC_Chunk(mc, a)) {
1298 ai->tag = Addr_Block;
1299 ai->Addr.Block.block_kind = Block_MempoolChunk;
1300 ai->Addr.Block.block_desc = "block";
1301 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +00001302 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +00001303 ai->Addr.Block.lastchange = mc->where;
1304 return True;
1305 }
1306 }
1307 }
1308 ai->tag = Addr_Block;
1309 ai->Addr.Block.block_kind = Block_Mempool;
1310 ai->Addr.Block.block_desc = "mempool";
1311 ai->Addr.Block.block_szB = cgbs[i].size;
sewardj56adc352008-05-02 11:25:17 +00001312 ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
sewardj7ce71662008-05-02 10:33:15 +00001313 ai->Addr.Block.lastchange = cgbs[i].where;
1314 return True;
1315 }
1316 ai->tag = Addr_Block;
1317 ai->Addr.Block.block_kind = Block_UserG;
1318 ai->Addr.Block.block_desc = cgbs[i].desc;
1319 ai->Addr.Block.block_szB = cgbs[i].size;
sewardj56adc352008-05-02 11:25:17 +00001320 ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
sewardj7ce71662008-05-02 10:33:15 +00001321 ai->Addr.Block.lastchange = cgbs[i].where;
1322 return True;
1323 }
1324 }
1325 return False;
1326}
1327
1328
1329/*------------------------------------------------------------*/
1330/*--- Suppressions ---*/
1331/*------------------------------------------------------------*/
1332
1333typedef
1334 enum {
1335 ParamSupp, // Bad syscall params
1336 UserSupp, // Errors arising from client-request checks
1337 CoreMemSupp, // Memory errors in core (pthread ops, signal handling)
1338
1339 // Undefined value errors of given size
1340 Value1Supp, Value2Supp, Value4Supp, Value8Supp, Value16Supp,
1341
1342 // Undefined value error in conditional.
1343 CondSupp,
1344
1345 // Unaddressable read/write attempt at given size
1346 Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp, Addr16Supp,
1347
1348 JumpSupp, // Jump to unaddressable target
1349 FreeSupp, // Invalid or mismatching free
1350 OverlapSupp, // Overlapping blocks in memcpy(), strcpy(), etc
1351 LeakSupp, // Something to be suppressed in a leak check.
1352 MempoolSupp, // Memory pool suppression.
1353 }
1354 MC_SuppKind;
1355
1356Bool MC_(is_recognised_suppression) ( Char* name, Supp* su )
1357{
1358 SuppKind skind;
1359
1360 if (VG_STREQ(name, "Param")) skind = ParamSupp;
1361 else if (VG_STREQ(name, "User")) skind = UserSupp;
1362 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
1363 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
1364 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
1365 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
1366 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
1367 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
1368 else if (VG_STREQ(name, "Jump")) skind = JumpSupp;
1369 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
1370 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
1371 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
1372 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
1373 else if (VG_STREQ(name, "Cond")) skind = CondSupp;
1374 else if (VG_STREQ(name, "Value0")) skind = CondSupp; /* backwards compat */
1375 else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
1376 else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
1377 else if (VG_STREQ(name, "Value4")) skind = Value4Supp;
1378 else if (VG_STREQ(name, "Value8")) skind = Value8Supp;
1379 else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
1380 else
1381 return False;
1382
1383 VG_(set_supp_kind)(su, skind);
1384 return True;
1385}
1386
njn35db56c2009-07-24 07:38:29 +00001387Bool MC_(read_extra_suppression_info) ( Int fd, Char** bufpp,
1388 SizeT* nBufp, Supp *su )
sewardj7ce71662008-05-02 10:33:15 +00001389{
1390 Bool eof;
1391
1392 if (VG_(get_supp_kind)(su) == ParamSupp) {
bart050eec52009-07-27 12:03:03 +00001393 eof = VG_(get_line) ( fd, bufpp, nBufp, NULL );
sewardj7ce71662008-05-02 10:33:15 +00001394 if (eof) return False;
njn35db56c2009-07-24 07:38:29 +00001395 VG_(set_supp_string)(su, VG_(strdup)("mc.resi.1", *bufpp));
sewardj7ce71662008-05-02 10:33:15 +00001396 }
1397 return True;
1398}
1399
1400Bool MC_(error_matches_suppression) ( Error* err, Supp* su )
1401{
1402 Int su_szB;
1403 MC_Error* extra = VG_(get_error_extra)(err);
1404 ErrorKind ekind = VG_(get_error_kind )(err);
1405
1406 switch (VG_(get_supp_kind)(su)) {
1407 case ParamSupp:
1408 return ((ekind == Err_RegParam || ekind == Err_MemParam)
1409 && VG_STREQ(VG_(get_error_string)(err),
1410 VG_(get_supp_string)(su)));
1411
1412 case UserSupp:
1413 return (ekind == Err_User);
1414
1415 case CoreMemSupp:
1416 return (ekind == Err_CoreMem
1417 && VG_STREQ(VG_(get_error_string)(err),
1418 VG_(get_supp_string)(su)));
1419
1420 case Value1Supp: su_szB = 1; goto value_case;
1421 case Value2Supp: su_szB = 2; goto value_case;
1422 case Value4Supp: su_szB = 4; goto value_case;
1423 case Value8Supp: su_szB = 8; goto value_case;
1424 case Value16Supp:su_szB =16; goto value_case;
1425 value_case:
1426 return (ekind == Err_Value && extra->Err.Value.szB == su_szB);
1427
1428 case CondSupp:
1429 return (ekind == Err_Cond);
1430
1431 case Addr1Supp: su_szB = 1; goto addr_case;
1432 case Addr2Supp: su_szB = 2; goto addr_case;
1433 case Addr4Supp: su_szB = 4; goto addr_case;
1434 case Addr8Supp: su_szB = 8; goto addr_case;
1435 case Addr16Supp:su_szB =16; goto addr_case;
1436 addr_case:
1437 return (ekind == Err_Addr && extra->Err.Addr.szB == su_szB);
1438
1439 case JumpSupp:
1440 return (ekind == Err_Jump);
1441
1442 case FreeSupp:
1443 return (ekind == Err_Free || ekind == Err_FreeMismatch);
1444
1445 case OverlapSupp:
1446 return (ekind == Err_Overlap);
1447
1448 case LeakSupp:
1449 return (ekind == Err_Leak);
1450
1451 case MempoolSupp:
1452 return (ekind == Err_IllegalMempool);
1453
1454 default:
1455 VG_(printf)("Error:\n"
1456 " unknown suppression type %d\n",
1457 VG_(get_supp_kind)(su));
1458 VG_(tool_panic)("unknown suppression type in "
1459 "MC_(error_matches_suppression)");
1460 }
1461}
1462
1463Char* MC_(get_error_name) ( Error* err )
1464{
1465 switch (VG_(get_error_kind)(err)) {
1466 case Err_RegParam: return "Param";
1467 case Err_MemParam: return "Param";
1468 case Err_User: return "User";
1469 case Err_FreeMismatch: return "Free";
1470 case Err_IllegalMempool: return "Mempool";
1471 case Err_Free: return "Free";
1472 case Err_Jump: return "Jump";
1473 case Err_CoreMem: return "CoreMem";
1474 case Err_Overlap: return "Overlap";
1475 case Err_Leak: return "Leak";
1476 case Err_Cond: return "Cond";
1477 case Err_Addr: {
1478 MC_Error* extra = VG_(get_error_extra)(err);
1479 switch ( extra->Err.Addr.szB ) {
1480 case 1: return "Addr1";
1481 case 2: return "Addr2";
1482 case 4: return "Addr4";
1483 case 8: return "Addr8";
1484 case 16: return "Addr16";
1485 default: VG_(tool_panic)("unexpected size for Addr");
1486 }
1487 }
1488 case Err_Value: {
1489 MC_Error* extra = VG_(get_error_extra)(err);
1490 switch ( extra->Err.Value.szB ) {
1491 case 1: return "Value1";
1492 case 2: return "Value2";
1493 case 4: return "Value4";
1494 case 8: return "Value8";
1495 case 16: return "Value16";
1496 default: VG_(tool_panic)("unexpected size for Value");
1497 }
1498 }
1499 default: VG_(tool_panic)("get_error_name: unexpected type");
1500 }
1501}
1502
sewardj588adef2009-08-15 22:41:51 +00001503Bool MC_(get_extra_suppression_info) ( Error* err,
1504 /*OUT*/Char* buf, Int nBuf )
sewardj7ce71662008-05-02 10:33:15 +00001505{
1506 ErrorKind ekind = VG_(get_error_kind )(err);
sewardj588adef2009-08-15 22:41:51 +00001507 tl_assert(buf);
1508 tl_assert(nBuf >= 16); // stay sane
sewardj7ce71662008-05-02 10:33:15 +00001509 if (Err_RegParam == ekind || Err_MemParam == ekind) {
sewardj588adef2009-08-15 22:41:51 +00001510 Char* errstr = VG_(get_error_string)(err);
1511 tl_assert(errstr);
1512 VG_(snprintf)(buf, nBuf-1, "%s", errstr);
1513 return True;
1514 } else {
1515 return False;
sewardj7ce71662008-05-02 10:33:15 +00001516 }
1517}
1518
1519
1520/*--------------------------------------------------------------------*/
1521/*--- end mc_errors.c ---*/
1522/*--------------------------------------------------------------------*/