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