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