]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/exp-ptrcheck/pc_common.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / exp-ptrcheck / pc_common.c
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
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             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             Char     datasym[96];
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, Char* 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, Error* e1, 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 ( 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 ( 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 ( HChar* format, ... ) PRINTF_CHECK(1, 2);
280 static void emit ( 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 ( 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 Char* 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 ( 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    switch (VG_(get_error_kind)(err)) {
313
314    //----------------------------------------------------------
315    case XE_SorG:
316
317       if (xml) {
318
319          emit( "  <kind>SorG</kind>\n");
320          emit( "  <what>Invalid %s of size %ld</what>\n",
321                xe->XE.SorG.sszB < 0 ? "write" : "read",
322                Word__abs(xe->XE.SorG.sszB) );
323          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
324    
325          emit( "  <auxwhat>Address %#lx expected vs actual:</auxwhat>\n",
326                xe->XE.SorG.addr );
327          emiN( "  <auxwhat>Expected: %t</auxwhat>\n",
328                &xe->XE.SorG.expect[0] );
329          emiN( "  <auxwhat>Actual:   %t</auxwhat>\n", 
330                &xe->XE.SorG.actual[0] );
331
332       } else {
333
334          emit( "Invalid %s of size %ld\n", 
335                xe->XE.SorG.sszB < 0 ? "write" : "read",
336                Word__abs(xe->XE.SorG.sszB) );
337          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
338    
339          emit( " Address %#lx expected vs actual:\n", xe->XE.SorG.addr );
340          emit( " Expected: %s\n", &xe->XE.SorG.expect[0] );
341          emit( " Actual:   %s\n", &xe->XE.SorG.actual[0] );
342          if (xe->XE.SorG.delta[0] != 0)
343             emit(" Actual:   is %s Expected\n", &xe->XE.SorG.delta[0]);
344       }
345       break;
346
347    //----------------------------------------------------------
348    case XE_Heap: {
349       Char *place, *legit, *how_invalid;
350       Addr a    = xe->XE.Heap.addr;
351       Seg* vseg = xe->XE.Heap.vseg;
352
353       tl_assert(is_known_segment(vseg) || NONPTR == vseg);
354
355       if (NONPTR == vseg) {
356          // Access via a non-pointer
357
358          if (xml) {
359
360             emit( "  <kind>Heap</kind>\n");
361             emit( "  <what>Invalid %s of size %ld</what>\n",
362                   readwrite(xe->XE.Heap.sszB),
363                   Word__abs(xe->XE.Heap.sszB) );
364             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
365    
366             emit( "  <auxwhat>Address %#lx is not derived from "
367                   "any known block</auxwhat>\n", a );
368
369          } else {
370
371             emit( "Invalid %s of size %ld\n",
372                   readwrite(xe->XE.Heap.sszB),
373                   Word__abs(xe->XE.Heap.sszB) );
374             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
375    
376             emit( " Address %#lx is not derived from "
377                   "any known block\n", a );
378
379          }
380
381       } else {
382          // Access via a pointer, but outside its range.
383          Int cmp;
384          UWord miss_size;
385          Seg__cmp(vseg, a, &cmp, &miss_size);
386          if      (cmp  < 0) place = "before";
387          else if (cmp == 0) place = "inside";
388          else               place = "after";
389          how_invalid = ( ( Seg__is_freed(vseg) && 0 != cmp )
390                        ? "Doubly-invalid" : "Invalid" );
391          legit = ( Seg__is_freed(vseg) ? "once-" : "" );
392
393          if (xml) {
394
395             emit( "  <kind>Heap</kind>\n");
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( "  %t\n",
437                   (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
438          if (xe->XE.Heap.descr2)
439             emiN( "  %t\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 \"%t\"</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       Char*  which;
472
473       tl_assert(BOTTOM != seg1);
474       tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
475
476       if (xml) {
477
478          emit( "  <kind>Arith</kind>\n");
479          emit( "  <what>Invalid arguments to %s</what>\n",
480                xe->XE.Arith.opname );
481          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
482    
483          if (seg1 != seg2) {
484             if (NONPTR == seg1) {
485                emit( "  <auxwhat>First arg not a pointer</auxwhat>\n" );
486             } else if (UNKNOWN == seg1) {
487                emit( "  <auxwhat>First arg may be a pointer</auxwhat>\n" );
488             } else {
489                emit( "  <auxwhat>First arg derived from address %#lx of "
490                      "%lu-byte block alloc'd</auxwhat>\n",
491                      Seg__addr(seg1), Seg__size(seg1) );
492                VG_(pp_ExeContext)(Seg__where(seg1));
493             }
494             which = "Second arg";
495          } else {
496             which = "Both args";
497          }
498          if (NONPTR == seg2) {
499             emit( "  <auxwhat>%s not a pointer</auxwhat>\n", which );
500          } else {
501             emit( "  <auxwhat>%s derived from address %#lx of "
502                   "%lu-byte block alloc'd</auxwhat>\n",
503                   which, Seg__addr(seg2), Seg__size(seg2) );
504             VG_(pp_ExeContext)(Seg__where(seg2));
505          }
506
507       } else {
508
509          emit( "Invalid arguments to %s\n",
510                xe->XE.Arith.opname );
511          VG_(pp_ExeContext)( VG_(get_error_where)(err) );
512    
513          if (seg1 != seg2) {
514             if (NONPTR == seg1) {
515                emit( " First arg not a pointer\n" );
516             } else if (UNKNOWN == seg1) {
517                emit( " First arg may be a pointer\n" );
518             } else {
519                emit( " First arg derived from address %#lx of "
520                      "%lu-byte block alloc'd\n",
521                      Seg__addr(seg1), Seg__size(seg1) );
522                VG_(pp_ExeContext)(Seg__where(seg1));
523             }
524             which = "Second arg";
525          } else {
526             which = "Both args";
527          }
528          if (NONPTR == seg2) {
529             emit( " %s not a pointer\n", which );
530          } else {
531             emit( " %s derived from address %#lx of "
532                   "%lu-byte block alloc'd\n",
533                   which, Seg__addr(seg2), Seg__size(seg2) );
534             VG_(pp_ExeContext)(Seg__where(seg2));
535          }
536
537       }
538
539       break;
540    }
541
542    //----------------------------------------------------------
543    case XE_SysParam: {
544       Addr  lo    = xe->XE.SysParam.lo;
545       Addr  hi    = xe->XE.SysParam.hi;
546       Seg*  seglo = xe->XE.SysParam.seglo;
547       Seg*  seghi = xe->XE.SysParam.seghi;
548       Char* s     = VG_(get_error_string) (err);
549       Char* what;
550
551       tl_assert(BOTTOM != seglo && BOTTOM != seghi);
552
553       if      (Vg_CoreSysCall == xe->XE.SysParam.part) 
554                  what = "Syscall param ";
555       else    VG_(tool_panic)("bad CorePart");
556
557       if (seglo == seghi) {
558          // freed block
559          tl_assert(is_known_segment(seglo));
560          tl_assert(Seg__is_freed(seglo)); // XXX what if it's now recycled?
561
562          if (xml) {
563
564             emit( "  <kind>SysParam</kind>\n");
565             emit( "  <what>%s%s contains unaddressable byte(s)</what>\n",
566                   what, s );
567             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
568    
569             emit( "  <auxwhat>Address %#lx is %ld bytes inside a "
570                   "%ld-byte block free'd</auxwhat>\n",
571                   lo, lo-Seg__addr(seglo), Seg__size(seglo) );
572             VG_(pp_ExeContext)(Seg__where(seglo));
573
574          } else {
575
576             emit( " %s%s contains unaddressable byte(s)\n",
577                   what, s );
578             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
579    
580             emit( " Address %#lx is %ld bytes inside a "
581                   "%ld-byte block free'd\n",
582                   lo, lo-Seg__addr(seglo), Seg__size(seglo) );
583             VG_(pp_ExeContext)(Seg__where(seglo));
584
585          }
586
587       } else {
588          // mismatch
589
590          if (xml) {
591
592             emit( "  <kind>SysParam</kind>\n");
593             emit( "  <what>%s%s is non-contiguous</what>\n",
594                   what, s );
595             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
596    
597             if (UNKNOWN == seglo) {
598                emit( "  <auxwhat>First byte is "
599                         "not inside a known block</auxwhat>\n" );
600             } else {
601                emit( "  <auxwhat>First byte (%#lx) is %ld bytes inside a "
602                      "%ld-byte block alloc'd</auxwhat>\n",
603                      lo, lo-Seg__addr(seglo), Seg__size(seglo) );
604                VG_(pp_ExeContext)(Seg__where(seglo));
605             }
606    
607             if (UNKNOWN == seghi) {
608                emit( "  <auxwhat>Last byte is "
609                         "not inside a known block</auxwhat>\n" );
610             } else {
611                emit( "  <auxwhat>Last byte (%#lx) is %ld bytes inside a "
612                      "%ld-byte block alloc'd</auxwhat>\n",
613                      hi, hi-Seg__addr(seghi), Seg__size(seghi) );
614                VG_(pp_ExeContext)(Seg__where(seghi));
615             }
616
617          } else {
618
619             emit( "%s%s is non-contiguous\n",
620                   what, s );
621             VG_(pp_ExeContext)( VG_(get_error_where)(err) );
622    
623             if (UNKNOWN == seglo) {
624                emit( " First byte is not inside a known block\n" );
625             } else {
626                emit( " First byte (%#lx) is %ld bytes inside a "
627                      "%ld-byte block alloc'd\n",
628                      lo, lo-Seg__addr(seglo), Seg__size(seglo) );
629                VG_(pp_ExeContext)(Seg__where(seglo));
630             }
631    
632             if (UNKNOWN == seghi) {
633                emit( " Last byte is not inside a known block\n" );
634             } else {
635                emit( " Last byte (%#lx) is %ld bytes inside a "
636                      "%ld-byte block alloc'd\n",
637                      hi, hi-Seg__addr(seghi), Seg__size(seghi) );
638                VG_(pp_ExeContext)(Seg__where(seghi));
639             }
640
641          }
642
643       }
644       break;
645    }
646
647    default:
648       VG_(tool_panic)("pp_Error: unrecognised error kind");
649    }
650 }
651
652
653 UInt pc_update_Error_extra ( Error* err )
654 {
655    XError *xe = (XError*)VG_(get_error_extra)(err);
656    tl_assert(xe);
657    switch (xe->tag) {
658       case XE_SorG:
659          break;
660       case XE_Heap: {
661          Bool have_descr;
662
663          tl_assert(sizeof(xe->XE.Heap.datasym) > 0);
664          xe->XE.Heap.datasymoff = 0;
665          xe->XE.Heap.datasym[0] = 0;
666
667          tl_assert(!xe->XE.Heap.descr1);
668          tl_assert(!xe->XE.Heap.descr2);
669
670          xe->XE.Heap.descr1
671             = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
672                           VG_(free), sizeof(HChar) );
673          xe->XE.Heap.descr2
674             = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
675                           VG_(free), sizeof(HChar) );
676
677          VG_(memset)(&xe->XE.Heap.datasym, 0, sizeof(xe->XE.Heap.datasym));
678          xe->XE.Heap.datasymoff = 0;
679
680          have_descr
681             = VG_(get_data_description)( xe->XE.Heap.descr1,
682                                          xe->XE.Heap.descr2,
683                                          xe->XE.Heap.addr );
684
685          /* If there's nothing in descr1/2, free it.  Why is it safe to
686             to VG_(indexXA) at zero here?  Because
687             VG_(get_data_description) guarantees to zero terminate
688             descr1/2 regardless of the outcome of the call.  So there's
689             always at least one element in each XA after the call.
690          */
691          if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr1, 0 ))
692              || !have_descr) {
693             VG_(deleteXA)( xe->XE.Heap.descr1 );
694             xe->XE.Heap.descr1 = NULL;
695          }
696          if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr2, 0 ))
697              || !have_descr) {
698             VG_(deleteXA)( xe->XE.Heap.descr2 );
699             xe->XE.Heap.descr2 = NULL;
700          }
701
702          /* If Dwarf3 info produced nothing useful, see at least if
703             we can fish something useful out of the ELF symbol info. */
704          if (!have_descr) {
705             if (VG_(get_datasym_and_offset)(
706                    xe->XE.Heap.addr, &xe->XE.Heap.datasym[0],
707                    sizeof(xe->XE.Heap.datasym)-1,
708                    &xe->XE.Heap.datasymoff )
709                ) {
710                tl_assert(xe->XE.Heap.datasym[sizeof(xe->XE.Heap.datasym)-1] 
711                          == 0);
712             }
713          }
714          break;
715       }
716       case XE_Arith:
717          break;
718       case XE_SysParam:
719          break;
720       default:
721          VG_(tool_panic)("update_extra");
722    }
723    return sizeof(XError);
724 }
725
726 Bool pc_is_recognised_suppression ( Char* name, Supp *su )
727 {
728    SuppKind skind;
729
730    if      (VG_STREQ(name, "SorG"))     skind = XS_SorG;
731    else if (VG_STREQ(name, "Heap"))     skind = XS_Heap;
732    else if (VG_STREQ(name, "Arith"))    skind = XS_Arith;
733    else if (VG_STREQ(name, "SysParam")) skind = XS_SysParam;
734    else
735       return False;
736
737    VG_(set_supp_kind)(su, skind);
738    return True;
739 }
740
741 Bool pc_read_extra_suppression_info ( Int fd, Char** bufpp, 
742                                       SizeT* nBufp, Supp* su )
743 {
744    Bool eof;
745    if (VG_(get_supp_kind)(su) == XS_SysParam) {
746       eof = VG_(get_line) ( fd, bufpp, nBufp, NULL );
747       if (eof) return False;
748       VG_(set_supp_string)(su, VG_(strdup)("pc.common.presi.1", *bufpp));
749    }
750    return True;
751 }
752
753 Bool pc_error_matches_suppression (Error* err, Supp* su)
754 {
755    ErrorKind ekind = VG_(get_error_kind)(err);
756    switch (VG_(get_supp_kind)(su)) {
757       case XS_SorG:     return ekind == XE_SorG;
758       case XS_Heap:     return ekind == XE_Heap;
759       case XS_Arith:    return ekind == XE_Arith;
760       case XS_SysParam: return ekind == XE_SysParam;
761       default:
762          VG_(printf)("Error:\n"
763                      "  unknown suppression type %d\n",
764                      VG_(get_supp_kind)(su));
765          VG_(tool_panic)("unknown suppression type in "
766                          "pc_error_matches_suppression");
767    }
768 }
769
770 Char* pc_get_error_name ( Error* err )
771 {
772    XError *xe = (XError*)VG_(get_error_extra)(err);
773    tl_assert(xe);
774    switch (xe->tag) {
775       case XE_SorG:     return "SorG";
776       case XE_Heap:     return "Heap";
777       case XE_Arith:    return "Arith";
778       case XE_SysParam: return "SysParam";
779       default:          VG_(tool_panic)("get_error_name: unexpected type");
780    }
781 }
782
783 Bool pc_get_extra_suppression_info ( Error* err,
784                                      /*OUT*/Char* buf, Int nBuf )
785 {
786    ErrorKind ekind = VG_(get_error_kind )(err);
787    tl_assert(buf);
788    tl_assert(nBuf >= 16); // stay sane
789    if (XE_SysParam == ekind) {
790       Char* errstr = VG_(get_error_string)(err);
791       tl_assert(errstr);
792       VG_(snprintf)(buf, nBuf-1, "%s", errstr);
793       return True;
794    } else {
795       return False;
796    }
797 }
798
799
800 /*--------------------------------------------------------------------*/
801 /*--- end                                              pc_common.c ---*/
802 /*--------------------------------------------------------------------*/