1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Ptrcheck: a pointer-use checker.                             ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Provides stuff shared between sg_ and h_ subtools.           ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                  pc_common.c ---*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Ptrcheck, a Valgrind tool for checking pointer
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use in programs.
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2008-2011 OpenWorks Ltd
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.co.uk
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_xarray.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_options.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_replacemalloc.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_execontext.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h"    // CorePart
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_threadstate.h"  // VG_(get_running_tid)
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_debuginfo.h"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pc_common.h"   // self, & Seg
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "h_main.h"      // NONPTR, BOTTOM, UNKNOWN
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//////////////////////////////////////////////////////////////
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                          //
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Command line options                                     //
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                          //
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//////////////////////////////////////////////////////////////
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool h_clo_partial_loads_ok  = True;   /* user visible */
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Bool h_clo_lossage_check     = False; */ /* dev flag only */
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool sg_clo_enable_sg_checks = True;   /* user visible */
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool pc_process_cmd_line_options(Char* arg)
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if VG_BOOL_CLO(arg, "--partial-loads-ok", h_clo_partial_loads_ok) {}
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* else if VG_BOOL_CLO(arg, "--lossage-check",    h_clo_lossage_check) {} */
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--enable-sg-checks", sg_clo_enable_sg_checks) {}
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(replacement_malloc_process_cmd_line_option)(arg);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pc_print_usage(void)
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)(
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "    --partial-loads-ok=no|yes  same as for Memcheck [yes]\n"
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "    --enable-sg-checks=no|yes  enable stack & global array checking? [yes]\n"
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pc_print_debug_usage(void)
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)(
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    (none)\n"
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//"    --lossage-check=no|yes    gather stats for quality control [no]\n"
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//////////////////////////////////////////////////////////////
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                          //
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Error management -- storage                              //
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                          //
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//////////////////////////////////////////////////////////////
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* What kind of error it is. */
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum {
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XE_SorG=1202, // sg: stack or global array inconsistency
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XE_Heap,      // h: mismatched ptr/addr segments on load/store
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XE_Arith,     // h: bad arithmetic between two segment pointers
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XE_SysParam   // h: block straddling >1 segment passed to syscall
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XErrorTag;
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum {
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XS_SorG=2021,
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XS_Heap,
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XS_Arith,
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XS_SysParam
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XSuppTag;
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      XErrorTag tag;
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union {
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Addr   addr;
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            SSizeT sszB;  /* -ve is write, +ve is read */
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HChar  expect[128];
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HChar  actual[128];
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            HChar  delta[32]; // text showing relation to expected
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } SorG;
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Addr     addr;
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            SSizeT   sszB;  /* -ve is write, +ve is read */
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Seg*     vseg;
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            XArray*  descr1; /* XArray* of HChar */
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            XArray*  descr2; /* XArray* of HChar */
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Char     datasym[96];
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            PtrdiffT datasymoff;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Heap;
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Seg* seg1;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Seg* seg2;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            const HChar* opname; // user-understandable text name
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Arith;
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CorePart part;
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Addr lo;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Addr hi;
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Seg* seglo;
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Seg* seghi;
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } SysParam;
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } XE;
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError;
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid sg_record_error_SorG ( ThreadId tid,
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            Addr addr, SSizeT sszB,
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            HChar* expect, HChar* actual, HChar* delta )
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError xe;
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(&xe, 0, sizeof(xe));
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.tag = XE_SorG;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SorG.addr = addr;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SorG.sszB = sszB;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(strncpy)( &xe.XE.SorG.expect[0],
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 expect, sizeof(xe.XE.SorG.expect) );
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(strncpy)( &xe.XE.SorG.actual[0],
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 actual, sizeof(xe.XE.SorG.actual) );
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(strncpy)( &xe.XE.SorG.delta[0],
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 delta, sizeof(xe.XE.SorG.delta) );
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SorG.expect[ sizeof(xe.XE.SorG.expect)-1 ] = 0;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SorG.actual[ sizeof(xe.XE.SorG.actual)-1 ] = 0;
174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   xe.XE.SorG.delta[ sizeof(xe.XE.SorG.delta)-1 ] = 0;
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(maybe_record_error)( tid, XE_SorG, 0, NULL, &xe );
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid h_record_heap_error( Addr a, SizeT size, Seg* vseg, Bool is_write )
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError xe;
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(size > 0);
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(&xe, 0, sizeof(xe));
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.tag = XE_Heap;
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.Heap.addr = a;
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.Heap.sszB = is_write ? -size : size;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.Heap.vseg = vseg;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Heap,
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid h_record_arith_error( Seg* seg1, Seg* seg2, HChar* opname )
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError xe;
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(&xe, 0, sizeof(xe));
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.tag = XE_Arith;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.Arith.seg1   = seg1;
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.Arith.seg2   = seg2;
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.Arith.opname = opname;
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Arith,
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid h_record_sysparam_error( ThreadId tid, CorePart part, Char* s,
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Addr lo, Addr hi, Seg* seglo, Seg* seghi )
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError xe;
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(&xe, 0, sizeof(xe));
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.tag = XE_SysParam;
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SysParam.part = part;
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SysParam.lo = lo;
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SysParam.hi = hi;
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SysParam.seglo = seglo;
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe.XE.SysParam.seghi = seghi;
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(maybe_record_error)( tid, XE_SysParam, /*a*/(Addr)0, /*str*/s,
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            /*extra*/(void*)&xe);
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool pc_eq_Error ( VgRes res, Error* e1, Error* e2 )
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError *xe1, *xe2;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //tl_assert(VG_(get_error_string)(e1) == NULL);
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //tl_assert(VG_(get_error_string)(e2) == NULL);
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe1 = (XError*)VG_(get_error_extra)(e1);
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xe2 = (XError*)VG_(get_error_extra)(e2);
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(xe1);
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(xe2);
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (xe1->tag != xe2->tag)
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (xe1->tag) {
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_SorG:
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return //xe1->XE.SorG.addr == xe2->XE.SorG.addr
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                //&&
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                xe1->XE.SorG.sszB == xe2->XE.SorG.sszB
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && 0 == VG_(strncmp)( &xe1->XE.SorG.expect[0],
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      &xe2->XE.SorG.expect[0],
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      sizeof(xe1->XE.SorG.expect) )
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                && 0 == VG_(strncmp)( &xe1->XE.SorG.actual[0],
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      &xe2->XE.SorG.actual[0],
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      sizeof(xe1->XE.SorG.actual) );
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_Heap:
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_Arith:
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_SysParam:
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("eq_Error: unrecognised error kind");
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//////////////////////////////////////////////////////////////
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                          //
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Error management -- printing                             //
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                          //
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//////////////////////////////////////////////////////////////
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the "this error is due to be printed shortly; so have a
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   look at it any print any preamble you want" function.  Which, in
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ptrcheck, we don't use.  Hence a no-op.
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pc_before_pp_Error ( Error* err ) {
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a printf-style operation on either the XML or normal output
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   channel, depending on the setting of VG_(clo_xml).
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void emit_WRK ( HChar* format, va_list vargs )
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml)) {
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(vprintf_xml)(format, vargs);
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(vmessage)(Vg_UserMsg, format, vargs);
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void emit ( HChar* format, ... )
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_list vargs;
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_start(vargs, format);
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   emit_WRK(format, vargs);
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_end(vargs);
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void emiN ( HChar* format, ... ) /* With NO FORMAT CHECK */
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_list vargs;
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_start(vargs, format);
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   emit_WRK(format, vargs);
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   va_end(vargs);
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Char* readwrite(SSizeT sszB)
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ( sszB < 0 ? "write" : "read" );
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Word Word__abs ( Word w ) {
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return w < 0 ? -w : w;
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pc_pp_Error ( Error* err )
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError *xe = (XError*)VG_(get_error_extra)(err);
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(xe);
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (xml)
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      emit( "  <kind>%s</kind>\n", pc_get_error_name(err));
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (VG_(get_error_kind)(err)) {
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //----------------------------------------------------------
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case XE_SorG:
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xml) {
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit( "  <what>Invalid %s of size %ld</what>\n",
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               xe->XE.SorG.sszB < 0 ? "write" : "read",
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Word__abs(xe->XE.SorG.sszB) );
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit( "  <auxwhat>Address %#lx expected vs actual:</auxwhat>\n",
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               xe->XE.SorG.addr );
329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         emiN( "  <auxwhat>Expected: %pS</auxwhat>\n",
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               &xe->XE.SorG.expect[0] );
331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         emiN( "  <auxwhat>Actual:   %pS</auxwhat>\n",
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               &xe->XE.SorG.actual[0] );
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit( "Invalid %s of size %ld\n",
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               xe->XE.SorG.sszB < 0 ? "write" : "read",
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Word__abs(xe->XE.SorG.sszB) );
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit( " Address %#lx expected vs actual:\n", xe->XE.SorG.addr );
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit( " Expected: %s\n", &xe->XE.SorG.expect[0] );
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit( " Actual:   %s\n", &xe->XE.SorG.actual[0] );
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (xe->XE.SorG.delta[0] != 0)
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            emit(" Actual:   is %s Expected\n", &xe->XE.SorG.delta[0]);
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //----------------------------------------------------------
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case XE_Heap: {
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char *place, *legit, *how_invalid;
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr a    = xe->XE.Heap.addr;
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Seg* vseg = xe->XE.Heap.vseg;
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(is_known_segment(vseg) || NONPTR == vseg);
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (NONPTR == vseg) {
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Access via a non-pointer
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xml) {
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <what>Invalid %s of size %ld</what>\n",
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  readwrite(xe->XE.Heap.sszB),
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Word__abs(xe->XE.Heap.sszB) );
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <auxwhat>Address %#lx is not derived from "
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "any known block</auxwhat>\n", a );
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "Invalid %s of size %ld\n",
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  readwrite(xe->XE.Heap.sszB),
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Word__abs(xe->XE.Heap.sszB) );
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " Address %#lx is not derived from "
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "any known block\n", a );
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Access via a pointer, but outside its range.
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int cmp;
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord miss_size;
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Seg__cmp(vseg, a, &cmp, &miss_size);
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if      (cmp  < 0) place = "before";
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (cmp == 0) place = "inside";
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else               place = "after";
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         how_invalid = ( ( Seg__is_freed(vseg) && 0 != cmp )
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ? "Doubly-invalid" : "Invalid" );
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         legit = ( Seg__is_freed(vseg) ? "once-" : "" );
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xml) {
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <what>%s %s of size %ld</what>\n",
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  how_invalid,
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  readwrite(xe->XE.Heap.sszB),
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Word__abs(xe->XE.Heap.sszB) );
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <auxwhat>Address %#lx is %lu bytes %s "
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "the accessing pointer's</auxwhat>\n",
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  a, miss_size, place );
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <auxwhat>%slegitimate range, "
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "a block of size %lu %s</auxwhat>\n",
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  legit, Seg__size(vseg),
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)(Seg__where(vseg));
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "%s %s of size %ld\n",
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  how_invalid,
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  readwrite(xe->XE.Heap.sszB),
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Word__abs(xe->XE.Heap.sszB) );
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " Address %#lx is %lu bytes %s the accessing pointer's\n",
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  a, miss_size, place );
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " %slegitimate range, a block of size %lu %s\n",
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  legit, Seg__size(vseg),
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)(Seg__where(vseg));
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If we have a better description of the address, show it.
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Note that in XML mode, it will already by nicely wrapped up
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         in tags, either <auxwhat> or <xauxwhat>, so we can just emit
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         it verbatim. */
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xml) {
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xe->XE.Heap.descr1)
436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            emiN( "  %pS\n",
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xe->XE.Heap.descr2)
439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            emiN( "  %pS\n",
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xe->XE.Heap.datasym[0] != 0)
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emiN( "  <auxwhat>Address 0x%llx is %llu bytes "
443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "inside data symbol \"%pS\"</auxwhat>\n",
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (ULong)xe->XE.Heap.addr,
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (ULong)xe->XE.Heap.datasymoff,
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  xe->XE.Heap.datasym );
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xe->XE.Heap.descr1)
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " %s\n",
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xe->XE.Heap.descr2)
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " %s\n",
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xe->XE.Heap.datasym[0] != 0)
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " Address 0x%llx is %llu bytes "
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "inside data symbol \"%s\"\n",
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (ULong)xe->XE.Heap.addr,
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (ULong)xe->XE.Heap.datasymoff,
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  xe->XE.Heap.datasym );
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //----------------------------------------------------------
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case XE_Arith: {
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Seg*   seg1   = xe->XE.Arith.seg1;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Seg*   seg2   = xe->XE.Arith.seg2;
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char*  which;
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(BOTTOM != seg1);
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xml) {
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit( "  <what>Invalid arguments to %s</what>\n",
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               xe->XE.Arith.opname );
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (seg1 != seg2) {
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (NONPTR == seg1) {
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( "  <auxwhat>First arg not a pointer</auxwhat>\n" );
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (UNKNOWN == seg1) {
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( "  <auxwhat>First arg may be a pointer</auxwhat>\n" );
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( "  <auxwhat>First arg derived from address %#lx of "
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "%lu-byte block alloc'd</auxwhat>\n",
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Seg__addr(seg1), Seg__size(seg1) );
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(pp_ExeContext)(Seg__where(seg1));
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            which = "Second arg";
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            which = "Both args";
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (NONPTR == seg2) {
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <auxwhat>%s not a pointer</auxwhat>\n", which );
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <auxwhat>%s derived from address %#lx of "
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "%lu-byte block alloc'd</auxwhat>\n",
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  which, Seg__addr(seg2), Seg__size(seg2) );
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)(Seg__where(seg2));
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         emit( "Invalid arguments to %s\n",
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               xe->XE.Arith.opname );
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(pp_ExeContext)( VG_(get_error_where)(err) );
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (seg1 != seg2) {
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (NONPTR == seg1) {
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( " First arg not a pointer\n" );
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else if (UNKNOWN == seg1) {
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( " First arg may be a pointer\n" );
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( " First arg derived from address %#lx of "
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "%lu-byte block alloc'd\n",
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Seg__addr(seg1), Seg__size(seg1) );
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(pp_ExeContext)(Seg__where(seg1));
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            which = "Second arg";
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            which = "Both args";
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (NONPTR == seg2) {
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " %s not a pointer\n", which );
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " %s derived from address %#lx of "
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "%lu-byte block alloc'd\n",
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  which, Seg__addr(seg2), Seg__size(seg2) );
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)(Seg__where(seg2));
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //----------------------------------------------------------
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case XE_SysParam: {
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr  lo    = xe->XE.SysParam.lo;
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr  hi    = xe->XE.SysParam.hi;
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Seg*  seglo = xe->XE.SysParam.seglo;
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Seg*  seghi = xe->XE.SysParam.seghi;
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* s     = VG_(get_error_string) (err);
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* what;
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(BOTTOM != seglo && BOTTOM != seghi);
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if      (Vg_CoreSysCall == xe->XE.SysParam.part)
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 what = "Syscall param ";
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else    VG_(tool_panic)("bad CorePart");
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (seglo == seghi) {
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // freed block
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(is_known_segment(seglo));
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(Seg__is_freed(seglo)); // XXX what if it's now recycled?
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xml) {
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <what>%s%s contains unaddressable byte(s)</what>\n",
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  what, s );
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <auxwhat>Address %#lx is %ld bytes inside a "
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "%ld-byte block free'd</auxwhat>\n",
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  lo, lo-Seg__addr(seglo), Seg__size(seglo) );
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)(Seg__where(seglo));
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " %s%s contains unaddressable byte(s)\n",
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  what, s );
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( " Address %#lx is %ld bytes inside a "
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "%ld-byte block free'd\n",
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  lo, lo-Seg__addr(seglo), Seg__size(seglo) );
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)(Seg__where(seglo));
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // mismatch
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (xml) {
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "  <what>%s%s is non-contiguous</what>\n",
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  what, s );
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (UNKNOWN == seglo) {
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( "  <auxwhat>First byte is "
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "not inside a known block</auxwhat>\n" );
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( "  <auxwhat>First byte (%#lx) is %ld bytes inside a "
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "%ld-byte block alloc'd</auxwhat>\n",
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     lo, lo-Seg__addr(seglo), Seg__size(seglo) );
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(pp_ExeContext)(Seg__where(seglo));
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (UNKNOWN == seghi) {
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( "  <auxwhat>Last byte is "
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "not inside a known block</auxwhat>\n" );
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( "  <auxwhat>Last byte (%#lx) is %ld bytes inside a "
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "%ld-byte block alloc'd</auxwhat>\n",
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hi, hi-Seg__addr(seghi), Seg__size(seghi) );
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(pp_ExeContext)(Seg__where(seghi));
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            emit( "%s%s is non-contiguous\n",
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  what, s );
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)( VG_(get_error_where)(err) );
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (UNKNOWN == seglo) {
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( " First byte is not inside a known block\n" );
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( " First byte (%#lx) is %ld bytes inside a "
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "%ld-byte block alloc'd\n",
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     lo, lo-Seg__addr(seglo), Seg__size(seglo) );
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(pp_ExeContext)(Seg__where(seglo));
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (UNKNOWN == seghi) {
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( " Last byte is not inside a known block\n" );
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               emit( " Last byte (%#lx) is %ld bytes inside a "
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "%ld-byte block alloc'd\n",
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     hi, hi-Seg__addr(seghi), Seg__size(seghi) );
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(pp_ExeContext)(Seg__where(seghi));
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("pp_Error: unrecognised error kind");
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt pc_update_Error_extra ( Error* err )
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError *xe = (XError*)VG_(get_error_extra)(err);
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(xe);
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (xe->tag) {
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_SorG:
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_Heap: {
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool have_descr;
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(sizeof(xe->XE.Heap.datasym) > 0);
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xe->XE.Heap.datasymoff = 0;
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xe->XE.Heap.datasym[0] = 0;
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(!xe->XE.Heap.descr1);
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(!xe->XE.Heap.descr2);
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xe->XE.Heap.descr1
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(free), sizeof(HChar) );
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xe->XE.Heap.descr2
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(free), sizeof(HChar) );
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(memset)(&xe->XE.Heap.datasym, 0, sizeof(xe->XE.Heap.datasym));
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xe->XE.Heap.datasymoff = 0;
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         have_descr
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = VG_(get_data_description)( xe->XE.Heap.descr1,
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         xe->XE.Heap.descr2,
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         xe->XE.Heap.addr );
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If there's nothing in descr1/2, free it.  Why is it safe to
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            to VG_(indexXA) at zero here?  Because
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(get_data_description) guarantees to zero terminate
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            descr1/2 regardless of the outcome of the call.  So there's
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            always at least one element in each XA after the call.
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr1, 0 ))
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || !have_descr) {
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(deleteXA)( xe->XE.Heap.descr1 );
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            xe->XE.Heap.descr1 = NULL;
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr2, 0 ))
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || !have_descr) {
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(deleteXA)( xe->XE.Heap.descr2 );
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            xe->XE.Heap.descr2 = NULL;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If Dwarf3 info produced nothing useful, see at least if
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            we can fish something useful out of the ELF symbol info. */
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!have_descr) {
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (VG_(get_datasym_and_offset)(
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   xe->XE.Heap.addr, &xe->XE.Heap.datasym[0],
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   sizeof(xe->XE.Heap.datasym)-1,
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   &xe->XE.Heap.datasymoff )
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ) {
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(xe->XE.Heap.datasym[sizeof(xe->XE.Heap.datasym)-1]
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         == 0);
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_Arith:
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_SysParam:
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("update_extra");
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sizeof(XError);
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool pc_is_recognised_suppression ( Char* name, Supp *su )
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SuppKind skind;
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if      (VG_STREQ(name, "SorG"))     skind = XS_SorG;
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (VG_STREQ(name, "Heap"))     skind = XS_Heap;
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (VG_STREQ(name, "Arith"))    skind = XS_Arith;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (VG_STREQ(name, "SysParam")) skind = XS_SysParam;
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(set_supp_kind)(su, skind);
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool pc_read_extra_suppression_info ( Int fd, Char** bufpp,
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      SizeT* nBufp, Supp* su )
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool eof;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(get_supp_kind)(su) == XS_SysParam) {
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eof = VG_(get_line) ( fd, bufpp, nBufp, NULL );
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (eof) return False;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(set_supp_string)(su, VG_(strdup)("pc.common.presi.1", *bufpp));
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool pc_error_matches_suppression (Error* err, Supp* su)
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ErrorKind ekind = VG_(get_error_kind)(err);
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (VG_(get_supp_kind)(su)) {
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XS_SorG:     return ekind == XE_SorG;
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XS_Heap:     return ekind == XE_Heap;
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XS_Arith:    return ekind == XE_Arith;
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XS_SysParam: return ekind == XE_SysParam;
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("Error:\n"
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "  unknown suppression type %d\n",
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     VG_(get_supp_kind)(su));
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)("unknown suppression type in "
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         "pc_error_matches_suppression");
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* pc_get_error_name ( Error* err )
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XError *xe = (XError*)VG_(get_error_extra)(err);
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(xe);
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (xe->tag) {
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_SorG:     return "SorG";
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_Heap:     return "Heap";
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_Arith:    return "Arith";
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case XE_SysParam: return "SysParam";
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:          VG_(tool_panic)("get_error_name: unexpected type");
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool pc_get_extra_suppression_info ( Error* err,
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     /*OUT*/Char* buf, Int nBuf )
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ErrorKind ekind = VG_(get_error_kind )(err);
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(buf);
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(nBuf >= 16); // stay sane
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (XE_SysParam == ekind) {
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* errstr = VG_(get_error_string)(err);
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(errstr);
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(snprintf)(buf, nBuf-1, "%s", errstr);
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                              pc_common.c ---*/
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
800