• Home
  • 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-2010 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(Char * arg)66 Bool pc_process_cmd_line_options(Char* 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          } SorG;
130          struct {
131             Addr     addr;
132             SSizeT   sszB;  /* -ve is write, +ve is read */
133             Seg*     vseg;
134             XArray*  descr1; /* XArray* of HChar */
135             XArray*  descr2; /* XArray* of HChar */
136             Char     datasym[96];
137             PtrdiffT datasymoff;
138          } Heap;
139          struct {
140             Seg* seg1;
141             Seg* seg2;
142             const HChar* opname; // user-understandable text name
143          } Arith;
144          struct {
145             CorePart part;
146             Addr lo;
147             Addr hi;
148             Seg* seglo;
149             Seg* seghi;
150          } SysParam;
151       } XE;
152    }
153    XError;
154 
155 
sg_record_error_SorG(ThreadId tid,Addr addr,SSizeT sszB,HChar * expect,HChar * actual)156 void sg_record_error_SorG ( ThreadId tid,
157                             Addr addr, SSizeT sszB,
158                             HChar* expect, HChar* actual )
159 {
160    XError xe;
161    VG_(memset)(&xe, 0, sizeof(xe));
162    xe.tag = XE_SorG;
163    xe.XE.SorG.addr = addr;
164    xe.XE.SorG.sszB = sszB;
165    VG_(strncpy)( &xe.XE.SorG.expect[0],
166                  expect, sizeof(xe.XE.SorG.expect) );
167    VG_(strncpy)( &xe.XE.SorG.actual[0],
168                  actual, sizeof(xe.XE.SorG.actual) );
169    xe.XE.SorG.expect[ sizeof(xe.XE.SorG.expect)-1 ] = 0;
170    xe.XE.SorG.actual[ sizeof(xe.XE.SorG.actual)-1 ] = 0;
171    VG_(maybe_record_error)( tid, XE_SorG, 0, NULL, &xe );
172 }
173 
h_record_heap_error(Addr a,SizeT size,Seg * vseg,Bool is_write)174 void h_record_heap_error( Addr a, SizeT size, Seg* vseg, Bool is_write )
175 {
176    XError xe;
177    tl_assert(size > 0);
178    VG_(memset)(&xe, 0, sizeof(xe));
179    xe.tag = XE_Heap;
180    xe.XE.Heap.addr = a;
181    xe.XE.Heap.sszB = is_write ? -size : size;
182    xe.XE.Heap.vseg = vseg;
183    VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Heap,
184                             /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
185 }
186 
h_record_arith_error(Seg * seg1,Seg * seg2,HChar * opname)187 void h_record_arith_error( Seg* seg1, Seg* seg2, HChar* opname )
188 {
189    XError xe;
190    VG_(memset)(&xe, 0, sizeof(xe));
191    xe.tag = XE_Arith;
192    xe.XE.Arith.seg1   = seg1;
193    xe.XE.Arith.seg2   = seg2;
194    xe.XE.Arith.opname = opname;
195    VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Arith,
196                             /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
197 }
198 
h_record_sysparam_error(ThreadId tid,CorePart part,Char * s,Addr lo,Addr hi,Seg * seglo,Seg * seghi)199 void h_record_sysparam_error( ThreadId tid, CorePart part, Char* s,
200                               Addr lo, Addr hi, Seg* seglo, Seg* seghi )
201 {
202    XError xe;
203    VG_(memset)(&xe, 0, sizeof(xe));
204    xe.tag = XE_SysParam;
205    xe.XE.SysParam.part = part;
206    xe.XE.SysParam.lo = lo;
207    xe.XE.SysParam.hi = hi;
208    xe.XE.SysParam.seglo = seglo;
209    xe.XE.SysParam.seghi = seghi;
210    VG_(maybe_record_error)( tid, XE_SysParam, /*a*/(Addr)0, /*str*/s,
211                             /*extra*/(void*)&xe);
212 }
213 
214 
pc_eq_Error(VgRes res,Error * e1,Error * e2)215 Bool pc_eq_Error ( VgRes res, Error* e1, Error* e2 )
216 {
217    XError *xe1, *xe2;
218    tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
219    //tl_assert(VG_(get_error_string)(e1) == NULL);
220    //tl_assert(VG_(get_error_string)(e2) == NULL);
221 
222    xe1 = (XError*)VG_(get_error_extra)(e1);
223    xe2 = (XError*)VG_(get_error_extra)(e2);
224    tl_assert(xe1);
225    tl_assert(xe2);
226 
227    if (xe1->tag != xe2->tag)
228       return False;
229 
230    switch (xe1->tag) {
231       case XE_SorG:
232          return //xe1->XE.SorG.addr == xe2->XE.SorG.addr
233                 //&&
234                 xe1->XE.SorG.sszB == xe2->XE.SorG.sszB
235                 && 0 == VG_(strncmp)( &xe1->XE.SorG.expect[0],
236                                       &xe2->XE.SorG.expect[0],
237                                       sizeof(xe1->XE.SorG.expect) )
238                 && 0 == VG_(strncmp)( &xe1->XE.SorG.actual[0],
239                                       &xe2->XE.SorG.actual[0],
240                                       sizeof(xe1->XE.SorG.actual) );
241       case XE_Heap:
242       case XE_Arith:
243       case XE_SysParam:
244          return True;
245       default:
246          VG_(tool_panic)("eq_Error: unrecognised error kind");
247    }
248 }
249 
250 
251 //////////////////////////////////////////////////////////////
252 //                                                          //
253 // Error management -- printing                             //
254 //                                                          //
255 //////////////////////////////////////////////////////////////
256 
257 /* This is the "this error is due to be printed shortly; so have a
258    look at it any print any preamble you want" function.  Which, in
259    Ptrcheck, we don't use.  Hence a no-op.
260 */
pc_before_pp_Error(Error * err)261 void pc_before_pp_Error ( Error* err ) {
262 }
263 
264 /* Do a printf-style operation on either the XML or normal output
265    channel, depending on the setting of VG_(clo_xml).
266 */
emit_WRK(HChar * format,va_list vargs)267 static void emit_WRK ( HChar* format, va_list vargs )
268 {
269    if (VG_(clo_xml)) {
270       VG_(vprintf_xml)(format, vargs);
271    } else {
272       VG_(vmessage)(Vg_UserMsg, format, vargs);
273    }
274 }
275 static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
emit(HChar * format,...)276 static void emit ( HChar* format, ... )
277 {
278    va_list vargs;
279    va_start(vargs, format);
280    emit_WRK(format, vargs);
281    va_end(vargs);
282 }
emiN(HChar * format,...)283 static void emiN ( HChar* format, ... ) /* With NO FORMAT CHECK */
284 {
285    va_list vargs;
286    va_start(vargs, format);
287    emit_WRK(format, vargs);
288    va_end(vargs);
289 }
290 
291 
readwrite(SSizeT sszB)292 static Char* readwrite(SSizeT sszB)
293 {
294    return ( sszB < 0 ? "write" : "read" );
295 }
296 
Word__abs(Word w)297 static Word Word__abs ( Word w ) {
298    return w < 0 ? -w : w;
299 }
300 
pc_pp_Error(Error * err)301 void pc_pp_Error ( Error* err )
302 {
303    const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
304 
305    XError *xe = (XError*)VG_(get_error_extra)(err);
306    tl_assert(xe);
307 
308    switch (VG_(get_error_kind)(err)) {
309 
310    //----------------------------------------------------------
311    case XE_SorG:
312 
313       if (xml) {
314 
315          emit( "  <kind>SorG</kind>\n");
316          emit( "  <what>Invalid %s of size %ld</what>\n",
317                xe->XE.SorG.sszB < 0 ? "write" : "read",
318                Word__abs(xe->XE.SorG.sszB) );
319          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
320 
321          emit( "  <auxwhat>Address %#lx expected vs actual:</auxwhat>\n",
322                xe->XE.SorG.addr );
323          emiN( "  <auxwhat>Expected: %t</auxwhat>\n",
324                &xe->XE.SorG.expect[0] );
325          emiN( "  <auxwhat>Actual:   %t</auxwhat>\n",
326                &xe->XE.SorG.actual[0] );
327 
328       } else {
329 
330          emit( "Invalid %s of size %ld\n",
331                xe->XE.SorG.sszB < 0 ? "write" : "read",
332                Word__abs(xe->XE.SorG.sszB) );
333          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
334 
335          emit( " Address %#lx expected vs actual:\n", xe->XE.SorG.addr );
336          emit( " Expected: %s\n", &xe->XE.SorG.expect[0] );
337          emit( " Actual:   %s\n", &xe->XE.SorG.actual[0] );
338 
339       }
340       break;
341 
342    //----------------------------------------------------------
343    case XE_Heap: {
344       Char *place, *legit, *how_invalid;
345       Addr a    = xe->XE.Heap.addr;
346       Seg* vseg = xe->XE.Heap.vseg;
347 
348       tl_assert(is_known_segment(vseg) || NONPTR == vseg);
349 
350       if (NONPTR == vseg) {
351          // Access via a non-pointer
352 
353          if (xml) {
354 
355             emit( "  <kind>Heap</kind>\n");
356             emit( "  <what>Invalid %s of size %ld</what>\n",
357                   readwrite(xe->XE.Heap.sszB),
358                   Word__abs(xe->XE.Heap.sszB) );
359             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
360 
361             emit( "  <auxwhat>Address %#lx is not derived from "
362                   "any known block</auxwhat>\n", a );
363 
364          } else {
365 
366             emit( "Invalid %s of size %ld\n",
367                   readwrite(xe->XE.Heap.sszB),
368                   Word__abs(xe->XE.Heap.sszB) );
369             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
370 
371             emit( " Address %#lx is not derived from "
372                   "any known block\n", a );
373 
374          }
375 
376       } else {
377          // Access via a pointer, but outside its range.
378          Int cmp;
379          UWord miss_size;
380          Seg__cmp(vseg, a, &cmp, &miss_size);
381          if      (cmp  < 0) place = "before";
382          else if (cmp == 0) place = "inside";
383          else               place = "after";
384          how_invalid = ( ( Seg__is_freed(vseg) && 0 != cmp )
385                        ? "Doubly-invalid" : "Invalid" );
386          legit = ( Seg__is_freed(vseg) ? "once-" : "" );
387 
388          if (xml) {
389 
390             emit( "  <kind>Heap</kind>\n");
391             emit( "  <what>%s %s of size %ld</what>\n",
392                   how_invalid,
393                   readwrite(xe->XE.Heap.sszB),
394                   Word__abs(xe->XE.Heap.sszB) );
395             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
396 
397             emit( "  <auxwhat>Address %#lx is %lu bytes %s "
398                      "the accessing pointer's</auxwhat>\n",
399                   a, miss_size, place );
400             emit( "  <auxwhat>%slegitimate range, "
401                      "a block of size %lu %s</auxwhat>\n",
402                   legit, Seg__size(vseg),
403                   Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
404             VG_(pp_ExeContext)(Seg__where(vseg));
405 
406          } else {
407 
408             emit( "%s %s of size %ld\n",
409                   how_invalid,
410                   readwrite(xe->XE.Heap.sszB),
411                   Word__abs(xe->XE.Heap.sszB) );
412             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
413 
414             emit( " Address %#lx is %lu bytes %s the accessing pointer's\n",
415                   a, miss_size, place );
416             emit( " %slegitimate range, a block of size %lu %s\n",
417                   legit, Seg__size(vseg),
418                   Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
419             VG_(pp_ExeContext)(Seg__where(vseg));
420 
421          }
422       }
423 
424       /* If we have a better description of the address, show it.
425          Note that in XML mode, it will already by nicely wrapped up
426          in tags, either <auxwhat> or <xauxwhat>, so we can just emit
427          it verbatim. */
428       if (xml) {
429 
430          if (xe->XE.Heap.descr1)
431             emiN( "  %t\n",
432                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
433          if (xe->XE.Heap.descr2)
434             emiN( "  %t\n",
435                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
436          if (xe->XE.Heap.datasym[0] != 0)
437             emiN( "  <auxwhat>Address 0x%llx is %llu bytes "
438                   "inside data symbol \"%t\"</auxwhat>\n",
439                   (ULong)xe->XE.Heap.addr,
440                   (ULong)xe->XE.Heap.datasymoff,
441                   xe->XE.Heap.datasym );
442 
443       } else {
444 
445          if (xe->XE.Heap.descr1)
446             emit( " %s\n",
447                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
448          if (xe->XE.Heap.descr2)
449             emit( " %s\n",
450                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
451          if (xe->XE.Heap.datasym[0] != 0)
452             emit( " Address 0x%llx is %llu bytes "
453                   "inside data symbol \"%s\"\n",
454                   (ULong)xe->XE.Heap.addr,
455                   (ULong)xe->XE.Heap.datasymoff,
456                   xe->XE.Heap.datasym );
457 
458       }
459       break;
460    }
461 
462    //----------------------------------------------------------
463    case XE_Arith: {
464       Seg*   seg1   = xe->XE.Arith.seg1;
465       Seg*   seg2   = xe->XE.Arith.seg2;
466       Char*  which;
467 
468       tl_assert(BOTTOM != seg1);
469       tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
470 
471       if (xml) {
472 
473          emit( "  <kind>Arith</kind>\n");
474          emit( "  <what>Invalid arguments to %s</what>\n",
475                xe->XE.Arith.opname );
476          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
477 
478          if (seg1 != seg2) {
479             if (NONPTR == seg1) {
480                emit( "  <auxwhat>First arg not a pointer</auxwhat>\n" );
481             } else if (UNKNOWN == seg1) {
482                emit( "  <auxwhat>First arg may be a pointer</auxwhat>\n" );
483             } else {
484                emit( "  <auxwhat>First arg derived from address %#lx of "
485                      "%lu-byte block alloc'd</auxwhat>\n",
486                      Seg__addr(seg1), Seg__size(seg1) );
487                VG_(pp_ExeContext)(Seg__where(seg1));
488             }
489             which = "Second arg";
490          } else {
491             which = "Both args";
492          }
493          if (NONPTR == seg2) {
494             emit( "  <auxwhat>%s not a pointer</auxwhat>\n", which );
495          } else {
496             emit( "  <auxwhat>%s derived from address %#lx of "
497                   "%lu-byte block alloc'd</auxwhat>\n",
498                   which, Seg__addr(seg2), Seg__size(seg2) );
499             VG_(pp_ExeContext)(Seg__where(seg2));
500          }
501 
502       } else {
503 
504          emit( "Invalid arguments to %s\n",
505                xe->XE.Arith.opname );
506          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
507 
508          if (seg1 != seg2) {
509             if (NONPTR == seg1) {
510                emit( " First arg not a pointer\n" );
511             } else if (UNKNOWN == seg1) {
512                emit( " First arg may be a pointer\n" );
513             } else {
514                emit( " First arg derived from address %#lx of "
515                      "%lu-byte block alloc'd\n",
516                      Seg__addr(seg1), Seg__size(seg1) );
517                VG_(pp_ExeContext)(Seg__where(seg1));
518             }
519             which = "Second arg";
520          } else {
521             which = "Both args";
522          }
523          if (NONPTR == seg2) {
524             emit( " %s not a pointer\n", which );
525          } else {
526             emit( " %s derived from address %#lx of "
527                   "%lu-byte block alloc'd\n",
528                   which, Seg__addr(seg2), Seg__size(seg2) );
529             VG_(pp_ExeContext)(Seg__where(seg2));
530          }
531 
532       }
533 
534       break;
535    }
536 
537    //----------------------------------------------------------
538    case XE_SysParam: {
539       Addr  lo    = xe->XE.SysParam.lo;
540       Addr  hi    = xe->XE.SysParam.hi;
541       Seg*  seglo = xe->XE.SysParam.seglo;
542       Seg*  seghi = xe->XE.SysParam.seghi;
543       Char* s     = VG_(get_error_string) (err);
544       Char* what;
545 
546       tl_assert(BOTTOM != seglo && BOTTOM != seghi);
547 
548       if      (Vg_CoreSysCall == xe->XE.SysParam.part)
549                  what = "Syscall param ";
550       else    VG_(tool_panic)("bad CorePart");
551 
552       if (seglo == seghi) {
553          // freed block
554          tl_assert(is_known_segment(seglo));
555          tl_assert(Seg__is_freed(seglo)); // XXX what if it's now recycled?
556 
557          if (xml) {
558 
559             emit( "  <kind>SysParam</kind>\n");
560             emit( "  <what>%s%s contains unaddressable byte(s)</what>\n",
561                   what, s );
562             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
563 
564             emit( "  <auxwhat>Address %#lx is %ld bytes inside a "
565                   "%ld-byte block free'd</auxwhat>\n",
566                   lo, lo-Seg__addr(seglo), Seg__size(seglo) );
567             VG_(pp_ExeContext)(Seg__where(seglo));
568 
569          } else {
570 
571             emit( " %s%s contains unaddressable byte(s)\n",
572                   what, s );
573             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
574 
575             emit( " Address %#lx is %ld bytes inside a "
576                   "%ld-byte block free'd\n",
577                   lo, lo-Seg__addr(seglo), Seg__size(seglo) );
578             VG_(pp_ExeContext)(Seg__where(seglo));
579 
580          }
581 
582       } else {
583          // mismatch
584 
585          if (xml) {
586 
587             emit( "  <kind>SysParam</kind>\n");
588             emit( "  <what>%s%s is non-contiguous</what>\n",
589                   what, s );
590             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
591 
592             if (UNKNOWN == seglo) {
593                emit( "  <auxwhat>First byte is "
594                         "not inside a known block</auxwhat>\n" );
595             } else {
596                emit( "  <auxwhat>First byte (%#lx) is %ld bytes inside a "
597                      "%ld-byte block alloc'd</auxwhat>\n",
598                      lo, lo-Seg__addr(seglo), Seg__size(seglo) );
599                VG_(pp_ExeContext)(Seg__where(seglo));
600             }
601 
602             if (UNKNOWN == seghi) {
603                emit( "  <auxwhat>Last byte is "
604                         "not inside a known block</auxwhat>\n" );
605             } else {
606                emit( "  <auxwhat>Last byte (%#lx) is %ld bytes inside a "
607                      "%ld-byte block alloc'd</auxwhat>\n",
608                      hi, hi-Seg__addr(seghi), Seg__size(seghi) );
609                VG_(pp_ExeContext)(Seg__where(seghi));
610             }
611 
612          } else {
613 
614             emit( "%s%s is non-contiguous\n",
615                   what, s );
616             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
617 
618             if (UNKNOWN == seglo) {
619                emit( " First byte is not inside a known block\n" );
620             } else {
621                emit( " First byte (%#lx) is %ld bytes inside a "
622                      "%ld-byte block alloc'd\n",
623                      lo, lo-Seg__addr(seglo), Seg__size(seglo) );
624                VG_(pp_ExeContext)(Seg__where(seglo));
625             }
626 
627             if (UNKNOWN == seghi) {
628                emit( " Last byte is not inside a known block\n" );
629             } else {
630                emit( " Last byte (%#lx) is %ld bytes inside a "
631                      "%ld-byte block alloc'd\n",
632                      hi, hi-Seg__addr(seghi), Seg__size(seghi) );
633                VG_(pp_ExeContext)(Seg__where(seghi));
634             }
635 
636          }
637 
638       }
639       break;
640    }
641 
642    default:
643       VG_(tool_panic)("pp_Error: unrecognised error kind");
644    }
645 }
646 
647 
pc_update_Error_extra(Error * err)648 UInt pc_update_Error_extra ( Error* err )
649 {
650    XError *xe = (XError*)VG_(get_error_extra)(err);
651    tl_assert(xe);
652    switch (xe->tag) {
653       case XE_SorG:
654          break;
655       case XE_Heap: {
656          Bool have_descr;
657 
658          tl_assert(sizeof(xe->XE.Heap.datasym) > 0);
659          xe->XE.Heap.datasymoff = 0;
660          xe->XE.Heap.datasym[0] = 0;
661 
662          tl_assert(!xe->XE.Heap.descr1);
663          tl_assert(!xe->XE.Heap.descr2);
664 
665          xe->XE.Heap.descr1
666             = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
667                           VG_(free), sizeof(HChar) );
668          xe->XE.Heap.descr2
669             = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
670                           VG_(free), sizeof(HChar) );
671 
672          VG_(memset)(&xe->XE.Heap.datasym, 0, sizeof(xe->XE.Heap.datasym));
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             if (VG_(get_datasym_and_offset)(
701                    xe->XE.Heap.addr, &xe->XE.Heap.datasym[0],
702                    sizeof(xe->XE.Heap.datasym)-1,
703                    &xe->XE.Heap.datasymoff )
704                ) {
705                tl_assert(xe->XE.Heap.datasym[sizeof(xe->XE.Heap.datasym)-1]
706                          == 0);
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(Char * name,Supp * su)721 Bool pc_is_recognised_suppression ( Char* 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,Char ** bufpp,SizeT * nBufp,Supp * su)736 Bool pc_read_extra_suppression_info ( Int fd, Char** bufpp,
737                                       SizeT* nBufp, Supp* su )
738 {
739    Bool eof;
740    if (VG_(get_supp_kind)(su) == XS_SysParam) {
741       eof = VG_(get_line) ( fd, bufpp, nBufp, NULL );
742       if (eof) return False;
743       VG_(set_supp_string)(su, VG_(strdup)("pc.common.presi.1", *bufpp));
744    }
745    return True;
746 }
747 
pc_error_matches_suppression(Error * err,Supp * su)748 Bool pc_error_matches_suppression (Error* err, Supp* su)
749 {
750    ErrorKind ekind = VG_(get_error_kind)(err);
751    switch (VG_(get_supp_kind)(su)) {
752       case XS_SorG:     return ekind == XE_SorG;
753       case XS_Heap:     return ekind == XE_Heap;
754       case XS_Arith:    return ekind == XE_Arith;
755       case XS_SysParam: return ekind == XE_SysParam;
756       default:
757          VG_(printf)("Error:\n"
758                      "  unknown suppression type %d\n",
759                      VG_(get_supp_kind)(su));
760          VG_(tool_panic)("unknown suppression type in "
761                          "pc_error_matches_suppression");
762    }
763 }
764 
pc_get_error_name(Error * err)765 Char* pc_get_error_name ( Error* err )
766 {
767    XError *xe = (XError*)VG_(get_error_extra)(err);
768    tl_assert(xe);
769    switch (xe->tag) {
770       case XE_SorG:     return "SorG";
771       case XE_Heap:     return "Heap";
772       case XE_Arith:    return "Arith";
773       case XE_SysParam: return "SysParam";
774       default:          VG_(tool_panic)("get_error_name: unexpected type");
775    }
776 }
777 
pc_get_extra_suppression_info(Error * err,Char * buf,Int nBuf)778 Bool pc_get_extra_suppression_info ( Error* err,
779                                      /*OUT*/Char* buf, Int nBuf )
780 {
781    ErrorKind ekind = VG_(get_error_kind )(err);
782    tl_assert(buf);
783    tl_assert(nBuf >= 16); // stay sane
784    if (XE_SysParam == ekind) {
785       Char* errstr = VG_(get_error_string)(err);
786       tl_assert(errstr);
787       VG_(snprintf)(buf, nBuf-1, "%s", errstr);
788       return True;
789    } else {
790       return False;
791    }
792 }
793 
794 
795 /*--------------------------------------------------------------------*/
796 /*--- end                                              pc_common.c ---*/
797 /*--------------------------------------------------------------------*/
798