1
2 /*--------------------------------------------------------------------*/
3 /*--- Ptrcheck: a pointer-use checker. ---*/
4 /*--- Provides stuff shared between sg_ and h_ subtools. ---*/
5 /*--- pc_common.c ---*/
6 /*--------------------------------------------------------------------*/
7
8 /*
9 This file is part of Ptrcheck, a Valgrind tool for checking pointer
10 use in programs.
11
12 Copyright (C) 2008-2010 OpenWorks Ltd
13 info@open-works.co.uk
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31
32 Neither the names of the U.S. Department of Energy nor the
33 University of California nor the names of its contributors may be
34 used to endorse or promote products derived from this software
35 without prior written permission.
36 */
37
38 #include "pub_tool_basics.h"
39 #include "pub_tool_libcbase.h"
40 #include "pub_tool_libcprint.h"
41 #include "pub_tool_xarray.h"
42 #include "pub_tool_mallocfree.h"
43 #include "pub_tool_libcassert.h"
44 #include "pub_tool_options.h"
45 #include "pub_tool_replacemalloc.h"
46 #include "pub_tool_execontext.h"
47 #include "pub_tool_tooliface.h" // CorePart
48 #include "pub_tool_threadstate.h" // VG_(get_running_tid)
49 #include "pub_tool_debuginfo.h"
50
51 #include "pc_common.h" // self, & Seg
52
53 #include "h_main.h" // NONPTR, BOTTOM, UNKNOWN
54
55
56 //////////////////////////////////////////////////////////////
57 // //
58 // Command line options //
59 // //
60 //////////////////////////////////////////////////////////////
61
62 Bool h_clo_partial_loads_ok = True; /* user visible */
63 /* Bool h_clo_lossage_check = False; */ /* dev flag only */
64 Bool sg_clo_enable_sg_checks = True; /* user visible */
65
pc_process_cmd_line_options(Char * arg)66 Bool pc_process_cmd_line_options(Char* arg)
67 {
68 if VG_BOOL_CLO(arg, "--partial-loads-ok", h_clo_partial_loads_ok) {}
69 /* else if VG_BOOL_CLO(arg, "--lossage-check", h_clo_lossage_check) {} */
70 else if VG_BOOL_CLO(arg, "--enable-sg-checks", sg_clo_enable_sg_checks) {}
71 else
72 return VG_(replacement_malloc_process_cmd_line_option)(arg);
73
74 return True;
75 }
76
pc_print_usage(void)77 void pc_print_usage(void)
78 {
79 VG_(printf)(
80 " --partial-loads-ok=no|yes same as for Memcheck [yes]\n"
81 " --enable-sg-checks=no|yes enable stack & global array checking? [yes]\n"
82 );
83 }
84
pc_print_debug_usage(void)85 void pc_print_debug_usage(void)
86 {
87 VG_(printf)(
88 " (none)\n"
89 //" --lossage-check=no|yes gather stats for quality control [no]\n"
90 );
91 }
92
93
94
95 //////////////////////////////////////////////////////////////
96 // //
97 // Error management -- storage //
98 // //
99 //////////////////////////////////////////////////////////////
100
101 /* What kind of error it is. */
102 typedef
103 enum {
104 XE_SorG=1202, // sg: stack or global array inconsistency
105 XE_Heap, // h: mismatched ptr/addr segments on load/store
106 XE_Arith, // h: bad arithmetic between two segment pointers
107 XE_SysParam // h: block straddling >1 segment passed to syscall
108 }
109 XErrorTag;
110
111 typedef
112 enum {
113 XS_SorG=2021,
114 XS_Heap,
115 XS_Arith,
116 XS_SysParam
117 }
118 XSuppTag;
119
120 typedef
121 struct {
122 XErrorTag tag;
123 union {
124 struct {
125 Addr addr;
126 SSizeT sszB; /* -ve is write, +ve is read */
127 HChar expect[128];
128 HChar actual[128];
129 } SorG;
130 struct {
131 Addr addr;
132 SSizeT sszB; /* -ve is write, +ve is read */
133 Seg* vseg;
134 XArray* descr1; /* XArray* of HChar */
135 XArray* descr2; /* XArray* of HChar */
136 Char datasym[96];
137 PtrdiffT datasymoff;
138 } Heap;
139 struct {
140 Seg* seg1;
141 Seg* seg2;
142 const HChar* opname; // user-understandable text name
143 } Arith;
144 struct {
145 CorePart part;
146 Addr lo;
147 Addr hi;
148 Seg* seglo;
149 Seg* seghi;
150 } SysParam;
151 } XE;
152 }
153 XError;
154
155
sg_record_error_SorG(ThreadId tid,Addr addr,SSizeT sszB,HChar * expect,HChar * actual)156 void sg_record_error_SorG ( ThreadId tid,
157 Addr addr, SSizeT sszB,
158 HChar* expect, HChar* actual )
159 {
160 XError xe;
161 VG_(memset)(&xe, 0, sizeof(xe));
162 xe.tag = XE_SorG;
163 xe.XE.SorG.addr = addr;
164 xe.XE.SorG.sszB = sszB;
165 VG_(strncpy)( &xe.XE.SorG.expect[0],
166 expect, sizeof(xe.XE.SorG.expect) );
167 VG_(strncpy)( &xe.XE.SorG.actual[0],
168 actual, sizeof(xe.XE.SorG.actual) );
169 xe.XE.SorG.expect[ sizeof(xe.XE.SorG.expect)-1 ] = 0;
170 xe.XE.SorG.actual[ sizeof(xe.XE.SorG.actual)-1 ] = 0;
171 VG_(maybe_record_error)( tid, XE_SorG, 0, NULL, &xe );
172 }
173
h_record_heap_error(Addr a,SizeT size,Seg * vseg,Bool is_write)174 void h_record_heap_error( Addr a, SizeT size, Seg* vseg, Bool is_write )
175 {
176 XError xe;
177 tl_assert(size > 0);
178 VG_(memset)(&xe, 0, sizeof(xe));
179 xe.tag = XE_Heap;
180 xe.XE.Heap.addr = a;
181 xe.XE.Heap.sszB = is_write ? -size : size;
182 xe.XE.Heap.vseg = vseg;
183 VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Heap,
184 /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
185 }
186
h_record_arith_error(Seg * seg1,Seg * seg2,HChar * opname)187 void h_record_arith_error( Seg* seg1, Seg* seg2, HChar* opname )
188 {
189 XError xe;
190 VG_(memset)(&xe, 0, sizeof(xe));
191 xe.tag = XE_Arith;
192 xe.XE.Arith.seg1 = seg1;
193 xe.XE.Arith.seg2 = seg2;
194 xe.XE.Arith.opname = opname;
195 VG_(maybe_record_error)( VG_(get_running_tid)(), XE_Arith,
196 /*a*/0, /*str*/NULL, /*extra*/(void*)&xe);
197 }
198
h_record_sysparam_error(ThreadId tid,CorePart part,Char * s,Addr lo,Addr hi,Seg * seglo,Seg * seghi)199 void h_record_sysparam_error( ThreadId tid, CorePart part, Char* s,
200 Addr lo, Addr hi, Seg* seglo, Seg* seghi )
201 {
202 XError xe;
203 VG_(memset)(&xe, 0, sizeof(xe));
204 xe.tag = XE_SysParam;
205 xe.XE.SysParam.part = part;
206 xe.XE.SysParam.lo = lo;
207 xe.XE.SysParam.hi = hi;
208 xe.XE.SysParam.seglo = seglo;
209 xe.XE.SysParam.seghi = seghi;
210 VG_(maybe_record_error)( tid, XE_SysParam, /*a*/(Addr)0, /*str*/s,
211 /*extra*/(void*)&xe);
212 }
213
214
pc_eq_Error(VgRes res,Error * e1,Error * e2)215 Bool pc_eq_Error ( VgRes res, Error* e1, Error* e2 )
216 {
217 XError *xe1, *xe2;
218 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
219 //tl_assert(VG_(get_error_string)(e1) == NULL);
220 //tl_assert(VG_(get_error_string)(e2) == NULL);
221
222 xe1 = (XError*)VG_(get_error_extra)(e1);
223 xe2 = (XError*)VG_(get_error_extra)(e2);
224 tl_assert(xe1);
225 tl_assert(xe2);
226
227 if (xe1->tag != xe2->tag)
228 return False;
229
230 switch (xe1->tag) {
231 case XE_SorG:
232 return //xe1->XE.SorG.addr == xe2->XE.SorG.addr
233 //&&
234 xe1->XE.SorG.sszB == xe2->XE.SorG.sszB
235 && 0 == VG_(strncmp)( &xe1->XE.SorG.expect[0],
236 &xe2->XE.SorG.expect[0],
237 sizeof(xe1->XE.SorG.expect) )
238 && 0 == VG_(strncmp)( &xe1->XE.SorG.actual[0],
239 &xe2->XE.SorG.actual[0],
240 sizeof(xe1->XE.SorG.actual) );
241 case XE_Heap:
242 case XE_Arith:
243 case XE_SysParam:
244 return True;
245 default:
246 VG_(tool_panic)("eq_Error: unrecognised error kind");
247 }
248 }
249
250
251 //////////////////////////////////////////////////////////////
252 // //
253 // Error management -- printing //
254 // //
255 //////////////////////////////////////////////////////////////
256
257 /* This is the "this error is due to be printed shortly; so have a
258 look at it any print any preamble you want" function. Which, in
259 Ptrcheck, we don't use. Hence a no-op.
260 */
pc_before_pp_Error(Error * err)261 void pc_before_pp_Error ( Error* err ) {
262 }
263
264 /* Do a printf-style operation on either the XML or normal output
265 channel, depending on the setting of VG_(clo_xml).
266 */
emit_WRK(HChar * format,va_list vargs)267 static void emit_WRK ( HChar* format, va_list vargs )
268 {
269 if (VG_(clo_xml)) {
270 VG_(vprintf_xml)(format, vargs);
271 } else {
272 VG_(vmessage)(Vg_UserMsg, format, vargs);
273 }
274 }
275 static void emit ( HChar* format, ... ) PRINTF_CHECK(1, 2);
emit(HChar * format,...)276 static void emit ( HChar* format, ... )
277 {
278 va_list vargs;
279 va_start(vargs, format);
280 emit_WRK(format, vargs);
281 va_end(vargs);
282 }
emiN(HChar * format,...)283 static void emiN ( HChar* format, ... ) /* With NO FORMAT CHECK */
284 {
285 va_list vargs;
286 va_start(vargs, format);
287 emit_WRK(format, vargs);
288 va_end(vargs);
289 }
290
291
readwrite(SSizeT sszB)292 static Char* readwrite(SSizeT sszB)
293 {
294 return ( sszB < 0 ? "write" : "read" );
295 }
296
Word__abs(Word w)297 static Word Word__abs ( Word w ) {
298 return w < 0 ? -w : w;
299 }
300
pc_pp_Error(Error * err)301 void pc_pp_Error ( Error* err )
302 {
303 const Bool xml = VG_(clo_xml); /* a shorthand, that's all */
304
305 XError *xe = (XError*)VG_(get_error_extra)(err);
306 tl_assert(xe);
307
308 switch (VG_(get_error_kind)(err)) {
309
310 //----------------------------------------------------------
311 case XE_SorG:
312
313 if (xml) {
314
315 emit( " <kind>SorG</kind>\n");
316 emit( " <what>Invalid %s of size %ld</what>\n",
317 xe->XE.SorG.sszB < 0 ? "write" : "read",
318 Word__abs(xe->XE.SorG.sszB) );
319 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
320
321 emit( " <auxwhat>Address %#lx expected vs actual:</auxwhat>\n",
322 xe->XE.SorG.addr );
323 emiN( " <auxwhat>Expected: %t</auxwhat>\n",
324 &xe->XE.SorG.expect[0] );
325 emiN( " <auxwhat>Actual: %t</auxwhat>\n",
326 &xe->XE.SorG.actual[0] );
327
328 } else {
329
330 emit( "Invalid %s of size %ld\n",
331 xe->XE.SorG.sszB < 0 ? "write" : "read",
332 Word__abs(xe->XE.SorG.sszB) );
333 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
334
335 emit( " Address %#lx expected vs actual:\n", xe->XE.SorG.addr );
336 emit( " Expected: %s\n", &xe->XE.SorG.expect[0] );
337 emit( " Actual: %s\n", &xe->XE.SorG.actual[0] );
338
339 }
340 break;
341
342 //----------------------------------------------------------
343 case XE_Heap: {
344 Char *place, *legit, *how_invalid;
345 Addr a = xe->XE.Heap.addr;
346 Seg* vseg = xe->XE.Heap.vseg;
347
348 tl_assert(is_known_segment(vseg) || NONPTR == vseg);
349
350 if (NONPTR == vseg) {
351 // Access via a non-pointer
352
353 if (xml) {
354
355 emit( " <kind>Heap</kind>\n");
356 emit( " <what>Invalid %s of size %ld</what>\n",
357 readwrite(xe->XE.Heap.sszB),
358 Word__abs(xe->XE.Heap.sszB) );
359 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
360
361 emit( " <auxwhat>Address %#lx is not derived from "
362 "any known block</auxwhat>\n", a );
363
364 } else {
365
366 emit( "Invalid %s of size %ld\n",
367 readwrite(xe->XE.Heap.sszB),
368 Word__abs(xe->XE.Heap.sszB) );
369 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
370
371 emit( " Address %#lx is not derived from "
372 "any known block\n", a );
373
374 }
375
376 } else {
377 // Access via a pointer, but outside its range.
378 Int cmp;
379 UWord miss_size;
380 Seg__cmp(vseg, a, &cmp, &miss_size);
381 if (cmp < 0) place = "before";
382 else if (cmp == 0) place = "inside";
383 else place = "after";
384 how_invalid = ( ( Seg__is_freed(vseg) && 0 != cmp )
385 ? "Doubly-invalid" : "Invalid" );
386 legit = ( Seg__is_freed(vseg) ? "once-" : "" );
387
388 if (xml) {
389
390 emit( " <kind>Heap</kind>\n");
391 emit( " <what>%s %s of size %ld</what>\n",
392 how_invalid,
393 readwrite(xe->XE.Heap.sszB),
394 Word__abs(xe->XE.Heap.sszB) );
395 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
396
397 emit( " <auxwhat>Address %#lx is %lu bytes %s "
398 "the accessing pointer's</auxwhat>\n",
399 a, miss_size, place );
400 emit( " <auxwhat>%slegitimate range, "
401 "a block of size %lu %s</auxwhat>\n",
402 legit, Seg__size(vseg),
403 Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
404 VG_(pp_ExeContext)(Seg__where(vseg));
405
406 } else {
407
408 emit( "%s %s of size %ld\n",
409 how_invalid,
410 readwrite(xe->XE.Heap.sszB),
411 Word__abs(xe->XE.Heap.sszB) );
412 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
413
414 emit( " Address %#lx is %lu bytes %s the accessing pointer's\n",
415 a, miss_size, place );
416 emit( " %slegitimate range, a block of size %lu %s\n",
417 legit, Seg__size(vseg),
418 Seg__is_freed(vseg) ? "free'd" : "alloc'd" );
419 VG_(pp_ExeContext)(Seg__where(vseg));
420
421 }
422 }
423
424 /* If we have a better description of the address, show it.
425 Note that in XML mode, it will already by nicely wrapped up
426 in tags, either <auxwhat> or <xauxwhat>, so we can just emit
427 it verbatim. */
428 if (xml) {
429
430 if (xe->XE.Heap.descr1)
431 emiN( " %t\n",
432 (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
433 if (xe->XE.Heap.descr2)
434 emiN( " %t\n",
435 (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
436 if (xe->XE.Heap.datasym[0] != 0)
437 emiN( " <auxwhat>Address 0x%llx is %llu bytes "
438 "inside data symbol \"%t\"</auxwhat>\n",
439 (ULong)xe->XE.Heap.addr,
440 (ULong)xe->XE.Heap.datasymoff,
441 xe->XE.Heap.datasym );
442
443 } else {
444
445 if (xe->XE.Heap.descr1)
446 emit( " %s\n",
447 (HChar*)VG_(indexXA)( xe->XE.Heap.descr1, 0 ) );
448 if (xe->XE.Heap.descr2)
449 emit( " %s\n",
450 (HChar*)VG_(indexXA)( xe->XE.Heap.descr2, 0 ) );
451 if (xe->XE.Heap.datasym[0] != 0)
452 emit( " Address 0x%llx is %llu bytes "
453 "inside data symbol \"%s\"\n",
454 (ULong)xe->XE.Heap.addr,
455 (ULong)xe->XE.Heap.datasymoff,
456 xe->XE.Heap.datasym );
457
458 }
459 break;
460 }
461
462 //----------------------------------------------------------
463 case XE_Arith: {
464 Seg* seg1 = xe->XE.Arith.seg1;
465 Seg* seg2 = xe->XE.Arith.seg2;
466 Char* which;
467
468 tl_assert(BOTTOM != seg1);
469 tl_assert(BOTTOM != seg2 && UNKNOWN != seg2);
470
471 if (xml) {
472
473 emit( " <kind>Arith</kind>\n");
474 emit( " <what>Invalid arguments to %s</what>\n",
475 xe->XE.Arith.opname );
476 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
477
478 if (seg1 != seg2) {
479 if (NONPTR == seg1) {
480 emit( " <auxwhat>First arg not a pointer</auxwhat>\n" );
481 } else if (UNKNOWN == seg1) {
482 emit( " <auxwhat>First arg may be a pointer</auxwhat>\n" );
483 } else {
484 emit( " <auxwhat>First arg derived from address %#lx of "
485 "%lu-byte block alloc'd</auxwhat>\n",
486 Seg__addr(seg1), Seg__size(seg1) );
487 VG_(pp_ExeContext)(Seg__where(seg1));
488 }
489 which = "Second arg";
490 } else {
491 which = "Both args";
492 }
493 if (NONPTR == seg2) {
494 emit( " <auxwhat>%s not a pointer</auxwhat>\n", which );
495 } else {
496 emit( " <auxwhat>%s derived from address %#lx of "
497 "%lu-byte block alloc'd</auxwhat>\n",
498 which, Seg__addr(seg2), Seg__size(seg2) );
499 VG_(pp_ExeContext)(Seg__where(seg2));
500 }
501
502 } else {
503
504 emit( "Invalid arguments to %s\n",
505 xe->XE.Arith.opname );
506 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
507
508 if (seg1 != seg2) {
509 if (NONPTR == seg1) {
510 emit( " First arg not a pointer\n" );
511 } else if (UNKNOWN == seg1) {
512 emit( " First arg may be a pointer\n" );
513 } else {
514 emit( " First arg derived from address %#lx of "
515 "%lu-byte block alloc'd\n",
516 Seg__addr(seg1), Seg__size(seg1) );
517 VG_(pp_ExeContext)(Seg__where(seg1));
518 }
519 which = "Second arg";
520 } else {
521 which = "Both args";
522 }
523 if (NONPTR == seg2) {
524 emit( " %s not a pointer\n", which );
525 } else {
526 emit( " %s derived from address %#lx of "
527 "%lu-byte block alloc'd\n",
528 which, Seg__addr(seg2), Seg__size(seg2) );
529 VG_(pp_ExeContext)(Seg__where(seg2));
530 }
531
532 }
533
534 break;
535 }
536
537 //----------------------------------------------------------
538 case XE_SysParam: {
539 Addr lo = xe->XE.SysParam.lo;
540 Addr hi = xe->XE.SysParam.hi;
541 Seg* seglo = xe->XE.SysParam.seglo;
542 Seg* seghi = xe->XE.SysParam.seghi;
543 Char* s = VG_(get_error_string) (err);
544 Char* what;
545
546 tl_assert(BOTTOM != seglo && BOTTOM != seghi);
547
548 if (Vg_CoreSysCall == xe->XE.SysParam.part)
549 what = "Syscall param ";
550 else VG_(tool_panic)("bad CorePart");
551
552 if (seglo == seghi) {
553 // freed block
554 tl_assert(is_known_segment(seglo));
555 tl_assert(Seg__is_freed(seglo)); // XXX what if it's now recycled?
556
557 if (xml) {
558
559 emit( " <kind>SysParam</kind>\n");
560 emit( " <what>%s%s contains unaddressable byte(s)</what>\n",
561 what, s );
562 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
563
564 emit( " <auxwhat>Address %#lx is %ld bytes inside a "
565 "%ld-byte block free'd</auxwhat>\n",
566 lo, lo-Seg__addr(seglo), Seg__size(seglo) );
567 VG_(pp_ExeContext)(Seg__where(seglo));
568
569 } else {
570
571 emit( " %s%s contains unaddressable byte(s)\n",
572 what, s );
573 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
574
575 emit( " Address %#lx is %ld bytes inside a "
576 "%ld-byte block free'd\n",
577 lo, lo-Seg__addr(seglo), Seg__size(seglo) );
578 VG_(pp_ExeContext)(Seg__where(seglo));
579
580 }
581
582 } else {
583 // mismatch
584
585 if (xml) {
586
587 emit( " <kind>SysParam</kind>\n");
588 emit( " <what>%s%s is non-contiguous</what>\n",
589 what, s );
590 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
591
592 if (UNKNOWN == seglo) {
593 emit( " <auxwhat>First byte is "
594 "not inside a known block</auxwhat>\n" );
595 } else {
596 emit( " <auxwhat>First byte (%#lx) is %ld bytes inside a "
597 "%ld-byte block alloc'd</auxwhat>\n",
598 lo, lo-Seg__addr(seglo), Seg__size(seglo) );
599 VG_(pp_ExeContext)(Seg__where(seglo));
600 }
601
602 if (UNKNOWN == seghi) {
603 emit( " <auxwhat>Last byte is "
604 "not inside a known block</auxwhat>\n" );
605 } else {
606 emit( " <auxwhat>Last byte (%#lx) is %ld bytes inside a "
607 "%ld-byte block alloc'd</auxwhat>\n",
608 hi, hi-Seg__addr(seghi), Seg__size(seghi) );
609 VG_(pp_ExeContext)(Seg__where(seghi));
610 }
611
612 } else {
613
614 emit( "%s%s is non-contiguous\n",
615 what, s );
616 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
617
618 if (UNKNOWN == seglo) {
619 emit( " First byte is not inside a known block\n" );
620 } else {
621 emit( " First byte (%#lx) is %ld bytes inside a "
622 "%ld-byte block alloc'd\n",
623 lo, lo-Seg__addr(seglo), Seg__size(seglo) );
624 VG_(pp_ExeContext)(Seg__where(seglo));
625 }
626
627 if (UNKNOWN == seghi) {
628 emit( " Last byte is not inside a known block\n" );
629 } else {
630 emit( " Last byte (%#lx) is %ld bytes inside a "
631 "%ld-byte block alloc'd\n",
632 hi, hi-Seg__addr(seghi), Seg__size(seghi) );
633 VG_(pp_ExeContext)(Seg__where(seghi));
634 }
635
636 }
637
638 }
639 break;
640 }
641
642 default:
643 VG_(tool_panic)("pp_Error: unrecognised error kind");
644 }
645 }
646
647
pc_update_Error_extra(Error * err)648 UInt pc_update_Error_extra ( Error* err )
649 {
650 XError *xe = (XError*)VG_(get_error_extra)(err);
651 tl_assert(xe);
652 switch (xe->tag) {
653 case XE_SorG:
654 break;
655 case XE_Heap: {
656 Bool have_descr;
657
658 tl_assert(sizeof(xe->XE.Heap.datasym) > 0);
659 xe->XE.Heap.datasymoff = 0;
660 xe->XE.Heap.datasym[0] = 0;
661
662 tl_assert(!xe->XE.Heap.descr1);
663 tl_assert(!xe->XE.Heap.descr2);
664
665 xe->XE.Heap.descr1
666 = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
667 VG_(free), sizeof(HChar) );
668 xe->XE.Heap.descr2
669 = VG_(newXA)( VG_(malloc), "pc.update_extra.Heap.descr1",
670 VG_(free), sizeof(HChar) );
671
672 VG_(memset)(&xe->XE.Heap.datasym, 0, sizeof(xe->XE.Heap.datasym));
673 xe->XE.Heap.datasymoff = 0;
674
675 have_descr
676 = VG_(get_data_description)( xe->XE.Heap.descr1,
677 xe->XE.Heap.descr2,
678 xe->XE.Heap.addr );
679
680 /* If there's nothing in descr1/2, free it. Why is it safe to
681 to VG_(indexXA) at zero here? Because
682 VG_(get_data_description) guarantees to zero terminate
683 descr1/2 regardless of the outcome of the call. So there's
684 always at least one element in each XA after the call.
685 */
686 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr1, 0 ))
687 || !have_descr) {
688 VG_(deleteXA)( xe->XE.Heap.descr1 );
689 xe->XE.Heap.descr1 = NULL;
690 }
691 if (0 == VG_(strlen)( VG_(indexXA)( xe->XE.Heap.descr2, 0 ))
692 || !have_descr) {
693 VG_(deleteXA)( xe->XE.Heap.descr2 );
694 xe->XE.Heap.descr2 = NULL;
695 }
696
697 /* If Dwarf3 info produced nothing useful, see at least if
698 we can fish something useful out of the ELF symbol info. */
699 if (!have_descr) {
700 if (VG_(get_datasym_and_offset)(
701 xe->XE.Heap.addr, &xe->XE.Heap.datasym[0],
702 sizeof(xe->XE.Heap.datasym)-1,
703 &xe->XE.Heap.datasymoff )
704 ) {
705 tl_assert(xe->XE.Heap.datasym[sizeof(xe->XE.Heap.datasym)-1]
706 == 0);
707 }
708 }
709 break;
710 }
711 case XE_Arith:
712 break;
713 case XE_SysParam:
714 break;
715 default:
716 VG_(tool_panic)("update_extra");
717 }
718 return sizeof(XError);
719 }
720
pc_is_recognised_suppression(Char * name,Supp * su)721 Bool pc_is_recognised_suppression ( Char* name, Supp *su )
722 {
723 SuppKind skind;
724
725 if (VG_STREQ(name, "SorG")) skind = XS_SorG;
726 else if (VG_STREQ(name, "Heap")) skind = XS_Heap;
727 else if (VG_STREQ(name, "Arith")) skind = XS_Arith;
728 else if (VG_STREQ(name, "SysParam")) skind = XS_SysParam;
729 else
730 return False;
731
732 VG_(set_supp_kind)(su, skind);
733 return True;
734 }
735
pc_read_extra_suppression_info(Int fd,Char ** bufpp,SizeT * nBufp,Supp * su)736 Bool pc_read_extra_suppression_info ( Int fd, Char** bufpp,
737 SizeT* nBufp, Supp* su )
738 {
739 Bool eof;
740 if (VG_(get_supp_kind)(su) == XS_SysParam) {
741 eof = VG_(get_line) ( fd, bufpp, nBufp, NULL );
742 if (eof) return False;
743 VG_(set_supp_string)(su, VG_(strdup)("pc.common.presi.1", *bufpp));
744 }
745 return True;
746 }
747
pc_error_matches_suppression(Error * err,Supp * su)748 Bool pc_error_matches_suppression (Error* err, Supp* su)
749 {
750 ErrorKind ekind = VG_(get_error_kind)(err);
751 switch (VG_(get_supp_kind)(su)) {
752 case XS_SorG: return ekind == XE_SorG;
753 case XS_Heap: return ekind == XE_Heap;
754 case XS_Arith: return ekind == XE_Arith;
755 case XS_SysParam: return ekind == XE_SysParam;
756 default:
757 VG_(printf)("Error:\n"
758 " unknown suppression type %d\n",
759 VG_(get_supp_kind)(su));
760 VG_(tool_panic)("unknown suppression type in "
761 "pc_error_matches_suppression");
762 }
763 }
764
pc_get_error_name(Error * err)765 Char* pc_get_error_name ( Error* err )
766 {
767 XError *xe = (XError*)VG_(get_error_extra)(err);
768 tl_assert(xe);
769 switch (xe->tag) {
770 case XE_SorG: return "SorG";
771 case XE_Heap: return "Heap";
772 case XE_Arith: return "Arith";
773 case XE_SysParam: return "SysParam";
774 default: VG_(tool_panic)("get_error_name: unexpected type");
775 }
776 }
777
pc_get_extra_suppression_info(Error * err,Char * buf,Int nBuf)778 Bool pc_get_extra_suppression_info ( Error* err,
779 /*OUT*/Char* buf, Int nBuf )
780 {
781 ErrorKind ekind = VG_(get_error_kind )(err);
782 tl_assert(buf);
783 tl_assert(nBuf >= 16); // stay sane
784 if (XE_SysParam == ekind) {
785 Char* errstr = VG_(get_error_string)(err);
786 tl_assert(errstr);
787 VG_(snprintf)(buf, nBuf-1, "%s", errstr);
788 return True;
789 } else {
790 return False;
791 }
792 }
793
794
795 /*--------------------------------------------------------------------*/
796 /*--- end pc_common.c ---*/
797 /*--------------------------------------------------------------------*/
798