2 /*--------------------------------------------------------------------*/
3 /*--- Ptrcheck: a pointer-use checker. ---*/
4 /*--- Provides stuff shared between sg_ and h_ subtools. ---*/
5 /*--- pc_common.c ---*/
6 /*--------------------------------------------------------------------*/
9 This file is part of Ptrcheck, a Valgrind tool for checking pointer
12 Copyright (C) 2008-2017 OpenWorks Ltd
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.
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.
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
30 The GNU General Public License is contained in the file COPYING.
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.
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"
51 #include "pc_common.h" // self, & Seg
53 #include "h_main.h" // NONPTR, BOTTOM, UNKNOWN
56 //////////////////////////////////////////////////////////////
58 // Command line options //
60 //////////////////////////////////////////////////////////////
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 */
66 Bool
pc_process_cmd_line_options(const HChar
* arg
)
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
) {}
72 return VG_(replacement_malloc_process_cmd_line_option
)(arg
);
77 void pc_print_usage(void)
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"
85 void pc_print_debug_usage(void)
89 //" --lossage-check=no|yes gather stats for quality control [no]\n"
95 //////////////////////////////////////////////////////////////
97 // Error management -- storage //
99 //////////////////////////////////////////////////////////////
101 /* What kind of error it is. */
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
126 SSizeT sszB
; /* -ve is write, +ve is read */
129 HChar delta
[32]; // text showing relation to expected
133 SSizeT sszB
; /* -ve is write, +ve is read */
135 XArray
* descr1
; /* XArray* of HChar */
136 XArray
* descr2
; /* XArray* of HChar */
137 const HChar
* datasym
;
143 const HChar
* opname
; // user-understandable text name
157 void sg_record_error_SorG ( ThreadId tid
,
158 Addr addr
, SSizeT sszB
,
159 HChar
* expect
, HChar
* actual
, HChar
* delta
)
162 VG_(memset
)(&xe
, 0, sizeof(xe
));
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
);
178 void h_record_heap_error( Addr a
, SizeT size
, Seg
* vseg
, Bool is_write
)
182 VG_(memset
)(&xe
, 0, sizeof(xe
));
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
);
191 void h_record_arith_error( Seg
* seg1
, Seg
* seg2
, HChar
* opname
)
194 VG_(memset
)(&xe
, 0, sizeof(xe
));
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
);
203 void h_record_sysparam_error( ThreadId tid
, CorePart part
, const HChar
* s
,
204 Addr lo
, Addr hi
, Seg
* seglo
, Seg
* seghi
)
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
);
219 Bool
pc_eq_Error ( VgRes res
, const Error
* e1
, const Error
* e2
)
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);
226 xe1
= (XError
*)VG_(get_error_extra
)(e1
);
227 xe2
= (XError
*)VG_(get_error_extra
)(e2
);
231 if (xe1
->tag
!= xe2
->tag
)
236 return //xe1->XE.SorG.addr == xe2->XE.SorG.addr
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
) );
250 VG_(tool_panic
)("eq_Error: unrecognised error kind");
255 //////////////////////////////////////////////////////////////
257 // Error management -- printing //
259 //////////////////////////////////////////////////////////////
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.
265 void pc_before_pp_Error ( const Error
* err
) {
268 /* Do a printf-style operation on either the XML or normal output
269 channel, depending on the setting of VG_(clo_xml).
271 static void emit_WRK ( const HChar
* format
, va_list vargs
)
274 VG_(vprintf_xml
)(format
, vargs
);
276 VG_(vmessage
)(Vg_UserMsg
, format
, vargs
);
279 static void emit ( const HChar
* format
, ... ) PRINTF_CHECK(1, 2);
280 static void emit ( const HChar
* format
, ... )
283 va_start(vargs
, format
);
284 emit_WRK(format
, vargs
);
287 static void emiN ( const HChar
* format
, ... ) /* With NO FORMAT CHECK */
290 va_start(vargs
, format
);
291 emit_WRK(format
, vargs
);
296 static const HChar
* readwrite(SSizeT sszB
)
298 return ( sszB
< 0 ? "write" : "read" );
301 static Word
Word__abs ( Word w
) {
302 return w
< 0 ? -w
: w
;
305 void pc_pp_Error ( const Error
* err
)
307 const Bool xml
= VG_(clo_xml
); /* a shorthand, that's all */
309 XError
*xe
= (XError
*)VG_(get_error_extra
)(err
);
313 emit( " <kind>%s</kind>\n", pc_get_error_name(err
));
315 switch (VG_(get_error_kind
)(err
)) {
317 //----------------------------------------------------------
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
) );
327 emit( " <auxwhat>Address %#lx expected vs actual:</auxwhat>\n",
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] );
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
) );
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]);
349 //----------------------------------------------------------
351 const HChar
*place
, *legit
, *how_invalid
;
352 Addr a
= xe
->XE
.Heap
.addr
;
353 Seg
* vseg
= xe
->XE
.Heap
.vseg
;
355 tl_assert(is_known_segment(vseg
) || NONPTR
== vseg
);
357 if (NONPTR
== vseg
) {
358 // Access via a non-pointer
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
) );
367 emit( " <auxwhat>Address %#lx is not derived from "
368 "any known block</auxwhat>\n", a
);
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
) );
377 emit( " Address %#lx is not derived from "
378 "any known block\n", a
);
383 // Access via a pointer, but outside its range.
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-" : "" );
396 emit( " <what>%s %s of size %ld</what>\n",
398 readwrite(xe
->XE
.Heap
.sszB
),
399 Word__abs(xe
->XE
.Heap
.sszB
) );
400 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
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
));
413 emit( "%s %s of size %ld\n",
415 readwrite(xe
->XE
.Heap
.sszB
),
416 Word__abs(xe
->XE
.Heap
.sszB
) );
417 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
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
));
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
435 if (xe
->XE
.Heap
.descr1
)
437 (HChar
*)VG_(indexXA
)( xe
->XE
.Heap
.descr1
, 0 ) );
438 if (xe
->XE
.Heap
.descr2
)
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
);
450 if (xe
->XE
.Heap
.descr1
)
452 (HChar
*)VG_(indexXA
)( xe
->XE
.Heap
.descr1
, 0 ) );
453 if (xe
->XE
.Heap
.descr2
)
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
);
467 //----------------------------------------------------------
469 Seg
* seg1
= xe
->XE
.Arith
.seg1
;
470 Seg
* seg2
= xe
->XE
.Arith
.seg2
;
473 tl_assert(BOTTOM
!= seg1
);
474 tl_assert(BOTTOM
!= seg2
&& UNKNOWN
!= seg2
);
478 emit( " <what>Invalid arguments to %s</what>\n",
479 xe
->XE
.Arith
.opname
);
480 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
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" );
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
));
493 which
= "Second arg";
497 if (NONPTR
== seg2
) {
498 emit( " <auxwhat>%s not a pointer</auxwhat>\n", which
);
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
));
508 emit( "Invalid arguments to %s\n",
509 xe
->XE
.Arith
.opname
);
510 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
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" );
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
));
523 which
= "Second arg";
527 if (NONPTR
== seg2
) {
528 emit( " %s not a pointer\n", which
);
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
));
541 //----------------------------------------------------------
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
);
550 tl_assert(BOTTOM
!= seglo
&& BOTTOM
!= seghi
);
552 if (Vg_CoreSysCall
== xe
->XE
.SysParam
.part
)
553 what
= "Syscall param ";
554 else VG_(tool_panic
)("bad CorePart");
556 if (seglo
== seghi
) {
558 tl_assert(is_known_segment(seglo
));
559 tl_assert(Seg__is_freed(seglo
)); // XXX what if it's now recycled?
563 emit( " <what>%s%s contains unaddressable byte(s)</what>\n",
565 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
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
));
574 emit( " %s%s contains unaddressable byte(s)\n",
576 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
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
));
590 emit( " <what>%s%s is non-contiguous</what>\n",
592 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
594 if (UNKNOWN
== seglo
) {
595 emit( " <auxwhat>First byte is "
596 "not inside a known block</auxwhat>\n" );
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
));
604 if (UNKNOWN
== seghi
) {
605 emit( " <auxwhat>Last byte is "
606 "not inside a known block</auxwhat>\n" );
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
));
616 emit( "%s%s is non-contiguous\n",
618 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
620 if (UNKNOWN
== seglo
) {
621 emit( " First byte is not inside a known block\n" );
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
));
629 if (UNKNOWN
== seghi
) {
630 emit( " Last byte is not inside a known block\n" );
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
));
645 VG_(tool_panic
)("pp_Error: unrecognised error kind");
650 UInt
pc_update_Error_extra ( const Error
* err
)
652 XError
*xe
= (XError
*)VG_(get_error_extra
)(err
);
653 const DiEpoch ep
= VG_(get_ExeContext_epoch
)(VG_(get_error_where
)(err
));
662 xe
->XE
.Heap
.datasymoff
= 0;
663 xe
->XE
.Heap
.datasym
= NULL
;
665 tl_assert(!xe
->XE
.Heap
.descr1
);
666 tl_assert(!xe
->XE
.Heap
.descr2
);
669 = VG_(newXA
)( VG_(malloc
), "pc.update_extra.Heap.descr1",
670 VG_(free
), sizeof(HChar
) );
672 = VG_(newXA
)( VG_(malloc
), "pc.update_extra.Heap.descr1",
673 VG_(free
), sizeof(HChar
) );
675 xe
->XE
.Heap
.datasymoff
= 0;
678 = VG_(get_data_description
)( xe
->XE
.Heap
.descr1
,
680 ep
, xe
->XE
.Heap
.addr
);
682 /* If there's nothing in descr1/2, free it. Why is it safe to
683 to VG_(indexXA) at zero here? Because
684 VG_(get_data_description) guarantees to zero terminate
685 descr1/2 regardless of the outcome of the call. So there's
686 always at least one element in each XA after the call.
688 if (0 == VG_(strlen
)( VG_(indexXA
)( xe
->XE
.Heap
.descr1
, 0 ))
690 VG_(deleteXA
)( xe
->XE
.Heap
.descr1
);
691 xe
->XE
.Heap
.descr1
= NULL
;
693 if (0 == VG_(strlen
)( VG_(indexXA
)( xe
->XE
.Heap
.descr2
, 0 ))
695 VG_(deleteXA
)( xe
->XE
.Heap
.descr2
);
696 xe
->XE
.Heap
.descr2
= NULL
;
699 /* If Dwarf3 info produced nothing useful, see at least if
700 we can fish something useful out of the ELF symbol info. */
703 if (VG_(get_datasym_and_offset
)(
704 ep
, xe
->XE
.Heap
.addr
, &name
,
705 &xe
->XE
.Heap
.datasymoff
)
707 xe
->XE
.Heap
.datasym
=
708 VG_(strdup
)("pc.update_extra.Heap.datasym", name
);
718 VG_(tool_panic
)("update_extra");
720 return sizeof(XError
);
723 Bool
pc_is_recognised_suppression ( const HChar
* name
, Supp
*su
)
727 if (VG_STREQ(name
, "SorG")) skind
= XS_SorG
;
728 else if (VG_STREQ(name
, "Heap")) skind
= XS_Heap
;
729 else if (VG_STREQ(name
, "Arith")) skind
= XS_Arith
;
730 else if (VG_STREQ(name
, "SysParam")) skind
= XS_SysParam
;
734 VG_(set_supp_kind
)(su
, skind
);
738 Bool
pc_read_extra_suppression_info ( Int fd
, HChar
** bufpp
,
739 SizeT
* nBufp
, Int
* lineno
,
743 if (VG_(get_supp_kind
)(su
) == XS_SysParam
) {
744 eof
= VG_(get_line
) ( fd
, bufpp
, nBufp
, lineno
);
745 if (eof
) return False
;
746 VG_(set_supp_string
)(su
, VG_(strdup
)("pc.common.presi.1", *bufpp
));
751 Bool
pc_error_matches_suppression (const Error
* err
, const Supp
* su
)
753 ErrorKind ekind
= VG_(get_error_kind
)(err
);
754 switch (VG_(get_supp_kind
)(su
)) {
755 case XS_SorG
: return ekind
== XE_SorG
;
756 case XS_Heap
: return ekind
== XE_Heap
;
757 case XS_Arith
: return ekind
== XE_Arith
;
758 case XS_SysParam
: return ekind
== XE_SysParam
;
760 VG_(printf
)("Error:\n"
761 " unknown suppression type %d\n",
762 VG_(get_supp_kind
)(su
));
763 VG_(tool_panic
)("unknown suppression type in "
764 "pc_error_matches_suppression");
768 const HChar
* pc_get_error_name ( const Error
* err
)
770 XError
*xe
= (XError
*)VG_(get_error_extra
)(err
);
773 case XE_SorG
: return "SorG";
774 case XE_Heap
: return "Heap";
775 case XE_Arith
: return "Arith";
776 case XE_SysParam
: return "SysParam";
777 default: VG_(tool_panic
)("get_error_name: unexpected type");
781 SizeT
pc_get_extra_suppression_info ( const Error
* err
,
782 /*OUT*/HChar
* buf
, Int nBuf
)
784 ErrorKind ekind
= VG_(get_error_kind
)(err
);
786 tl_assert(nBuf
>= 1);
788 if (XE_SysParam
== ekind
) {
789 const HChar
* errstr
= VG_(get_error_string
)(err
);
791 return VG_(snprintf
)(buf
, nBuf
, "%s", errstr
);
798 SizeT
pc_print_extra_suppression_use ( const Supp
* su
,
799 /*OUT*/HChar
* buf
, Int nBuf
)
801 tl_assert(nBuf
>= 1);
806 void pc_update_extra_suppression_use (const Error
* err
, const Supp
* su
)
811 /*--------------------------------------------------------------------*/
812 /*--- end pc_common.c ---*/
813 /*--------------------------------------------------------------------*/