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-2013 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 %ld bytes inside a "
568                   "%ld-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 %ld bytes inside a "
579                   "%ld-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 %ld bytes inside a "
599                      "%ld-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 %ld bytes inside a "
609                      "%ld-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 %ld bytes inside a "
624                      "%ld-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 %ld bytes inside a "
633                      "%ld-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