Home | History | Annotate | Download | only in exp-sgcheck
      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-2017 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(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 
     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             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 
    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 
    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 
    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 
    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 
    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 */
    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 */
    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);
    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 }
    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 
    296 static const HChar* readwrite(SSizeT sszB)
    297 {
    298    return ( sszB < 0 ? "write" : "read" );
    299 }
    300 
    301 static Word Word__abs ( Word w ) {
    302    return w < 0 ? -w : w;
    303 }
    304 
    305 void pc_pp_Error ( const Error* err )
    306 {
    307    const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
    308 
    309    XError *xe = (XError*)VG_(get_error_extra)(err);
    310    tl_assert(xe);
    311 
    312    if (xml)
    313       emit( "  <kind>%s</kind>\n", pc_get_error_name(err));
    314 
    315    switch (VG_(get_error_kind)(err)) {
    316 
    317    //----------------------------------------------------------
    318    case XE_SorG:
    319 
    320       if (xml) {
    321 
    322          emit( "  <what>Invalid %s of size %ld</what>\n",
    323                xe->XE.SorG.sszB < 0 ? "write" : "read",
    324                Word__abs(xe->XE.SorG.sszB) );
    325          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    326 
    327          emit( "  <auxwhat>Address %#lx expected vs actual:</auxwhat>\n",
    328                xe->XE.SorG.addr );
    329          emiN( "  <auxwhat>Expected: %pS</auxwhat>\n",
    330                &xe->XE.SorG.expect[0] );
    331          emiN( "  <auxwhat>Actual:   %pS</auxwhat>\n",
    332                &xe->XE.SorG.actual[0] );
    333 
    334       } else {
    335 
    336          emit( "Invalid %s of size %ld\n",
    337                xe->XE.SorG.sszB < 0 ? "write" : "read",
    338                Word__abs(xe->XE.SorG.sszB) );
    339          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    340 
    341          emit( " Address %#lx expected vs actual:\n", xe->XE.SorG.addr );
    342          emit( " Expected: %s\n", &xe->XE.SorG.expect[0] );
    343          emit( " Actual:   %s\n", &xe->XE.SorG.actual[0] );
    344          if (xe->XE.SorG.delta[0] != 0)
    345             emit(" Actual:   is %s Expected\n", &xe->XE.SorG.delta[0]);
    346       }
    347       break;
    348 
    349    //----------------------------------------------------------
    350    case XE_Heap: {
    351       const HChar *place, *legit, *how_invalid;
    352       Addr a    = xe->XE.Heap.addr;
    353       Seg* vseg = xe->XE.Heap.vseg;
    354 
    355       tl_assert(is_known_segment(vseg) || NONPTR == vseg);
    356 
    357       if (NONPTR == vseg) {
    358          // Access via a non-pointer
    359 
    360          if (xml) {
    361 
    362             emit( "  <what>Invalid %s of size %ld</what>\n",
    363                   readwrite(xe->XE.Heap.sszB),
    364                   Word__abs(xe->XE.Heap.sszB) );
    365             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    366 
    367             emit( "  <auxwhat>Address %#lx is not derived from "
    368                   "any known block</auxwhat>\n", a );
    369 
    370          } else {
    371 
    372             emit( "Invalid %s of size %ld\n",
    373                   readwrite(xe->XE.Heap.sszB),
    374                   Word__abs(xe->XE.Heap.sszB) );
    375             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    376 
    377             emit( " Address %#lx is not derived from "
    378                   "any known block\n", a );
    379 
    380          }
    381 
    382       } else {
    383          // Access via a pointer, but outside its range.
    384          Int cmp;
    385          UWord miss_size;
    386          Seg__cmp(vseg, a, &cmp, &miss_size);
    387          if      (cmp  < 0) place = "before";
    388          else if (cmp == 0) place = "inside";
    389          else               place = "after";
    390          how_invalid = ( ( Seg__is_freed(vseg) && 0 != cmp )
    391                        ? "Doubly-invalid" : "Invalid" );
    392          legit = ( Seg__is_freed(vseg) ? "once-" : "" );
    393 
    394          if (xml) {
    395 
    396             emit( "  <what>%s %s of size %ld</what>\n",
    397                   how_invalid,
    398                   readwrite(xe->XE.Heap.sszB),
    399                   Word__abs(xe->XE.Heap.sszB) );
    400             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    401 
    402             emit( "  <auxwhat>Address %#lx is %lu bytes %s "
    403                      "the accessing pointer's</auxwhat>\n",
    404                   a, miss_size, place );
    405             emit( "  <auxwhat>%slegitimate range, "
    406                      "a block of size %lu %s</auxwhat>\n",
    407                   legit, Seg__size(vseg),
    408                   Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
    409             VG_(pp_ExeContext)(Seg__where(vseg));
    410 
    411          } else {
    412 
    413             emit( "%s %s of size %ld\n",
    414                   how_invalid,
    415                   readwrite(xe->XE.Heap.sszB),
    416                   Word__abs(xe->XE.Heap.sszB) );
    417             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    418 
    419             emit( " Address %#lx is %lu bytes %s the accessing pointer's\n",
    420                   a, miss_size, place );
    421             emit( " %slegitimate range, a block of size %lu %s\n",
    422                   legit, Seg__size(vseg),
    423                   Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
    424             VG_(pp_ExeContext)(Seg__where(vseg));
    425 
    426          }
    427       }
    428 
    429       /* If we have a better description of the address, show it.
    430          Note that in XML mode, it will already by nicely wrapped up
    431          in tags, either <auxwhat> or <xauxwhat>, so we can just emit
    432          it verbatim. */
    433       if (xml) {
    434 
    435          if (xe->XE.Heap.descr1)
    436             emiN( "  %pS\n",
    437                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
    438          if (xe->XE.Heap.descr2)
    439             emiN( "  %pS\n",
    440                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
    441          if (xe->XE.Heap.datasym[0] != 0)
    442             emiN( "  <auxwhat>Address 0x%llx is %llu bytes "
    443                   "inside data symbol \"%pS\"</auxwhat>\n",
    444                   (ULong)xe->XE.Heap.addr,
    445                   (ULong)xe->XE.Heap.datasymoff,
    446                   xe->XE.Heap.datasym );
    447 
    448       } else {
    449 
    450          if (xe->XE.Heap.descr1)
    451             emit( " %s\n",
    452                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
    453          if (xe->XE.Heap.descr2)
    454             emit( " %s\n",
    455                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
    456          if (xe->XE.Heap.datasym[0] != 0)
    457             emit( " Address 0x%llx is %llu bytes "
    458                   "inside data symbol \"%s\"\n",
    459                   (ULong)xe->XE.Heap.addr,
    460                   (ULong)xe->XE.Heap.datasymoff,
    461                   xe->XE.Heap.datasym );
    462 
    463       }
    464       break;
    465    }
    466 
    467    //----------------------------------------------------------
    468    case XE_Arith: {
    469       Seg*   seg1   = xe->XE.Arith.seg1;
    470       Seg*   seg2   = xe->XE.Arith.seg2;
    471       const HChar*  which;
    472 
    473       tl_assert(BOTTOM != seg1);
    474       tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
    475 
    476       if (xml) {
    477 
    478          emit( "  <what>Invalid arguments to %s</what>\n",
    479                xe->XE.Arith.opname );
    480          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    481 
    482          if (seg1 != seg2) {
    483             if (NONPTR == seg1) {
    484                emit( "  <auxwhat>First arg not a pointer</auxwhat>\n" );
    485             } else if (UNKNOWN == seg1) {
    486                emit( "  <auxwhat>First arg may be a pointer</auxwhat>\n" );
    487             } else {
    488                emit( "  <auxwhat>First arg derived from address %#lx of "
    489                      "%lu-byte block alloc'd</auxwhat>\n",
    490                      Seg__addr(seg1), Seg__size(seg1) );
    491                VG_(pp_ExeContext)(Seg__where(seg1));
    492             }
    493             which = "Second arg";
    494          } else {
    495             which = "Both args";
    496          }
    497          if (NONPTR == seg2) {
    498             emit( "  <auxwhat>%s not a pointer</auxwhat>\n", which );
    499          } else {
    500             emit( "  <auxwhat>%s derived from address %#lx of "
    501                   "%lu-byte block alloc'd</auxwhat>\n",
    502                   which, Seg__addr(seg2), Seg__size(seg2) );
    503             VG_(pp_ExeContext)(Seg__where(seg2));
    504          }
    505 
    506       } else {
    507 
    508          emit( "Invalid arguments to %s\n",
    509                xe->XE.Arith.opname );
    510          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    511 
    512          if (seg1 != seg2) {
    513             if (NONPTR == seg1) {
    514                emit( " First arg not a pointer\n" );
    515             } else if (UNKNOWN == seg1) {
    516                emit( " First arg may be a pointer\n" );
    517             } else {
    518                emit( " First arg derived from address %#lx of "
    519                      "%lu-byte block alloc'd\n",
    520                      Seg__addr(seg1), Seg__size(seg1) );
    521                VG_(pp_ExeContext)(Seg__where(seg1));
    522             }
    523             which = "Second arg";
    524          } else {
    525             which = "Both args";
    526          }
    527          if (NONPTR == seg2) {
    528             emit( " %s not a pointer\n", which );
    529          } else {
    530             emit( " %s derived from address %#lx of "
    531                   "%lu-byte block alloc'd\n",
    532                   which, Seg__addr(seg2), Seg__size(seg2) );
    533             VG_(pp_ExeContext)(Seg__where(seg2));
    534          }
    535 
    536       }
    537 
    538       break;
    539    }
    540 
    541    //----------------------------------------------------------
    542    case XE_SysParam: {
    543       Addr  lo    = xe->XE.SysParam.lo;
    544       Addr  hi    = xe->XE.SysParam.hi;
    545       Seg*  seglo = xe->XE.SysParam.seglo;
    546       Seg*  seghi = xe->XE.SysParam.seghi;
    547       const HChar* s = VG_(get_error_string) (err);
    548       const HChar* what;
    549 
    550       tl_assert(BOTTOM != seglo && BOTTOM != seghi);
    551 
    552       if      (Vg_CoreSysCall == xe->XE.SysParam.part)
    553                  what = "Syscall param ";
    554       else    VG_(tool_panic)("bad CorePart");
    555 
    556       if (seglo == seghi) {
    557          // freed block
    558          tl_assert(is_known_segment(seglo));
    559          tl_assert(Seg__is_freed(seglo)); // XXX what if it's now recycled?
    560 
    561          if (xml) {
    562 
    563             emit( "  <what>%s%s contains unaddressable byte(s)</what>\n",
    564                   what, s );
    565             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    566 
    567             emit( "  <auxwhat>Address %#lx is %lu bytes inside a "
    568                   "%lu-byte block free'd</auxwhat>\n",
    569                   lo, lo-Seg__addr(seglo), Seg__size(seglo) );
    570             VG_(pp_ExeContext)(Seg__where(seglo));
    571 
    572          } else {
    573 
    574             emit( " %s%s contains unaddressable byte(s)\n",
    575                   what, s );
    576             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    577 
    578             emit( " Address %#lx is %lu bytes inside a "
    579                   "%lu-byte block free'd\n",
    580                   lo, lo-Seg__addr(seglo), Seg__size(seglo) );
    581             VG_(pp_ExeContext)(Seg__where(seglo));
    582 
    583          }
    584 
    585       } else {
    586          // mismatch
    587 
    588          if (xml) {
    589 
    590             emit( "  <what>%s%s is non-contiguous</what>\n",
    591                   what, s );
    592             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    593 
    594             if (UNKNOWN == seglo) {
    595                emit( "  <auxwhat>First byte is "
    596                         "not inside a known block</auxwhat>\n" );
    597             } else {
    598                emit( "  <auxwhat>First byte (%#lx) is %lu bytes inside a "
    599                      "%lu-byte block alloc'd</auxwhat>\n",
    600                      lo, lo-Seg__addr(seglo), Seg__size(seglo) );
    601                VG_(pp_ExeContext)(Seg__where(seglo));
    602             }
    603 
    604             if (UNKNOWN == seghi) {
    605                emit( "  <auxwhat>Last byte is "
    606                         "not inside a known block</auxwhat>\n" );
    607             } else {
    608                emit( "  <auxwhat>Last byte (%#lx) is %lu bytes inside a "
    609                      "%lu-byte block alloc'd</auxwhat>\n",
    610                      hi, hi-Seg__addr(seghi), Seg__size(seghi) );
    611                VG_(pp_ExeContext)(Seg__where(seghi));
    612             }
    613 
    614          } else {
    615 
    616             emit( "%s%s is non-contiguous\n",
    617                   what, s );
    618             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
    619 
    620             if (UNKNOWN == seglo) {
    621                emit( " First byte is not inside a known block\n" );
    622             } else {
    623                emit( " First byte (%#lx) is %lu bytes inside a "
    624                      "%lu-byte block alloc'd\n",
    625                      lo, lo-Seg__addr(seglo), Seg__size(seglo) );
    626                VG_(pp_ExeContext)(Seg__where(seglo));
    627             }
    628 
    629             if (UNKNOWN == seghi) {
    630                emit( " Last byte is not inside a known block\n" );
    631             } else {
    632                emit( " Last byte (%#lx) is %lu bytes inside a "
    633                      "%lu-byte block alloc'd\n",
    634                      hi, hi-Seg__addr(seghi), Seg__size(seghi) );
    635                VG_(pp_ExeContext)(Seg__where(seghi));
    636             }
    637 
    638          }
    639 
    640       }
    641       break;
    642    }
    643 
    644    default:
    645       VG_(tool_panic)("pp_Error: unrecognised error kind");
    646    }
    647 }
    648 
    649 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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