blob: f8a957bab3cac67f28bfbebac7918af09bb117fb [file] [log] [blame]
njn132bfcc2005-06-04 19:16:06 +00001
2/*--------------------------------------------------------------------*/
3/*--- Assertions and panics. m_libcassert.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj0f157dd2013-10-18 14:27:36 +000010 Copyright (C) 2000-2013 Julian Seward
njn132bfcc2005-06-04 19:16:06 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
sewardj745fc452006-10-17 02:03:11 +000033#include "pub_core_vkiscnums.h"
sewardj6c591e12011-04-11 16:17:51 +000034#include "pub_core_libcsetjmp.h" // to keep threadstate.h happy
njn49b45ba2005-07-20 02:41:31 +000035#include "pub_core_threadstate.h"
philippe180a7502014-04-20 13:41:10 +000036#include "pub_core_gdbserver.h"
philippe4f6f3362014-04-19 00:25:54 +000037#include "pub_core_aspacemgr.h"
njn132bfcc2005-06-04 19:16:06 +000038#include "pub_core_libcbase.h"
39#include "pub_core_libcassert.h"
40#include "pub_core_libcprint.h"
njn49b45ba2005-07-20 02:41:31 +000041#include "pub_core_libcproc.h" // For VG_(gettid)()
42#include "pub_core_stacktrace.h"
njn9abd6082005-06-17 21:31:45 +000043#include "pub_core_syscall.h"
njne070c202005-06-20 23:58:15 +000044#include "pub_core_tooliface.h" // For VG_(details).{name,bug_reports_to}
sewardjf349d552005-11-14 17:01:01 +000045#include "pub_core_options.h" // For VG_(clo_xml)
njn132bfcc2005-06-04 19:16:06 +000046
47/* ---------------------------------------------------------------------
48 Assertery.
49 ------------------------------------------------------------------ */
50
sewardj59570ff2010-01-01 11:59:33 +000051#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
52# define GET_STARTREGS(srP) \
53 { UInt eip, esp, ebp; \
54 __asm__ __volatile__( \
55 "call 0f;" \
56 "0: popl %0;" \
57 "movl %%esp, %1;" \
58 "movl %%ebp, %2;" \
59 : "=r" (eip), "=r" (esp), "=r" (ebp) \
60 : /* reads none */ \
61 : "memory" \
62 ); \
63 (srP)->r_pc = (ULong)eip; \
64 (srP)->r_sp = (ULong)esp; \
65 (srP)->misc.X86.r_ebp = ebp; \
66 }
67#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
68# define GET_STARTREGS(srP) \
69 { ULong rip, rsp, rbp; \
70 __asm__ __volatile__( \
71 "leaq 0(%%rip), %0;" \
72 "movq %%rsp, %1;" \
73 "movq %%rbp, %2;" \
74 : "=r" (rip), "=r" (rsp), "=r" (rbp) \
75 : /* reads none */ \
76 : "memory" \
77 ); \
78 (srP)->r_pc = rip; \
79 (srP)->r_sp = rsp; \
80 (srP)->misc.AMD64.r_rbp = rbp; \
81 }
sewardj6e9de462011-06-28 07:25:29 +000082#elif defined(VGP_ppc32_linux)
sewardj59570ff2010-01-01 11:59:33 +000083# define GET_STARTREGS(srP) \
84 { UInt cia, r1, lr; \
85 __asm__ __volatile__( \
86 "mflr 0;" /* r0 = lr */ \
87 "bl m_libcassert_get_ip;" /* lr = pc */ \
88 "m_libcassert_get_ip:\n" \
89 "mflr %0;" /* %0 = pc */ \
90 "mtlr 0;" /* restore lr */ \
91 "mr %1,1;" /* %1 = r1 */ \
92 "mr %2,0;" /* %2 = lr */ \
93 : "=r" (cia), "=r" (r1), "=r" (lr) \
94 : /* reads none */ \
95 : "r0" /* trashed */ \
96 ); \
sewardjf5f1e122010-01-02 13:24:58 +000097 (srP)->r_pc = (ULong)cia; \
98 (srP)->r_sp = (ULong)r1; \
99 (srP)->misc.PPC32.r_lr = lr; \
sewardj59570ff2010-01-01 11:59:33 +0000100 }
sewardj6e9de462011-06-28 07:25:29 +0000101#elif defined(VGP_ppc64_linux)
sewardj59570ff2010-01-01 11:59:33 +0000102# define GET_STARTREGS(srP) \
103 { ULong cia, r1, lr; \
104 __asm__ __volatile__( \
105 "mflr 0;" /* r0 = lr */ \
106 "bl .m_libcassert_get_ip;" /* lr = pc */ \
107 ".m_libcassert_get_ip:\n" \
108 "mflr %0;" /* %0 = pc */ \
109 "mtlr 0;" /* restore lr */ \
110 "mr %1,1;" /* %1 = r1 */ \
111 "mr %2,0;" /* %2 = lr */ \
112 : "=r" (cia), "=r" (r1), "=r" (lr) \
113 : /* reads none */ \
114 : "r0" /* trashed */ \
115 ); \
sewardjf5f1e122010-01-02 13:24:58 +0000116 (srP)->r_pc = cia; \
117 (srP)->r_sp = r1; \
118 (srP)->misc.PPC64.r_lr = lr; \
sewardj59570ff2010-01-01 11:59:33 +0000119 }
120#elif defined(VGP_arm_linux)
121# define GET_STARTREGS(srP) \
sewardjfa5ce562010-09-23 22:05:59 +0000122 { UInt block[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000123 __asm__ __volatile__( \
124 "str r15, [%0, #+0];" \
125 "str r14, [%0, #+4];" \
126 "str r13, [%0, #+8];" \
127 "str r12, [%0, #+12];" \
128 "str r11, [%0, #+16];" \
sewardjfa5ce562010-09-23 22:05:59 +0000129 "str r7, [%0, #+20];" \
sewardj59570ff2010-01-01 11:59:33 +0000130 : /* out */ \
131 : /* in */ "r"(&block[0]) \
132 : /* trash */ "memory" \
133 ); \
134 (srP)->r_pc = block[0] - 8; \
135 (srP)->r_sp = block[1]; \
136 (srP)->misc.ARM.r14 = block[2]; \
137 (srP)->misc.ARM.r12 = block[3]; \
138 (srP)->misc.ARM.r11 = block[4]; \
sewardjfa5ce562010-09-23 22:05:59 +0000139 (srP)->misc.ARM.r7 = block[5]; \
sewardj59570ff2010-01-01 11:59:33 +0000140 }
sewardjf0c12502014-01-12 12:54:00 +0000141#elif defined(VGP_arm64_linux)
142# define GET_STARTREGS(srP) \
143 { ULong block[4]; \
144 __asm__ __volatile__( \
145 "adr x19, 0;" \
146 "str x19, [%0, #+0];" /* pc */ \
147 "mov x19, sp;" \
148 "str x19, [%0, #+8];" /* sp */ \
149 "str x29, [%0, #+16];" /* fp */ \
150 "str x30, [%0, #+24];" /* lr */ \
151 : /* out */ \
152 : /* in */ "r"(&block[0]) \
153 : /* trash */ "memory","x19" \
154 ); \
155 (srP)->r_pc = block[0]; \
156 (srP)->r_sp = block[1]; \
157 (srP)->misc.ARM64.x29 = block[2]; \
158 (srP)->misc.ARM64.x30 = block[3]; \
159 }
sewardjb5b87402011-03-07 16:05:35 +0000160#elif defined(VGP_s390x_linux)
161# define GET_STARTREGS(srP) \
162 { ULong ia, sp, fp, lr; \
163 __asm__ __volatile__( \
164 "bras %0,0f;" \
165 "0: lgr %1,15;" \
166 "lgr %2,11;" \
167 "lgr %3,14;" \
168 : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr) \
169 /* no read & clobber */ \
170 ); \
171 (srP)->r_pc = ia; \
172 (srP)->r_sp = sp; \
173 (srP)->misc.S390X.r_fp = fp; \
174 (srP)->misc.S390X.r_lr = lr; \
175 }
sewardj5db15402012-06-07 09:13:21 +0000176#elif defined(VGP_mips32_linux)
177# define GET_STARTREGS(srP) \
178 { UInt pc, sp, fp, ra, gp; \
179 asm("move $8, $31;" /* t0 = ra */ \
180 "bal m_libcassert_get_ip;" /* ra = pc */ \
181 "m_libcassert_get_ip:\n" \
182 "move %0, $31;" \
183 "move $31, $8;" /* restore lr */ \
184 "move %1, $29;" \
185 "move %2, $30;" \
186 "move %3, $31;" \
187 "move %4, $28;" \
188 : "=r" (pc), \
189 "=r" (sp), \
190 "=r" (fp), \
191 "=r" (ra), \
192 "=r" (gp) \
193 : /* reads none */ \
194 : "$8" /* trashed */ ); \
195 (srP)->r_pc = (ULong)pc - 8; \
196 (srP)->r_sp = (ULong)sp; \
197 (srP)->misc.MIPS32.r30 = (ULong)fp; \
198 (srP)->misc.MIPS32.r31 = (ULong)ra; \
199 (srP)->misc.MIPS32.r28 = (ULong)gp; \
200 }
petarj4df0bfc2013-02-27 23:17:33 +0000201#elif defined(VGP_mips64_linux)
202# define GET_STARTREGS(srP) \
203 { ULong pc, sp, fp, ra, gp; \
204 asm("move $8, $31;" /* t0 = ra */ \
205 "bal m_libcassert_get_ip;" /* ra = pc */ \
206 "m_libcassert_get_ip:\n" \
207 "move %0, $31;" \
208 "move $31, $8;" /* restore lr */ \
209 "move %1, $29;" \
210 "move %2, $30;" \
211 "move %3, $31;" \
212 "move %4, $28;" \
213 : "=r" (pc), \
214 "=r" (sp), \
215 "=r" (fp), \
216 "=r" (ra), \
217 "=r" (gp) \
218 : /* reads none */ \
219 : "$8" /* trashed */ ); \
220 (srP)->r_pc = (ULong)pc - 8; \
221 (srP)->r_sp = (ULong)sp; \
222 (srP)->misc.MIPS64.r30 = (ULong)fp; \
223 (srP)->misc.MIPS64.r31 = (ULong)ra; \
224 (srP)->misc.MIPS64.r28 = (ULong)gp; \
225 }
njn9450d242005-06-26 20:50:05 +0000226#else
227# error Unknown platform
228#endif
229
230#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +0000231
philippe180a7502014-04-20 13:41:10 +0000232__attribute__ ((__noreturn__))
233static void exit_wrk( Int status, Bool gdbserver_call_allowed)
njnf39e9a32005-06-12 02:43:17 +0000234{
philippe180a7502014-04-20 13:41:10 +0000235 static Bool exit_called = False;
236 // avoid recursive exit during gdbserver call.
237
238 if (gdbserver_call_allowed && !exit_called) {
239 const ThreadId atid = 1; // Arbitrary tid used to call/terminate gdbsrv.
240 exit_called = True;
241 if (status != 0 && VG_(gdbserver_stop_at) (VgdbStopAt_ValgrindAbExit)) {
242 if (VG_(gdbserver_init_done)()) {
243 VG_(umsg)("(action at valgrind abnormal exit) vgdb me ... \n");
244 VG_(gdbserver) (atid);
245 } else {
246 VG_(umsg)("(action at valgrind abnormal exit) "
247 "Early valgrind exit : vgdb not yet usable\n");
248 }
249 }
250 if (VG_(gdbserver_init_done)()) {
251 // Always terminate the gdbserver when Valgrind exits, so as
252 // to e.g. cleanup the FIFOs.
253 VG_(gdbserver_exit) (atid,
254 status == 0 ? VgSrc_ExitProcess : VgSrc_FatalSig);
255 }
256 }
257 exit_called = True;
258
njn5b6b8fa2009-05-19 05:28:43 +0000259#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000260 (void)VG_(do_syscall1)(__NR_exit_group, status );
sewardj6e9de462011-06-28 07:25:29 +0000261#elif defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000262 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000263#else
264# error Unknown OS
265#endif
njnf39e9a32005-06-12 02:43:17 +0000266 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000267 // We really shouldn't reach here. Just in case we do, use some very crude
268 // methods to force abort
269 __builtin_trap();
270 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000271}
272
philippe180a7502014-04-20 13:41:10 +0000273/* Pull down the entire world */
274void VG_(exit)( Int status )
275{
276 exit_wrk (status, True);
277}
278
279/* Pull down the entire world */
280void VG_(client_exit)( Int status )
281{
282 exit_wrk (status, False);
283}
284
285
njnc7561b92005-06-19 01:24:32 +0000286// Print the scheduler status.
philippe4f6f3362014-04-19 00:25:54 +0000287static void show_sched_status_wrk ( Bool host_stacktrace,
288 Bool valgrind_stack_usage,
289 Bool exited_threads,
290 UnwindStartRegs* startRegsIN)
njn49b45ba2005-07-20 02:41:31 +0000291{
292 Int i;
philippe4f6f3362014-04-19 00:25:54 +0000293 if (host_stacktrace) {
294 const Bool save_clo_xml = VG_(clo_xml);
295 Addr stacktop;
296 Addr ips[BACKTRACE_DEPTH];
297 Int n_ips;
298 ThreadState *tst
299 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
300
301 // If necessary, fake up an ExeContext which is of our actual real CPU
302 // state. Could cause problems if we got the panic/exception within the
303 // execontext/stack dump/symtab code. But it's better than nothing.
304 UnwindStartRegs startRegs;
305 VG_(memset)(&startRegs, 0, sizeof(startRegs));
306
307 if (startRegsIN == NULL) {
308 GET_STARTREGS(&startRegs);
309 } else {
310 startRegs = *startRegsIN;
311 }
312
313 stacktop = tst->os_state.valgrind_stack_init_SP;
314
315 n_ips =
316 VG_(get_StackTrace_wrk)(
317 0/*tid is unknown*/,
318 ips, BACKTRACE_DEPTH,
319 NULL/*array to dump SP values in*/,
320 NULL/*array to dump FP values in*/,
321 &startRegs, stacktop
322 );
323 VG_(printf)("\nhost stacktrace:\n");
324 VG_(clo_xml) = False;
325 VG_(pp_StackTrace) (ips, n_ips);
326 VG_(clo_xml) = save_clo_xml;
327 }
328
njn49b45ba2005-07-20 02:41:31 +0000329 VG_(printf)("\nsched status:\n");
330 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
331 for (i = 1; i < VG_N_THREADS; i++) {
philippe4f6f3362014-04-19 00:25:54 +0000332 VgStack* stack
333 = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
334 /* If a thread slot was never used (yet), valgrind_stack_base is 0.
335 If a thread slot is used by a thread or was used by a thread which
336 has exited, then valgrind_stack_base points to the stack base. */
337 if (VG_(threads)[i].status == VgTs_Empty
338 && (!exited_threads || stack == 0)) continue;
339 VG_(printf)("\nThread %d: status = %s\n", i,
340 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
341 if (VG_(threads)[i].status != VgTs_Empty)
342 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
343 if (valgrind_stack_usage && stack != 0)
344 VG_(printf)("valgrind stack top usage: %ld of %ld\n",
345 VG_STACK_ACTIVE_SZB
philippe180a7502014-04-20 13:41:10 +0000346 - VG_(am_get_VgStack_unused_szB)(stack,
347 VG_STACK_ACTIVE_SZB),
philippe4f6f3362014-04-19 00:25:54 +0000348 (SizeT) VG_STACK_ACTIVE_SZB);
njn49b45ba2005-07-20 02:41:31 +0000349 }
350 VG_(printf)("\n");
351}
njnc7561b92005-06-19 01:24:32 +0000352
philippe4f6f3362014-04-19 00:25:54 +0000353void VG_(show_sched_status) ( Bool host_stacktrace,
354 Bool valgrind_stack_usage,
355 Bool exited_threads)
356{
357 show_sched_status_wrk (host_stacktrace,
358 valgrind_stack_usage,
359 exited_threads,
360 NULL);
361}
362
njn132bfcc2005-06-04 19:16:06 +0000363__attribute__ ((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000364static void report_and_quit ( const HChar* report,
sewardj59570ff2010-01-01 11:59:33 +0000365 UnwindStartRegs* startRegsIN )
njn132bfcc2005-06-04 19:16:06 +0000366{
philippe4f6f3362014-04-19 00:25:54 +0000367 show_sched_status_wrk (True, // host_stacktrace
368 False, // valgrind_stack_usage
369 False, // exited_threads
370 startRegsIN);
njnb8329f02009-04-16 00:33:20 +0000371 VG_(printf)(
372 "\n"
373 "Note: see also the FAQ in the source distribution.\n"
374 "It contains workarounds to several common problems.\n"
375 "In particular, if Valgrind aborted or crashed after\n"
376 "identifying problems in your program, there's a good chance\n"
377 "that fixing those problems will prevent Valgrind aborting or\n"
378 "crashing, especially if it happened in m_mallocfree.c.\n"
379 "\n"
380 "If that doesn't help, please report this bug to: %s\n\n"
381 "In the bug report, send all the above text, the valgrind\n"
382 "version, and what OS and version you are using. Thanks.\n\n",
383 report);
njn132bfcc2005-06-04 19:16:06 +0000384 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000385}
386
florianbbd9a212012-10-14 00:16:28 +0000387void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
388 Int line, const HChar* fn, const HChar* format, ... )
njn132bfcc2005-06-04 19:16:06 +0000389{
390 va_list vargs;
florian5869ded2013-01-29 04:25:45 +0000391 HChar buf[512];
florianbbd9a212012-10-14 00:16:28 +0000392 const HChar* component;
393 const HChar* bugs_to;
florian5869ded2013-01-29 04:25:45 +0000394 UInt written;
njn132bfcc2005-06-04 19:16:06 +0000395
396 static Bool entered = False;
397 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000398 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000399 entered = True;
400
401 va_start(vargs, format);
florian5869ded2013-01-29 04:25:45 +0000402 written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000403 va_end(vargs);
404
florian5869ded2013-01-29 04:25:45 +0000405 if (written >= sizeof(buf)) {
406 VG_(printf)("\nvalgrind: %s: buf is too small, sizeof(buf) = %u, "
407 "written = %d\n", __func__, (unsigned)sizeof(buf), written);
408 }
409
njn132bfcc2005-06-04 19:16:06 +0000410 if (isCore) {
411 component = "valgrind";
412 bugs_to = VG_BUGS_TO;
413 } else {
414 component = VG_(details).name;
415 bugs_to = VG_(details).bug_reports_to;
416 }
417
sewardjf349d552005-11-14 17:01:01 +0000418 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000419 VG_(printf_xml)("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000420
njn132bfcc2005-06-04 19:16:06 +0000421 // Treat vg_assert2(0, "foo") specially, as a panicky abort
422 if (VG_STREQ(expr, "0")) {
423 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000424 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000425 } else {
426 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
427 component, file, line, fn, expr );
428 }
429 if (!VG_STREQ(buf, ""))
430 VG_(printf)("%s: %s\n", component, buf );
431
sewardj59570ff2010-01-01 11:59:33 +0000432 report_and_quit(bugs_to, NULL);
njn132bfcc2005-06-04 19:16:06 +0000433}
434
435__attribute__ ((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000436static void panic ( const HChar* name, const HChar* report, const HChar* str,
sewardj59570ff2010-01-01 11:59:33 +0000437 UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000438{
sewardjf349d552005-11-14 17:01:01 +0000439 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000440 VG_(printf_xml)("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000441 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardj59570ff2010-01-01 11:59:33 +0000442 report_and_quit(report, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000443}
444
florianbbd9a212012-10-14 00:16:28 +0000445void VG_(core_panic_at) ( const HChar* str, UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000446{
sewardj59570ff2010-01-01 11:59:33 +0000447 panic("valgrind", VG_BUGS_TO, str, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000448}
449
florianbbd9a212012-10-14 00:16:28 +0000450void VG_(core_panic) ( const HChar* str )
njn132bfcc2005-06-04 19:16:06 +0000451{
sewardj59570ff2010-01-01 11:59:33 +0000452 VG_(core_panic_at)(str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000453}
454
florianbbd9a212012-10-14 00:16:28 +0000455void VG_(tool_panic) ( const HChar* str )
njn132bfcc2005-06-04 19:16:06 +0000456{
sewardj59570ff2010-01-01 11:59:33 +0000457 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000458}
459
njn49b45ba2005-07-20 02:41:31 +0000460/* Print some helpful-ish text about unimplemented things, and give up. */
florianbbd9a212012-10-14 00:16:28 +0000461void VG_(unimplemented) ( const HChar* msg )
njn132bfcc2005-06-04 19:16:06 +0000462{
sewardjf349d552005-11-14 17:01:01 +0000463 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000464 VG_(printf_xml)("</valgrindoutput>\n");
465 VG_(umsg)("\n");
466 VG_(umsg)("Valgrind detected that your program requires\n");
467 VG_(umsg)("the following unimplemented functionality:\n");
468 VG_(umsg)(" %s\n", msg);
469 VG_(umsg)("This may be because the functionality is hard to implement,\n");
470 VG_(umsg)("or because no reasonable program would behave this way,\n");
471 VG_(umsg)("or because nobody has yet needed it. "
472 "In any case, let us know at\n");
473 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
474 VG_BUGS_TO);
475 VG_(umsg)("\n");
476 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
477 VG_(umsg)("\n");
philippe4f6f3362014-04-19 00:25:54 +0000478 VG_(show_sched_status)(False, // host_stacktrace
479 False, // valgrind_stack_usage
480 False); // exited_threads
njn132bfcc2005-06-04 19:16:06 +0000481 VG_(exit)(1);
482}
483
njn132bfcc2005-06-04 19:16:06 +0000484/*--------------------------------------------------------------------*/
485/*--- end ---*/
486/*--------------------------------------------------------------------*/