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