Home | History | Annotate | Download | only in exp-ptrcheck
      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 (at) 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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 */
    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 */
    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);
    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 }
    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 
    292 static Char* readwrite(SSizeT sszB)
    293 {
    294    return ( sszB < 0 ? "write" : "read" );
    295 }
    296 
    297 static Word Word__abs ( Word w ) {
    298    return w < 0 ? -w : w;
    299 }
    300 
    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 
    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 
    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 
    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 
    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 
    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 
    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