• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
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 
11    Copyright (C) 2000-2013 Julian Seward
12       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"
33 #include "pub_tool_gdbserver.h"
34 #include "pub_tool_poolalloc.h"     // For mc_include.h
35 #include "pub_tool_hashtable.h"     // For mc_include.h
36 #include "pub_tool_libcbase.h"
37 #include "pub_tool_libcassert.h"
38 #include "pub_tool_libcprint.h"
39 #include "pub_tool_machine.h"
40 #include "pub_tool_mallocfree.h"
41 #include "pub_tool_options.h"
42 #include "pub_tool_replacemalloc.h"
43 #include "pub_tool_tooliface.h"
44 #include "pub_tool_threadstate.h"
45 #include "pub_tool_debuginfo.h"     // VG_(get_dataname_and_offset)
46 #include "pub_tool_xarray.h"
47 #include "pub_tool_addrinfo.h"
48 
49 #include "mc_include.h"
50 
51 
52 /*------------------------------------------------------------*/
53 /*--- Error types                                          ---*/
54 /*------------------------------------------------------------*/
55 
56 /* See comment in mc_include.h */
57 Bool MC_(any_value_errors) = False;
58 
59 
60 /* ------------------ Errors ----------------------- */
61 
62 /* What kind of error it is. */
63 typedef
64    enum {
65       Err_Value,
66       Err_Cond,
67       Err_CoreMem,
68       Err_Addr,
69       Err_Jump,
70       Err_RegParam,
71       Err_MemParam,
72       Err_User,
73       Err_Free,
74       Err_FreeMismatch,
75       Err_Overlap,
76       Err_Leak,
77       Err_IllegalMempool,
78    }
79    MC_ErrorTag;
80 
81 
82 typedef struct _MC_Error MC_Error;
83 
84 struct _MC_Error {
85    // Nb: we don't need the tag here, as it's stored in the Error type! Yuk.
86    //MC_ErrorTag tag;
87 
88    union {
89       // Use of an undefined value:
90       // - as a pointer in a load or store
91       // - as a jump target
92       struct {
93          SizeT szB;   // size of value in bytes
94          // Origin info
95          UInt        otag;      // origin tag
96          ExeContext* origin_ec; // filled in later
97       } Value;
98 
99       // Use of an undefined value in a conditional branch or move.
100       struct {
101          // Origin info
102          UInt        otag;      // origin tag
103          ExeContext* origin_ec; // filled in later
104       } Cond;
105 
106       // Addressability error in core (signal-handling) operation.
107       // It would be good to get rid of this error kind, merge it with
108       // another one somehow.
109       struct {
110       } CoreMem;
111 
112       // Use of an unaddressable memory location in a load or store.
113       struct {
114          Bool     isWrite;    // read or write?
115          SizeT    szB;        // not used for exec (jump) errors
116          Bool     maybe_gcc;  // True if just below %esp -- could be a gcc bug
117          AddrInfo ai;
118       } Addr;
119 
120       // Jump to an unaddressable memory location.
121       struct {
122          AddrInfo ai;
123       } Jump;
124 
125       // System call register input contains undefined bytes.
126       struct {
127          // Origin info
128          UInt        otag;      // origin tag
129          ExeContext* origin_ec; // filled in later
130       } RegParam;
131 
132       // System call memory input contains undefined/unaddressable bytes
133       struct {
134          Bool     isAddrErr;  // Addressability or definedness error?
135          AddrInfo ai;
136          // Origin info
137          UInt        otag;      // origin tag
138          ExeContext* origin_ec; // filled in later
139       } MemParam;
140 
141       // Problem found from a client request like CHECK_MEM_IS_ADDRESSABLE.
142       struct {
143          Bool     isAddrErr;  // Addressability or definedness error?
144          AddrInfo ai;
145          // Origin info
146          UInt        otag;      // origin tag
147          ExeContext* origin_ec; // filled in later
148       } User;
149 
150       // Program tried to free() something that's not a heap block (this
151       // covers double-frees). */
152       struct {
153          AddrInfo ai;
154       } Free;
155 
156       // Program allocates heap block with one function
157       // (malloc/new/new[]/custom) and deallocates with not the matching one.
158       struct {
159          AddrInfo ai;
160       } FreeMismatch;
161 
162       // Call to strcpy, memcpy, etc, with overlapping blocks.
163       struct {
164          Addr  src;   // Source block
165          Addr  dst;   // Destination block
166          SizeT szB;   // Size in bytes;  0 if unused.
167       } Overlap;
168 
169       // A memory leak.
170       struct {
171          UInt        n_this_record;
172          UInt        n_total_records;
173          LossRecord* lr;
174       } Leak;
175 
176       // A memory pool error.
177       struct {
178          AddrInfo ai;
179       } IllegalMempool;
180 
181    } Err;
182 };
183 
184 
185 /*------------------------------------------------------------*/
186 /*--- Printing errors                                      ---*/
187 /*------------------------------------------------------------*/
188 
189 /* This is the "this error is due to be printed shortly; so have a
190    look at it any print any preamble you want" function.  Which, in
191    Memcheck, we don't use.  Hence a no-op.
192 */
MC_(before_pp_Error)193 void MC_(before_pp_Error) ( Error* err ) {
194 }
195 
196 /* Do a printf-style operation on either the XML or normal output
197    channel, depending on the setting of VG_(clo_xml).
198 */
emit_WRK(const HChar * format,va_list vargs)199 static void emit_WRK ( const HChar* format, va_list vargs )
200 {
201    if (VG_(clo_xml)) {
202       VG_(vprintf_xml)(format, vargs);
203    } else {
204       VG_(vmessage)(Vg_UserMsg, format, vargs);
205    }
206 }
207 static void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
emit(const HChar * format,...)208 static void emit ( const HChar* format, ... )
209 {
210    va_list vargs;
211    va_start(vargs, format);
212    emit_WRK(format, vargs);
213    va_end(vargs);
214 }
215 
216 
str_leak_lossmode(Reachedness lossmode)217 static const HChar* str_leak_lossmode ( Reachedness lossmode )
218 {
219    const HChar *loss = "?";
220    switch (lossmode) {
221       case Unreached:    loss = "definitely lost"; break;
222       case IndirectLeak: loss = "indirectly lost"; break;
223       case Possible:     loss = "possibly lost"; break;
224       case Reachable:    loss = "still reachable"; break;
225    }
226    return loss;
227 }
228 
xml_leak_kind(Reachedness lossmode)229 static const HChar* xml_leak_kind ( Reachedness lossmode )
230 {
231    const HChar *loss = "?";
232    switch (lossmode) {
233       case Unreached:    loss = "Leak_DefinitelyLost"; break;
234       case IndirectLeak: loss = "Leak_IndirectlyLost"; break;
235       case Possible:     loss = "Leak_PossiblyLost"; break;
236       case Reachable:    loss = "Leak_StillReachable"; break;
237    }
238    return loss;
239 }
240 
MC_(parse_leak_kinds)241 Bool MC_(parse_leak_kinds) ( const HChar* str0, UInt* lks )
242 {
243    return VG_(parse_enum_set)("reachable,possible,indirect,definite",
244                               str0, lks);
245 }
246 
pp_Reachedness_for_leak_kinds(Reachedness r)247 static const HChar* pp_Reachedness_for_leak_kinds(Reachedness r)
248 {
249    switch(r) {
250    case Reachable:    return "reachable";
251    case Possible:     return "possible";
252    case IndirectLeak: return "indirect";
253    case Unreached:    return "definite";
254    default:           tl_assert(0);
255    }
256 }
257 
mc_pp_origin(ExeContext * ec,UInt okind)258 static void mc_pp_origin ( ExeContext* ec, UInt okind )
259 {
260    const HChar* src = NULL;
261    tl_assert(ec);
262 
263    switch (okind) {
264       case MC_OKIND_STACK:   src = " by a stack allocation"; break;
265       case MC_OKIND_HEAP:    src = " by a heap allocation"; break;
266       case MC_OKIND_USER:    src = " by a client request"; break;
267       case MC_OKIND_UNKNOWN: src = ""; break;
268    }
269    tl_assert(src); /* guards against invalid 'okind' */
270 
271    if (VG_(clo_xml)) {
272       emit( "  <auxwhat>Uninitialised value was created%s</auxwhat>\n",
273             src);
274       VG_(pp_ExeContext)( ec );
275    } else {
276       emit( " Uninitialised value was created%s\n", src);
277       VG_(pp_ExeContext)( ec );
278    }
279 }
280 
MC_(snprintf_delta)281 HChar * MC_(snprintf_delta) (HChar * buf, Int size,
282                              SizeT current_val, SizeT old_val,
283                              LeakCheckDeltaMode delta_mode)
284 {
285    if (delta_mode == LCD_Any)
286       buf[0] = '\0';
287    else if (current_val >= old_val)
288       VG_(snprintf) (buf, size, " (+%'lu)", current_val - old_val);
289    else
290       VG_(snprintf) (buf, size, " (-%'lu)", old_val - current_val);
291 
292    return buf;
293 }
294 
pp_LossRecord(UInt n_this_record,UInt n_total_records,LossRecord * lr,Bool xml)295 static void pp_LossRecord(UInt n_this_record, UInt n_total_records,
296                           LossRecord* lr, Bool xml)
297 {
298    // char arrays to produce the indication of increase/decrease in case
299    // of delta_mode != LCD_Any
300    HChar d_bytes[20];
301    HChar d_direct_bytes[20];
302    HChar d_indirect_bytes[20];
303    HChar d_num_blocks[20];
304 
305    MC_(snprintf_delta) (d_bytes, 20,
306                         lr->szB + lr->indirect_szB,
307                         lr->old_szB + lr->old_indirect_szB,
308                         MC_(detect_memory_leaks_last_delta_mode));
309    MC_(snprintf_delta) (d_direct_bytes, 20,
310                         lr->szB,
311                         lr->old_szB,
312                         MC_(detect_memory_leaks_last_delta_mode));
313    MC_(snprintf_delta) (d_indirect_bytes, 20,
314                         lr->indirect_szB,
315                         lr->old_indirect_szB,
316                         MC_(detect_memory_leaks_last_delta_mode));
317    MC_(snprintf_delta) (d_num_blocks, 20,
318                         (SizeT) lr->num_blocks,
319                         (SizeT) lr->old_num_blocks,
320                         MC_(detect_memory_leaks_last_delta_mode));
321 
322    if (xml) {
323       emit("  <kind>%s</kind>\n", xml_leak_kind(lr->key.state));
324       if (lr->indirect_szB > 0) {
325          emit( "  <xwhat>\n" );
326          emit( "    <text>%'lu%s (%'lu%s direct, %'lu%s indirect) bytes "
327                "in %'u%s blocks"
328                " are %s in loss record %'u of %'u</text>\n",
329                lr->szB + lr->indirect_szB, d_bytes,
330                lr->szB, d_direct_bytes,
331                lr->indirect_szB, d_indirect_bytes,
332                lr->num_blocks, d_num_blocks,
333                str_leak_lossmode(lr->key.state),
334                n_this_record, n_total_records );
335          // Nb: don't put commas in these XML numbers
336          emit( "    <leakedbytes>%lu</leakedbytes>\n",
337                lr->szB + lr->indirect_szB );
338          emit( "    <leakedblocks>%u</leakedblocks>\n", lr->num_blocks );
339          emit( "  </xwhat>\n" );
340       } else {
341          emit( "  <xwhat>\n" );
342          emit( "    <text>%'lu%s bytes in %'u%s blocks"
343                " are %s in loss record %'u of %'u</text>\n",
344                lr->szB, d_direct_bytes,
345                lr->num_blocks, d_num_blocks,
346                str_leak_lossmode(lr->key.state),
347                n_this_record, n_total_records );
348          emit( "    <leakedbytes>%ld</leakedbytes>\n", lr->szB);
349          emit( "    <leakedblocks>%d</leakedblocks>\n", lr->num_blocks);
350          emit( "  </xwhat>\n" );
351       }
352       VG_(pp_ExeContext)(lr->key.allocated_at);
353    } else { /* ! if (xml) */
354       if (lr->indirect_szB > 0) {
355          emit(
356             "%'lu%s (%'lu%s direct, %'lu%s indirect) bytes in %'u%s blocks"
357             " are %s in loss record %'u of %'u\n",
358             lr->szB + lr->indirect_szB, d_bytes,
359             lr->szB, d_direct_bytes,
360             lr->indirect_szB, d_indirect_bytes,
361             lr->num_blocks, d_num_blocks,
362             str_leak_lossmode(lr->key.state),
363             n_this_record, n_total_records
364          );
365       } else {
366          emit(
367             "%'lu%s bytes in %'u%s blocks are %s in loss record %'u of %'u\n",
368             lr->szB, d_direct_bytes,
369             lr->num_blocks, d_num_blocks,
370             str_leak_lossmode(lr->key.state),
371             n_this_record, n_total_records
372          );
373       }
374       VG_(pp_ExeContext)(lr->key.allocated_at);
375    } /* if (xml) */
376 }
377 
MC_(pp_LossRecord)378 void MC_(pp_LossRecord)(UInt n_this_record, UInt n_total_records,
379                         LossRecord* l)
380 {
381    pp_LossRecord (n_this_record, n_total_records, l, /* xml */ False);
382 }
383 
MC_(pp_Error)384 void MC_(pp_Error) ( Error* err )
385 {
386    const Bool xml  = VG_(clo_xml); /* a shorthand */
387    MC_Error* extra = VG_(get_error_extra)(err);
388 
389    switch (VG_(get_error_kind)(err)) {
390       case Err_CoreMem:
391          /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
392          /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
393             signal handler frame.  --njn */
394          // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
395          // the following code is untested.  Bad.
396          if (xml) {
397             emit( "  <kind>CoreMemError</kind>\n" );
398             emit( "  <what>%pS contains unaddressable byte(s)</what>\n",
399                   VG_(get_error_string)(err));
400             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
401          } else {
402             emit( "%s contains unaddressable byte(s)\n",
403                   VG_(get_error_string)(err));
404             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
405          }
406          break;
407 
408       case Err_Value:
409          MC_(any_value_errors) = True;
410          if (xml) {
411             emit( "  <kind>UninitValue</kind>\n" );
412             emit( "  <what>Use of uninitialised value of size %ld</what>\n",
413                   extra->Err.Value.szB );
414             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
415             if (extra->Err.Value.origin_ec)
416                mc_pp_origin( extra->Err.Value.origin_ec,
417                             extra->Err.Value.otag & 3 );
418          } else {
419             /* Could also show extra->Err.Cond.otag if debugging origin
420                tracking */
421             emit( "Use of uninitialised value of size %ld\n",
422                   extra->Err.Value.szB );
423             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
424             if (extra->Err.Value.origin_ec)
425                mc_pp_origin( extra->Err.Value.origin_ec,
426                             extra->Err.Value.otag & 3 );
427          }
428          break;
429 
430       case Err_Cond:
431          MC_(any_value_errors) = True;
432          if (xml) {
433             emit( "  <kind>UninitCondition</kind>\n" );
434             emit( "  <what>Conditional jump or move depends"
435                   " on uninitialised value(s)</what>\n" );
436             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
437             if (extra->Err.Cond.origin_ec)
438                mc_pp_origin( extra->Err.Cond.origin_ec,
439                              extra->Err.Cond.otag & 3 );
440          } else {
441             /* Could also show extra->Err.Cond.otag if debugging origin
442                tracking */
443             emit( "Conditional jump or move depends"
444                   " on uninitialised value(s)\n" );
445             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
446             if (extra->Err.Cond.origin_ec)
447                mc_pp_origin( extra->Err.Cond.origin_ec,
448                              extra->Err.Cond.otag & 3 );
449          }
450          break;
451 
452       case Err_RegParam:
453          MC_(any_value_errors) = True;
454          if (xml) {
455             emit( "  <kind>SyscallParam</kind>\n" );
456             emit( "  <what>Syscall param %pS contains "
457                   "uninitialised byte(s)</what>\n",
458                   VG_(get_error_string)(err) );
459             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
460             if (extra->Err.RegParam.origin_ec)
461                mc_pp_origin( extra->Err.RegParam.origin_ec,
462                              extra->Err.RegParam.otag & 3 );
463          } else {
464             emit( "Syscall param %s contains uninitialised byte(s)\n",
465                   VG_(get_error_string)(err) );
466             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
467             if (extra->Err.RegParam.origin_ec)
468                mc_pp_origin( extra->Err.RegParam.origin_ec,
469                              extra->Err.RegParam.otag & 3 );
470          }
471          break;
472 
473       case Err_MemParam:
474          if (!extra->Err.MemParam.isAddrErr)
475             MC_(any_value_errors) = True;
476          if (xml) {
477             emit( "  <kind>SyscallParam</kind>\n" );
478             emit( "  <what>Syscall param %pS points to %s byte(s)</what>\n",
479                   VG_(get_error_string)(err),
480                   extra->Err.MemParam.isAddrErr
481                      ? "unaddressable" : "uninitialised" );
482             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
483             VG_(pp_addrinfo_mc)(VG_(get_error_address)(err),
484                                 &extra->Err.MemParam.ai, False);
485             if (extra->Err.MemParam.origin_ec
486                 && !extra->Err.MemParam.isAddrErr)
487                mc_pp_origin( extra->Err.MemParam.origin_ec,
488                              extra->Err.MemParam.otag & 3 );
489          } else {
490             emit( "Syscall param %s points to %s byte(s)\n",
491                   VG_(get_error_string)(err),
492                   extra->Err.MemParam.isAddrErr
493                      ? "unaddressable" : "uninitialised" );
494             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
495             VG_(pp_addrinfo_mc)(VG_(get_error_address)(err),
496                                 &extra->Err.MemParam.ai, False);
497             if (extra->Err.MemParam.origin_ec
498                 && !extra->Err.MemParam.isAddrErr)
499                mc_pp_origin( extra->Err.MemParam.origin_ec,
500                              extra->Err.MemParam.otag & 3 );
501          }
502          break;
503 
504       case Err_User:
505          if (!extra->Err.User.isAddrErr)
506             MC_(any_value_errors) = True;
507          if (xml) {
508             emit( "  <kind>ClientCheck</kind>\n" );
509             emit( "  <what>%s byte(s) found "
510                   "during client check request</what>\n",
511                    extra->Err.User.isAddrErr
512                       ? "Unaddressable" : "Uninitialised" );
513             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
514             VG_(pp_addrinfo_mc)(VG_(get_error_address)(err), &extra->Err.User.ai,
515                                 False);
516             if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
517                mc_pp_origin( extra->Err.User.origin_ec,
518                              extra->Err.User.otag & 3 );
519          } else {
520             emit( "%s byte(s) found during client check request\n",
521                    extra->Err.User.isAddrErr
522                       ? "Unaddressable" : "Uninitialised" );
523             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
524             VG_(pp_addrinfo_mc)(VG_(get_error_address)(err), &extra->Err.User.ai,
525                                 False);
526             if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
527                mc_pp_origin( extra->Err.User.origin_ec,
528                              extra->Err.User.otag & 3 );
529          }
530          break;
531 
532       case Err_Free:
533          if (xml) {
534             emit( "  <kind>InvalidFree</kind>\n" );
535             emit( "  <what>Invalid free() / delete / delete[]"
536                   " / realloc()</what>\n" );
537             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
538             VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
539                                  &extra->Err.Free.ai, False );
540          } else {
541             emit( "Invalid free() / delete / delete[] / realloc()\n" );
542             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
543             VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
544                                  &extra->Err.Free.ai, False );
545          }
546          break;
547 
548       case Err_FreeMismatch:
549          if (xml) {
550             emit( "  <kind>MismatchedFree</kind>\n" );
551             emit( "  <what>Mismatched free() / delete / delete []</what>\n" );
552             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
553             VG_(pp_addrinfo_mc)(VG_(get_error_address)(err),
554                                 &extra->Err.FreeMismatch.ai, False);
555          } else {
556             emit( "Mismatched free() / delete / delete []\n" );
557             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
558             VG_(pp_addrinfo_mc)(VG_(get_error_address)(err),
559                                 &extra->Err.FreeMismatch.ai, False);
560          }
561          break;
562 
563       case Err_Addr:
564          if (xml) {
565             emit( "  <kind>Invalid%s</kind>\n",
566                   extra->Err.Addr.isWrite ? "Write" : "Read"  );
567             emit( "  <what>Invalid %s of size %ld</what>\n",
568                   extra->Err.Addr.isWrite ? "write" : "read",
569                   extra->Err.Addr.szB );
570             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
571             VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
572                                  &extra->Err.Addr.ai,
573                                  extra->Err.Addr.maybe_gcc );
574          } else {
575             emit( "Invalid %s of size %ld\n",
576                   extra->Err.Addr.isWrite ? "write" : "read",
577                   extra->Err.Addr.szB );
578             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
579 
580             VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
581                                  &extra->Err.Addr.ai,
582                                  extra->Err.Addr.maybe_gcc );
583          }
584          break;
585 
586       case Err_Jump:
587          if (xml) {
588             emit( "  <kind>InvalidJump</kind>\n" );
589             emit( "  <what>Jump to the invalid address stated "
590                   "on the next line</what>\n" );
591             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
592             VG_(pp_addrinfo_mc)( VG_(get_error_address)(err), &extra->Err.Jump.ai,
593                                  False );
594          } else {
595             emit( "Jump to the invalid address stated on the next line\n" );
596             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
597             VG_(pp_addrinfo_mc)( VG_(get_error_address)(err), &extra->Err.Jump.ai,
598                                  False );
599          }
600          break;
601 
602       case Err_Overlap:
603          if (xml) {
604             emit( "  <kind>Overlap</kind>\n" );
605             if (extra->Err.Overlap.szB == 0) {
606                emit( "  <what>Source and destination overlap "
607                      "in %pS(%#lx, %#lx)\n</what>\n",
608                      VG_(get_error_string)(err),
609                      extra->Err.Overlap.dst, extra->Err.Overlap.src );
610             } else {
611                emit( "  <what>Source and destination overlap "
612                      "in %s(%#lx, %#lx, %lu)</what>\n",
613                      VG_(get_error_string)(err),
614                      extra->Err.Overlap.dst, extra->Err.Overlap.src,
615                      extra->Err.Overlap.szB );
616             }
617             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
618          } else {
619             if (extra->Err.Overlap.szB == 0) {
620                emit( "Source and destination overlap in %pS(%#lx, %#lx)\n",
621                      VG_(get_error_string)(err),
622                      extra->Err.Overlap.dst, extra->Err.Overlap.src );
623             } else {
624                emit( "Source and destination overlap in %s(%#lx, %#lx, %lu)\n",
625                      VG_(get_error_string)(err),
626                      extra->Err.Overlap.dst, extra->Err.Overlap.src,
627                      extra->Err.Overlap.szB );
628             }
629             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
630          }
631          break;
632 
633       case Err_IllegalMempool:
634          // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
635          // the following code is untested.  Bad.
636          if (xml) {
637             emit( "  <kind>InvalidMemPool</kind>\n" );
638             emit( "  <what>Illegal memory pool address</what>\n" );
639             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
640             VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
641                                  &extra->Err.IllegalMempool.ai, False );
642          } else {
643             emit( "Illegal memory pool address\n" );
644             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
645             VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
646                                  &extra->Err.IllegalMempool.ai, False );
647          }
648          break;
649 
650       case Err_Leak: {
651          UInt        n_this_record   = extra->Err.Leak.n_this_record;
652          UInt        n_total_records = extra->Err.Leak.n_total_records;
653          LossRecord* lr              = extra->Err.Leak.lr;
654          pp_LossRecord (n_this_record, n_total_records, lr, xml);
655          break;
656       }
657 
658       default:
659          VG_(printf)("Error:\n  unknown Memcheck error code %d\n",
660                      VG_(get_error_kind)(err));
661          VG_(tool_panic)("unknown error code in mc_pp_Error)");
662    }
663 }
664 
665 /*------------------------------------------------------------*/
666 /*--- Recording errors                                     ---*/
667 /*------------------------------------------------------------*/
668 
669 /* These many bytes below %ESP are considered addressible if we're
670    doing the --workaround-gcc296-bugs hack. */
671 #define VG_GCC296_BUG_STACK_SLOP 1024
672 
673 /* Is this address within some small distance below %ESP?  Used only
674    for the --workaround-gcc296-bugs kludge. */
is_just_below_ESP(Addr esp,Addr aa)675 static Bool is_just_below_ESP( Addr esp, Addr aa )
676 {
677    esp -= VG_STACK_REDZONE_SZB;
678    if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
679       return True;
680    else
681       return False;
682 }
683 
684 /* --- Called from generated and non-generated code --- */
685 
MC_(record_address_error)686 void MC_(record_address_error) ( ThreadId tid, Addr a, Int szB,
687                                  Bool isWrite )
688 {
689    MC_Error extra;
690    Bool     just_below_esp;
691 
692    if (MC_(in_ignored_range)(a))
693       return;
694 
695    if (VG_(is_watched)( (isWrite ? write_watchpoint : read_watchpoint), a, szB))
696       return;
697 
698    just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
699 
700    /* If this is caused by an access immediately below %ESP, and the
701       user asks nicely, we just ignore it. */
702    if (MC_(clo_workaround_gcc296_bugs) && just_below_esp)
703       return;
704 
705    extra.Err.Addr.isWrite   = isWrite;
706    extra.Err.Addr.szB       = szB;
707    extra.Err.Addr.maybe_gcc = just_below_esp;
708    extra.Err.Addr.ai.tag    = Addr_Undescribed;
709    VG_(maybe_record_error)( tid, Err_Addr, a, /*s*/NULL, &extra );
710 }
711 
MC_(record_value_error)712 void MC_(record_value_error) ( ThreadId tid, Int szB, UInt otag )
713 {
714    MC_Error extra;
715    tl_assert( MC_(clo_mc_level) >= 2 );
716    if (otag > 0)
717       tl_assert( MC_(clo_mc_level) == 3 );
718    extra.Err.Value.szB       = szB;
719    extra.Err.Value.otag      = otag;
720    extra.Err.Value.origin_ec = NULL;  /* Filled in later */
721    VG_(maybe_record_error)( tid, Err_Value, /*addr*/0, /*s*/NULL, &extra );
722 }
723 
MC_(record_cond_error)724 void MC_(record_cond_error) ( ThreadId tid, UInt otag )
725 {
726    MC_Error extra;
727    tl_assert( MC_(clo_mc_level) >= 2 );
728    if (otag > 0)
729       tl_assert( MC_(clo_mc_level) == 3 );
730    extra.Err.Cond.otag      = otag;
731    extra.Err.Cond.origin_ec = NULL;  /* Filled in later */
732    VG_(maybe_record_error)( tid, Err_Cond, /*addr*/0, /*s*/NULL, &extra );
733 }
734 
735 /* --- Called from non-generated code --- */
736 
737 /* This is for memory errors in signal-related memory. */
MC_(record_core_mem_error)738 void MC_(record_core_mem_error) ( ThreadId tid, const HChar* msg )
739 {
740    VG_(maybe_record_error)( tid, Err_CoreMem, /*addr*/0, msg, /*extra*/NULL );
741 }
742 
MC_(record_regparam_error)743 void MC_(record_regparam_error) ( ThreadId tid, const HChar* msg, UInt otag )
744 {
745    MC_Error extra;
746    tl_assert(VG_INVALID_THREADID != tid);
747    if (otag > 0)
748       tl_assert( MC_(clo_mc_level) == 3 );
749    extra.Err.RegParam.otag      = otag;
750    extra.Err.RegParam.origin_ec = NULL;  /* Filled in later */
751    VG_(maybe_record_error)( tid, Err_RegParam, /*addr*/0, msg, &extra );
752 }
753 
MC_(record_memparam_error)754 void MC_(record_memparam_error) ( ThreadId tid, Addr a,
755                                   Bool isAddrErr, const HChar* msg, UInt otag )
756 {
757    MC_Error extra;
758    tl_assert(VG_INVALID_THREADID != tid);
759    if (!isAddrErr)
760       tl_assert( MC_(clo_mc_level) >= 2 );
761    if (otag != 0) {
762       tl_assert( MC_(clo_mc_level) == 3 );
763       tl_assert( !isAddrErr );
764    }
765    extra.Err.MemParam.isAddrErr = isAddrErr;
766    extra.Err.MemParam.ai.tag    = Addr_Undescribed;
767    extra.Err.MemParam.otag      = otag;
768    extra.Err.MemParam.origin_ec = NULL;  /* Filled in later */
769    VG_(maybe_record_error)( tid, Err_MemParam, a, msg, &extra );
770 }
771 
MC_(record_jump_error)772 void MC_(record_jump_error) ( ThreadId tid, Addr a )
773 {
774    MC_Error extra;
775    tl_assert(VG_INVALID_THREADID != tid);
776    extra.Err.Jump.ai.tag = Addr_Undescribed;
777    VG_(maybe_record_error)( tid, Err_Jump, a, /*s*/NULL, &extra );
778 }
779 
MC_(record_free_error)780 void MC_(record_free_error) ( ThreadId tid, Addr a )
781 {
782    MC_Error extra;
783    tl_assert(VG_INVALID_THREADID != tid);
784    extra.Err.Free.ai.tag = Addr_Undescribed;
785    VG_(maybe_record_error)( tid, Err_Free, a, /*s*/NULL, &extra );
786 }
787 
MC_(record_freemismatch_error)788 void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* mc )
789 {
790    MC_Error extra;
791    AddrInfo* ai = &extra.Err.FreeMismatch.ai;
792    tl_assert(VG_INVALID_THREADID != tid);
793    ai->tag = Addr_Block;
794    ai->Addr.Block.block_kind = Block_Mallocd;  // Nb: Not 'Block_Freed'
795    ai->Addr.Block.block_desc = "block";
796    ai->Addr.Block.block_szB  = mc->szB;
797    ai->Addr.Block.rwoffset   = 0;
798    ai->Addr.Block.allocated_at = MC_(allocated_at) (mc);
799    ai->Addr.Block.freed_at = MC_(freed_at) (mc);
800    VG_(maybe_record_error)( tid, Err_FreeMismatch, mc->data, /*s*/NULL,
801                             &extra );
802 }
803 
MC_(record_illegal_mempool_error)804 void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
805 {
806    MC_Error extra;
807    tl_assert(VG_INVALID_THREADID != tid);
808    extra.Err.IllegalMempool.ai.tag = Addr_Undescribed;
809    VG_(maybe_record_error)( tid, Err_IllegalMempool, a, /*s*/NULL, &extra );
810 }
811 
MC_(record_overlap_error)812 void MC_(record_overlap_error) ( ThreadId tid, const HChar* function,
813                                  Addr src, Addr dst, SizeT szB )
814 {
815    MC_Error extra;
816    tl_assert(VG_INVALID_THREADID != tid);
817    extra.Err.Overlap.src = src;
818    extra.Err.Overlap.dst = dst;
819    extra.Err.Overlap.szB = szB;
820    VG_(maybe_record_error)(
821       tid, Err_Overlap, /*addr*/0, /*s*/function, &extra );
822 }
823 
MC_(record_leak_error)824 Bool MC_(record_leak_error) ( ThreadId tid, UInt n_this_record,
825                               UInt n_total_records, LossRecord* lr,
826                               Bool print_record, Bool count_error )
827 {
828    MC_Error extra;
829    extra.Err.Leak.n_this_record   = n_this_record;
830    extra.Err.Leak.n_total_records = n_total_records;
831    extra.Err.Leak.lr              = lr;
832    return
833    VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
834                        lr->key.allocated_at, print_record,
835                        /*allow_GDB_attach*/False, count_error );
836 }
837 
MC_(record_user_error)838 void MC_(record_user_error) ( ThreadId tid, Addr a,
839                               Bool isAddrErr, UInt otag )
840 {
841    MC_Error extra;
842    if (otag != 0) {
843       tl_assert(!isAddrErr);
844       tl_assert( MC_(clo_mc_level) == 3 );
845    }
846    if (!isAddrErr) {
847       tl_assert( MC_(clo_mc_level) >= 2 );
848    }
849    tl_assert(VG_INVALID_THREADID != tid);
850    extra.Err.User.isAddrErr = isAddrErr;
851    extra.Err.User.ai.tag    = Addr_Undescribed;
852    extra.Err.User.otag      = otag;
853    extra.Err.User.origin_ec = NULL;  /* Filled in later */
854    VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra );
855 }
856 
857 /*------------------------------------------------------------*/
858 /*--- Other error operations                               ---*/
859 /*------------------------------------------------------------*/
860 
861 /* Compare error contexts, to detect duplicates.  Note that if they
862    are otherwise the same, the faulting addrs and associated rwoffsets
863    are allowed to be different.  */
MC_(eq_Error)864 Bool MC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
865 {
866    MC_Error* extra1 = VG_(get_error_extra)(e1);
867    MC_Error* extra2 = VG_(get_error_extra)(e2);
868 
869    /* Guaranteed by calling function */
870    tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
871 
872    switch (VG_(get_error_kind)(e1)) {
873       case Err_CoreMem: {
874          const HChar *e1s, *e2s;
875          e1s = VG_(get_error_string)(e1);
876          e2s = VG_(get_error_string)(e2);
877          if (e1s == e2s)                   return True;
878          if (VG_STREQ(e1s, e2s))           return True;
879          return False;
880       }
881 
882       case Err_RegParam:
883          return VG_STREQ(VG_(get_error_string)(e1), VG_(get_error_string)(e2));
884 
885       // Perhaps we should also check the addrinfo.akinds for equality.
886       // That would result in more error reports, but only in cases where
887       // a register contains uninitialised bytes and points to memory
888       // containing uninitialised bytes.  Currently, the 2nd of those to be
889       // detected won't be reported.  That is (nearly?) always the memory
890       // error, which is good.
891       case Err_MemParam:
892          if (!VG_STREQ(VG_(get_error_string)(e1),
893                        VG_(get_error_string)(e2))) return False;
894          // fall through
895       case Err_User:
896          return ( extra1->Err.User.isAddrErr == extra2->Err.User.isAddrErr
897                 ? True : False );
898 
899       case Err_Free:
900       case Err_FreeMismatch:
901       case Err_Jump:
902       case Err_IllegalMempool:
903       case Err_Overlap:
904       case Err_Cond:
905          return True;
906 
907       case Err_Addr:
908          return ( extra1->Err.Addr.szB == extra2->Err.Addr.szB
909                 ? True : False );
910 
911       case Err_Value:
912          return ( extra1->Err.Value.szB == extra2->Err.Value.szB
913                 ? True : False );
914 
915       case Err_Leak:
916          VG_(tool_panic)("Shouldn't get Err_Leak in mc_eq_Error,\n"
917                          "since it's handled with VG_(unique_error)()!");
918 
919       default:
920          VG_(printf)("Error:\n  unknown error code %d\n",
921                      VG_(get_error_kind)(e1));
922          VG_(tool_panic)("unknown error code in mc_eq_Error");
923    }
924 }
925 
926 /* Functions used when searching MC_Chunk lists */
927 static
addr_is_in_MC_Chunk_default_REDZONE_SZB(MC_Chunk * mc,Addr a)928 Bool addr_is_in_MC_Chunk_default_REDZONE_SZB(MC_Chunk* mc, Addr a)
929 {
930    return VG_(addr_is_in_block)( a, mc->data, mc->szB,
931                                  MC_(Malloc_Redzone_SzB) );
932 }
933 static
addr_is_in_MC_Chunk_with_REDZONE_SZB(MC_Chunk * mc,Addr a,SizeT rzB)934 Bool addr_is_in_MC_Chunk_with_REDZONE_SZB(MC_Chunk* mc, Addr a, SizeT rzB)
935 {
936    return VG_(addr_is_in_block)( a, mc->data, mc->szB,
937                                  rzB );
938 }
939 
940 // Forward declarations
941 static Bool client_block_maybe_describe( Addr a, AddrInfo* ai );
942 static Bool mempool_block_maybe_describe( Addr a, AddrInfo* ai );
943 
944 
945 /* Describe an address as best you can, for error messages,
946    putting the result in ai. */
describe_addr(Addr a,AddrInfo * ai)947 static void describe_addr ( Addr a, /*OUT*/AddrInfo* ai )
948 {
949    MC_Chunk*  mc;
950 
951    tl_assert(Addr_Undescribed == ai->tag);
952 
953    /* -- Perhaps it's a user-named block? -- */
954    if (client_block_maybe_describe( a, ai )) {
955       return;
956    }
957    /* -- Perhaps it's in mempool block? -- */
958    if (mempool_block_maybe_describe( a, ai )) {
959       return;
960    }
961    /* Blocks allocated by memcheck malloc functions are either
962       on the recently freed list or on the malloc-ed list.
963       Custom blocks can be on both : a recently freed block might
964       have been just re-allocated.
965       So, first search the malloc-ed block, as the most recent
966       block is the probable cause of error.
967       We however detect and report that this is a recently re-allocated
968       block. */
969    /* -- Search for a currently malloc'd block which might bracket it. -- */
970    VG_(HT_ResetIter)(MC_(malloc_list));
971    while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
972       if (addr_is_in_MC_Chunk_default_REDZONE_SZB(mc, a)) {
973          ai->tag = Addr_Block;
974          ai->Addr.Block.block_kind = Block_Mallocd;
975          if (MC_(get_freed_block_bracketting)( a ))
976             ai->Addr.Block.block_desc = "recently re-allocated block";
977          else
978             ai->Addr.Block.block_desc = "block";
979          ai->Addr.Block.block_szB  = mc->szB;
980          ai->Addr.Block.rwoffset   = (Word)a - (Word)mc->data;
981          ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
982          ai->Addr.Block.freed_at = MC_(freed_at)(mc);
983          return;
984       }
985    }
986    /* -- Search for a recently freed block which might bracket it. -- */
987    mc = MC_(get_freed_block_bracketting)( a );
988    if (mc) {
989       ai->tag = Addr_Block;
990       ai->Addr.Block.block_kind = Block_Freed;
991       ai->Addr.Block.block_desc = "block";
992       ai->Addr.Block.block_szB  = mc->szB;
993       ai->Addr.Block.rwoffset   = (Word)a - (Word)mc->data;
994       ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
995       ai->Addr.Block.freed_at = MC_(freed_at)(mc);
996       return;
997    }
998 
999    /* No block found. Search a non-heap block description. */
1000    VG_(describe_addr) (a, ai);
1001 }
1002 
MC_(pp_describe_addr)1003 void MC_(pp_describe_addr) ( Addr a )
1004 {
1005    AddrInfo ai;
1006 
1007    ai.tag = Addr_Undescribed;
1008    describe_addr (a, &ai);
1009    VG_(pp_addrinfo_mc) (a, &ai, /* maybe_gcc */ False);
1010 }
1011 
1012 /* Fill in *origin_ec as specified by otag, or NULL it out if otag
1013    does not refer to a known origin. */
update_origin(ExeContext ** origin_ec,UInt otag)1014 static void update_origin ( /*OUT*/ExeContext** origin_ec,
1015                             UInt otag )
1016 {
1017    UInt ecu = otag & ~3;
1018    *origin_ec = NULL;
1019    if (VG_(is_plausible_ECU)(ecu)) {
1020       *origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
1021    }
1022 }
1023 
1024 /* Updates the copy with address info if necessary (but not for all errors). */
MC_(update_Error_extra)1025 UInt MC_(update_Error_extra)( Error* err )
1026 {
1027    MC_Error* extra = VG_(get_error_extra)(err);
1028 
1029    switch (VG_(get_error_kind)(err)) {
1030    // These ones don't have addresses associated with them, and so don't
1031    // need any updating.
1032    case Err_CoreMem:
1033    //case Err_Value:
1034    //case Err_Cond:
1035    case Err_Overlap:
1036    // For Err_Leaks the returned size does not matter -- they are always
1037    // shown with VG_(unique_error)() so they 'extra' not copied.  But
1038    // we make it consistent with the others.
1039    case Err_Leak:
1040       return sizeof(MC_Error);
1041 
1042    // For value errors, get the ExeContext corresponding to the
1043    // origin tag.  Note that it is a kludge to assume that
1044    // a length-1 trace indicates a stack origin.  FIXME.
1045    case Err_Value:
1046       update_origin( &extra->Err.Value.origin_ec,
1047                      extra->Err.Value.otag );
1048       return sizeof(MC_Error);
1049    case Err_Cond:
1050       update_origin( &extra->Err.Cond.origin_ec,
1051                      extra->Err.Cond.otag );
1052       return sizeof(MC_Error);
1053    case Err_RegParam:
1054       update_origin( &extra->Err.RegParam.origin_ec,
1055                      extra->Err.RegParam.otag );
1056       return sizeof(MC_Error);
1057 
1058    // These ones always involve a memory address.
1059    case Err_Addr:
1060       describe_addr ( VG_(get_error_address)(err),
1061                       &extra->Err.Addr.ai );
1062       return sizeof(MC_Error);
1063    case Err_MemParam:
1064       describe_addr ( VG_(get_error_address)(err),
1065                       &extra->Err.MemParam.ai );
1066       update_origin( &extra->Err.MemParam.origin_ec,
1067                      extra->Err.MemParam.otag );
1068       return sizeof(MC_Error);
1069    case Err_Jump:
1070       describe_addr ( VG_(get_error_address)(err),
1071                       &extra->Err.Jump.ai );
1072       return sizeof(MC_Error);
1073    case Err_User:
1074       describe_addr ( VG_(get_error_address)(err),
1075                       &extra->Err.User.ai );
1076       update_origin( &extra->Err.User.origin_ec,
1077                      extra->Err.User.otag );
1078       return sizeof(MC_Error);
1079    case Err_Free:
1080       describe_addr ( VG_(get_error_address)(err),
1081                       &extra->Err.Free.ai );
1082       return sizeof(MC_Error);
1083    case Err_IllegalMempool:
1084       describe_addr ( VG_(get_error_address)(err),
1085                       &extra->Err.IllegalMempool.ai );
1086       return sizeof(MC_Error);
1087 
1088    // Err_FreeMismatches have already had their address described;  this is
1089    // possible because we have the MC_Chunk on hand when the error is
1090    // detected.  However, the address may be part of a user block, and if so
1091    // we override the pre-determined description with a user block one.
1092    case Err_FreeMismatch: {
1093       tl_assert(extra && Block_Mallocd ==
1094                 extra->Err.FreeMismatch.ai.Addr.Block.block_kind);
1095       (void)client_block_maybe_describe( VG_(get_error_address)(err),
1096                                         &extra->Err.FreeMismatch.ai );
1097       return sizeof(MC_Error);
1098    }
1099 
1100    default: VG_(tool_panic)("mc_update_extra: bad errkind");
1101    }
1102 }
1103 
1104 
client_block_maybe_describe(Addr a,AddrInfo * ai)1105 static Bool client_block_maybe_describe( Addr a,
1106                                          /*OUT*/AddrInfo* ai )
1107 {
1108    UWord      i;
1109    CGenBlock* cgbs = NULL;
1110    UWord      cgb_used = 0;
1111 
1112    MC_(get_ClientBlock_array)( &cgbs, &cgb_used );
1113    if (cgbs == NULL)
1114       tl_assert(cgb_used == 0);
1115 
1116    /* Perhaps it's a general block ? */
1117    for (i = 0; i < cgb_used; i++) {
1118       if (cgbs[i].start == 0 && cgbs[i].size == 0)
1119          continue;
1120       // Use zero as the redzone for client blocks.
1121       if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
1122          ai->tag = Addr_Block;
1123          ai->Addr.Block.block_kind = Block_UserG;
1124          ai->Addr.Block.block_desc = cgbs[i].desc;
1125          ai->Addr.Block.block_szB  = cgbs[i].size;
1126          ai->Addr.Block.rwoffset   = (Word)(a) - (Word)(cgbs[i].start);
1127          ai->Addr.Block.allocated_at = cgbs[i].where;
1128          ai->Addr.Block.freed_at = VG_(null_ExeContext)();;
1129          return True;
1130       }
1131    }
1132    return False;
1133 }
1134 
1135 
mempool_block_maybe_describe(Addr a,AddrInfo * ai)1136 static Bool mempool_block_maybe_describe( Addr a,
1137                                           /*OUT*/AddrInfo* ai )
1138 {
1139    MC_Mempool* mp;
1140    tl_assert( MC_(mempool_list) );
1141 
1142    VG_(HT_ResetIter)( MC_(mempool_list) );
1143    while ( (mp = VG_(HT_Next)(MC_(mempool_list))) ) {
1144       if (mp->chunks != NULL) {
1145          MC_Chunk* mc;
1146          VG_(HT_ResetIter)(mp->chunks);
1147          while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
1148             if (addr_is_in_MC_Chunk_with_REDZONE_SZB(mc, a, mp->rzB)) {
1149                ai->tag = Addr_Block;
1150                ai->Addr.Block.block_kind = Block_MempoolChunk;
1151                ai->Addr.Block.block_desc = "block";
1152                ai->Addr.Block.block_szB  = mc->szB;
1153                ai->Addr.Block.rwoffset   = (Word)a - (Word)mc->data;
1154                ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
1155                ai->Addr.Block.freed_at = MC_(freed_at)(mc);
1156                return True;
1157             }
1158          }
1159       }
1160    }
1161    return False;
1162 }
1163 
1164 
1165 /*------------------------------------------------------------*/
1166 /*--- Suppressions                                         ---*/
1167 /*------------------------------------------------------------*/
1168 
1169 typedef
1170    enum {
1171       ParamSupp,     // Bad syscall params
1172       UserSupp,      // Errors arising from client-request checks
1173       CoreMemSupp,   // Memory errors in core (pthread ops, signal handling)
1174 
1175       // Undefined value errors of given size
1176       Value1Supp, Value2Supp, Value4Supp, Value8Supp, Value16Supp,
1177 
1178       // Undefined value error in conditional.
1179       CondSupp,
1180 
1181       // Unaddressable read/write attempt at given size
1182       Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp, Addr16Supp,
1183 
1184       JumpSupp,      // Jump to unaddressable target
1185       FreeSupp,      // Invalid or mismatching free
1186       OverlapSupp,   // Overlapping blocks in memcpy(), strcpy(), etc
1187       LeakSupp,      // Something to be suppressed in a leak check.
1188       MempoolSupp,   // Memory pool suppression.
1189    }
1190    MC_SuppKind;
1191 
MC_(is_recognised_suppression)1192 Bool MC_(is_recognised_suppression) ( const HChar* name, Supp* su )
1193 {
1194    SuppKind skind;
1195 
1196    if      (VG_STREQ(name, "Param"))   skind = ParamSupp;
1197    else if (VG_STREQ(name, "User"))    skind = UserSupp;
1198    else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
1199    else if (VG_STREQ(name, "Addr1"))   skind = Addr1Supp;
1200    else if (VG_STREQ(name, "Addr2"))   skind = Addr2Supp;
1201    else if (VG_STREQ(name, "Addr4"))   skind = Addr4Supp;
1202    else if (VG_STREQ(name, "Addr8"))   skind = Addr8Supp;
1203    else if (VG_STREQ(name, "Addr16"))  skind = Addr16Supp;
1204    else if (VG_STREQ(name, "Jump"))    skind = JumpSupp;
1205    else if (VG_STREQ(name, "Free"))    skind = FreeSupp;
1206    else if (VG_STREQ(name, "Leak"))    skind = LeakSupp;
1207    else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
1208    else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
1209    else if (VG_STREQ(name, "Cond"))    skind = CondSupp;
1210    else if (VG_STREQ(name, "Value0"))  skind = CondSupp; /* backwards compat */
1211    else if (VG_STREQ(name, "Value1"))  skind = Value1Supp;
1212    else if (VG_STREQ(name, "Value2"))  skind = Value2Supp;
1213    else if (VG_STREQ(name, "Value4"))  skind = Value4Supp;
1214    else if (VG_STREQ(name, "Value8"))  skind = Value8Supp;
1215    else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
1216    else
1217       return False;
1218 
1219    VG_(set_supp_kind)(su, skind);
1220    return True;
1221 }
1222 
1223 typedef struct _MC_LeakSuppExtra MC_LeakSuppExtra;
1224 
1225 struct _MC_LeakSuppExtra {
1226    UInt match_leak_kinds;
1227 
1228    /* Maintains nr of blocks and bytes suppressed with this suppression
1229       during the leak search identified by leak_search_gen.
1230       blocks_suppressed and bytes_suppressed are reset to 0 when
1231       used the first time during a leak search. */
1232    SizeT blocks_suppressed;
1233    SizeT bytes_suppressed;
1234    UInt  leak_search_gen;
1235 };
1236 
MC_(read_extra_suppression_info)1237 Bool MC_(read_extra_suppression_info) ( Int fd, HChar** bufpp,
1238                                         SizeT* nBufp, Int* lineno, Supp *su )
1239 {
1240    Bool eof;
1241    Int i;
1242 
1243    if (VG_(get_supp_kind)(su) == ParamSupp) {
1244       eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
1245       if (eof) return False;
1246       VG_(set_supp_string)(su, VG_(strdup)("mc.resi.1", *bufpp));
1247    } else if (VG_(get_supp_kind)(su) == LeakSupp) {
1248       // We might have the optional match-leak-kinds line
1249       MC_LeakSuppExtra* lse;
1250       lse = VG_(malloc)("mc.resi.2", sizeof(MC_LeakSuppExtra));
1251       lse->match_leak_kinds = RallS;
1252       lse->blocks_suppressed = 0;
1253       lse->bytes_suppressed = 0;
1254       lse->leak_search_gen = 0;
1255       VG_(set_supp_extra)(su, lse); // By default, all kinds will match.
1256       eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
1257       if (eof) return True; // old LeakSupp style, no match-leak-kinds line.
1258       if (0 == VG_(strncmp)(*bufpp, "match-leak-kinds:", 17)) {
1259          i = 17;
1260          while ((*bufpp)[i] && VG_(isspace((*bufpp)[i])))
1261             i++;
1262          if (!MC_(parse_leak_kinds)((*bufpp)+i, &lse->match_leak_kinds)) {
1263             return False;
1264          }
1265       } else {
1266          return False; // unknown extra line.
1267       }
1268    }
1269    return True;
1270 }
1271 
MC_(error_matches_suppression)1272 Bool MC_(error_matches_suppression) ( Error* err, Supp* su )
1273 {
1274    Int       su_szB;
1275    MC_Error* extra = VG_(get_error_extra)(err);
1276    ErrorKind ekind = VG_(get_error_kind )(err);
1277 
1278    switch (VG_(get_supp_kind)(su)) {
1279       case ParamSupp:
1280          return ((ekind == Err_RegParam || ekind == Err_MemParam)
1281               && VG_STREQ(VG_(get_error_string)(err),
1282                           VG_(get_supp_string)(su)));
1283 
1284       case UserSupp:
1285          return (ekind == Err_User);
1286 
1287       case CoreMemSupp:
1288          return (ekind == Err_CoreMem
1289               && VG_STREQ(VG_(get_error_string)(err),
1290                           VG_(get_supp_string)(su)));
1291 
1292       case Value1Supp: su_szB = 1; goto value_case;
1293       case Value2Supp: su_szB = 2; goto value_case;
1294       case Value4Supp: su_szB = 4; goto value_case;
1295       case Value8Supp: su_szB = 8; goto value_case;
1296       case Value16Supp:su_szB =16; goto value_case;
1297       value_case:
1298          return (ekind == Err_Value && extra->Err.Value.szB == su_szB);
1299 
1300       case CondSupp:
1301          return (ekind == Err_Cond);
1302 
1303       case Addr1Supp: su_szB = 1; goto addr_case;
1304       case Addr2Supp: su_szB = 2; goto addr_case;
1305       case Addr4Supp: su_szB = 4; goto addr_case;
1306       case Addr8Supp: su_szB = 8; goto addr_case;
1307       case Addr16Supp:su_szB =16; goto addr_case;
1308       addr_case:
1309          return (ekind == Err_Addr && extra->Err.Addr.szB == su_szB);
1310 
1311       case JumpSupp:
1312          return (ekind == Err_Jump);
1313 
1314       case FreeSupp:
1315          return (ekind == Err_Free || ekind == Err_FreeMismatch);
1316 
1317       case OverlapSupp:
1318          return (ekind == Err_Overlap);
1319 
1320       case LeakSupp:
1321          if (ekind == Err_Leak) {
1322             MC_LeakSuppExtra* lse = (MC_LeakSuppExtra*) VG_(get_supp_extra)(su);
1323             if (lse->leak_search_gen != MC_(leak_search_gen)) {
1324                // First time we see this suppression during this leak search.
1325                // => reset the counters to 0.
1326                lse->blocks_suppressed = 0;
1327                lse->bytes_suppressed = 0;
1328                lse->leak_search_gen = MC_(leak_search_gen);
1329             }
1330             return RiS(extra->Err.Leak.lr->key.state, lse->match_leak_kinds);
1331          } else
1332             return False;
1333 
1334       case MempoolSupp:
1335          return (ekind == Err_IllegalMempool);
1336 
1337       default:
1338          VG_(printf)("Error:\n"
1339                      "  unknown suppression type %d\n",
1340                      VG_(get_supp_kind)(su));
1341          VG_(tool_panic)("unknown suppression type in "
1342                          "MC_(error_matches_suppression)");
1343    }
1344 }
1345 
MC_(get_error_name)1346 const HChar* MC_(get_error_name) ( Error* err )
1347 {
1348    switch (VG_(get_error_kind)(err)) {
1349    case Err_RegParam:       return "Param";
1350    case Err_MemParam:       return "Param";
1351    case Err_User:           return "User";
1352    case Err_FreeMismatch:   return "Free";
1353    case Err_IllegalMempool: return "Mempool";
1354    case Err_Free:           return "Free";
1355    case Err_Jump:           return "Jump";
1356    case Err_CoreMem:        return "CoreMem";
1357    case Err_Overlap:        return "Overlap";
1358    case Err_Leak:           return "Leak";
1359    case Err_Cond:           return "Cond";
1360    case Err_Addr: {
1361       MC_Error* extra = VG_(get_error_extra)(err);
1362       switch ( extra->Err.Addr.szB ) {
1363       case 1:               return "Addr1";
1364       case 2:               return "Addr2";
1365       case 4:               return "Addr4";
1366       case 8:               return "Addr8";
1367       case 16:              return "Addr16";
1368       default:              VG_(tool_panic)("unexpected size for Addr");
1369       }
1370    }
1371    case Err_Value: {
1372       MC_Error* extra = VG_(get_error_extra)(err);
1373       switch ( extra->Err.Value.szB ) {
1374       case 1:               return "Value1";
1375       case 2:               return "Value2";
1376       case 4:               return "Value4";
1377       case 8:               return "Value8";
1378       case 16:              return "Value16";
1379       default:              VG_(tool_panic)("unexpected size for Value");
1380       }
1381    }
1382    default:                 VG_(tool_panic)("get_error_name: unexpected type");
1383    }
1384 }
1385 
MC_(get_extra_suppression_info)1386 Bool MC_(get_extra_suppression_info) ( Error* err,
1387                                        /*OUT*/HChar* buf, Int nBuf )
1388 {
1389    ErrorKind ekind = VG_(get_error_kind )(err);
1390    tl_assert(buf);
1391    tl_assert(nBuf >= 16); // stay sane
1392    if (Err_RegParam == ekind || Err_MemParam == ekind) {
1393       const HChar* errstr = VG_(get_error_string)(err);
1394       tl_assert(errstr);
1395       VG_(snprintf)(buf, nBuf-1, "%s", errstr);
1396       return True;
1397    } else if (Err_Leak == ekind) {
1398       MC_Error* extra = VG_(get_error_extra)(err);
1399       VG_(snprintf)
1400          (buf, nBuf-1, "match-leak-kinds: %s",
1401           pp_Reachedness_for_leak_kinds(extra->Err.Leak.lr->key.state));
1402       return True;
1403    } else {
1404       return False;
1405    }
1406 }
1407 
MC_(print_extra_suppression_use)1408 Bool MC_(print_extra_suppression_use) ( Supp *su,
1409                                         /*OUT*/HChar *buf, Int nBuf )
1410 {
1411    if (VG_(get_supp_kind)(su) == LeakSupp) {
1412       MC_LeakSuppExtra *lse = (MC_LeakSuppExtra*) VG_(get_supp_extra) (su);
1413 
1414       if (lse->leak_search_gen == MC_(leak_search_gen)
1415           && lse->blocks_suppressed > 0) {
1416          VG_(snprintf) (buf, nBuf-1,
1417                         "suppressed: %'lu bytes in %'lu blocks",
1418                         lse->bytes_suppressed,
1419                         lse->blocks_suppressed);
1420          return True;
1421       } else
1422          return False;
1423    } else
1424       return False;
1425 }
1426 
MC_(update_extra_suppression_use)1427 void MC_(update_extra_suppression_use) ( Error* err, Supp* su)
1428 {
1429    if (VG_(get_supp_kind)(su) == LeakSupp) {
1430       MC_LeakSuppExtra *lse = (MC_LeakSuppExtra*) VG_(get_supp_extra) (su);
1431       MC_Error* extra = VG_(get_error_extra)(err);
1432 
1433       tl_assert (lse->leak_search_gen = MC_(leak_search_gen));
1434       lse->blocks_suppressed += extra->Err.Leak.lr->num_blocks;
1435       lse->bytes_suppressed
1436          += extra->Err.Leak.lr->szB + extra->Err.Leak.lr->indirect_szB;
1437    }
1438 }
1439 
1440 /*--------------------------------------------------------------------*/
1441 /*--- end                                              mc_errors.c ---*/
1442 /*--------------------------------------------------------------------*/
1443