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