2 /*--------------------------------------------------------------------*/
3 /*--- Assertions and panics. m_libcassert.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2013 Julian Seward
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_vkiscnums.h"
34 #include "pub_core_libcsetjmp.h" // to keep threadstate.h happy
35 #include "pub_core_threadstate.h"
36 #include "pub_core_gdbserver.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_libcbase.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_libcproc.h" // For VG_(gettid)()
42 #include "pub_core_machine.h"
43 #include "pub_core_stacks.h"
44 #include "pub_core_stacktrace.h"
45 #include "pub_core_syscall.h"
46 #include "pub_core_tooliface.h" // For VG_(details).{name,bug_reports_to}
47 #include "pub_core_options.h" // For VG_(clo_xml)
49 /* ---------------------------------------------------------------------
51 ------------------------------------------------------------------ */
53 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
54 # define GET_STARTREGS(srP) \
55 { UInt eip, esp, ebp; \
56 __asm__ __volatile__( \
61 : "=r" (eip), "=r" (esp), "=r" (ebp) \
65 (srP)->r_pc = (ULong)eip; \
66 (srP)->r_sp = (ULong)esp; \
67 (srP)->misc.X86.r_ebp = ebp; \
69 #elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
70 # define GET_STARTREGS(srP) \
71 { ULong rip, rsp, rbp; \
72 __asm__ __volatile__( \
73 "leaq 0(%%rip), %0;" \
76 : "=r" (rip), "=r" (rsp), "=r" (rbp) \
82 (srP)->misc.AMD64.r_rbp = rbp; \
84 #elif defined(VGP_ppc32_linux)
85 # define GET_STARTREGS(srP) \
87 __asm__ __volatile__( \
88 "mflr 0;" /* r0 = lr */ \
89 "bl m_libcassert_get_ip;" /* lr = pc */ \
90 "m_libcassert_get_ip:\n" \
91 "mflr %0;" /* %0 = pc */ \
92 "mtlr 0;" /* restore lr */ \
93 "mr %1,1;" /* %1 = r1 */ \
94 "mr %2,0;" /* %2 = lr */ \
95 : "=r" (cia), "=r" (r1), "=r" (lr) \
97 : "r0" /* trashed */ \
99 (srP)->r_pc = (ULong)cia; \
100 (srP)->r_sp = (ULong)r1; \
101 (srP)->misc.PPC32.r_lr = lr; \
103 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
104 # define GET_STARTREGS(srP) \
105 { ULong cia, r1, lr; \
106 __asm__ __volatile__( \
107 "mflr 0;" /* r0 = lr */ \
108 "bl .m_libcassert_get_ip;" /* lr = pc */ \
109 ".m_libcassert_get_ip:\n" \
110 "mflr %0;" /* %0 = pc */ \
111 "mtlr 0;" /* restore lr */ \
112 "mr %1,1;" /* %1 = r1 */ \
113 "mr %2,0;" /* %2 = lr */ \
114 : "=r" (cia), "=r" (r1), "=r" (lr) \
116 : "r0" /* trashed */ \
120 (srP)->misc.PPC64.r_lr = lr; \
122 #elif defined(VGP_arm_linux)
123 # define GET_STARTREGS(srP) \
125 __asm__ __volatile__( \
126 "str r15, [%0, #+0];" \
127 "str r14, [%0, #+4];" \
128 "str r13, [%0, #+8];" \
129 "str r12, [%0, #+12];" \
130 "str r11, [%0, #+16];" \
131 "str r7, [%0, #+20];" \
133 : /* in */ "r"(&block[0]) \
134 : /* trash */ "memory" \
136 (srP)->r_pc = block[0] - 8; \
137 (srP)->misc.ARM.r14 = block[1]; \
138 (srP)->r_sp = block[2]; \
139 (srP)->misc.ARM.r12 = block[3]; \
140 (srP)->misc.ARM.r11 = block[4]; \
141 (srP)->misc.ARM.r7 = block[5]; \
143 #elif defined(VGP_arm64_linux)
144 # define GET_STARTREGS(srP) \
146 __asm__ __volatile__( \
148 "str x19, [%0, #+0];" /* pc */ \
150 "str x19, [%0, #+8];" /* sp */ \
151 "str x29, [%0, #+16];" /* fp */ \
152 "str x30, [%0, #+24];" /* lr */ \
154 : /* in */ "r"(&block[0]) \
155 : /* trash */ "memory","x19" \
157 (srP)->r_pc = block[0]; \
158 (srP)->r_sp = block[1]; \
159 (srP)->misc.ARM64.x29 = block[2]; \
160 (srP)->misc.ARM64.x30 = block[3]; \
162 #elif defined(VGP_s390x_linux)
163 # define GET_STARTREGS(srP) \
164 { ULong ia, sp, fp, lr; \
165 __asm__ __volatile__( \
170 : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr) \
171 /* no read & clobber */ \
175 (srP)->misc.S390X.r_fp = fp; \
176 (srP)->misc.S390X.r_lr = lr; \
178 #elif defined(VGP_mips32_linux)
179 # define GET_STARTREGS(srP) \
180 { UInt pc, sp, fp, ra, gp; \
181 asm("move $8, $31;" /* t0 = ra */ \
182 "bal m_libcassert_get_ip;" /* ra = pc */ \
183 "m_libcassert_get_ip:\n" \
185 "move $31, $8;" /* restore lr */ \
196 : "$8" /* trashed */ ); \
197 (srP)->r_pc = (ULong)pc - 8; \
198 (srP)->r_sp = (ULong)sp; \
199 (srP)->misc.MIPS32.r30 = (ULong)fp; \
200 (srP)->misc.MIPS32.r31 = (ULong)ra; \
201 (srP)->misc.MIPS32.r28 = (ULong)gp; \
203 #elif defined(VGP_mips64_linux)
204 # define GET_STARTREGS(srP) \
205 { ULong pc, sp, fp, ra, gp; \
206 asm("move $8, $31;" /* t0 = ra */ \
207 "bal m_libcassert_get_ip;" /* ra = pc */ \
208 "m_libcassert_get_ip:\n" \
210 "move $31, $8;" /* restore lr */ \
221 : "$8" /* trashed */ ); \
222 (srP)->r_pc = (ULong)pc - 8; \
223 (srP)->r_sp = (ULong)sp; \
224 (srP)->misc.MIPS64.r30 = (ULong)fp; \
225 (srP)->misc.MIPS64.r31 = (ULong)ra; \
226 (srP)->misc.MIPS64.r28 = (ULong)gp; \
229 # error Unknown platform
232 #define BACKTRACE_DEPTH 100 // nice and deep!
234 __attribute__ ((__noreturn__
))
235 static void exit_wrk( Int status
, Bool gdbserver_call_allowed
)
237 static Bool exit_called
= False
;
238 // avoid recursive exit during gdbserver call.
240 if (gdbserver_call_allowed
&& !exit_called
) {
241 const ThreadId atid
= 1; // Arbitrary tid used to call/terminate gdbsrv.
243 if (status
!= 0 && VG_(gdbserver_stop_at
) (VgdbStopAt_ValgrindAbExit
)) {
244 if (VG_(gdbserver_init_done
)()) {
245 VG_(umsg
)("(action at valgrind abnormal exit) vgdb me ... \n");
246 VG_(gdbserver
) (atid
);
248 VG_(umsg
)("(action at valgrind abnormal exit) "
249 "Early valgrind exit : vgdb not yet usable\n");
252 if (VG_(gdbserver_init_done
)()) {
253 // Always terminate the gdbserver when Valgrind exits, so as
254 // to e.g. cleanup the FIFOs.
255 VG_(gdbserver_exit
) (atid
,
256 status
== 0 ? VgSrc_ExitProcess
: VgSrc_FatalSig
);
261 VG_(exit_now
) (status
);
264 /* Call the appropriate system call and nothing else. This function should
265 be called in places where the dependencies of VG_(exit) need to be
267 __attribute__ ((__noreturn__
))
268 void VG_(exit_now
)( Int status
)
270 #if defined(VGO_linux)
271 (void)VG_(do_syscall1
)(__NR_exit_group
, status
);
272 #elif defined(VGO_darwin)
273 (void)VG_(do_syscall1
)(__NR_exit
, status
);
278 // We really shouldn't reach here. Just in case we do, use some very crude
279 // methods to force abort
281 *(volatile Int
*)0 = 'x';
284 /* Pull down the entire world */
285 void VG_(exit
)( Int status
)
287 exit_wrk (status
, True
);
290 /* Pull down the entire world */
291 void VG_(client_exit
)( Int status
)
293 exit_wrk (status
, False
);
297 // Print the scheduler status.
298 static void show_sched_status_wrk ( Bool host_stacktrace
,
301 const UnwindStartRegs
* startRegsIN
)
304 if (host_stacktrace
) {
305 const Bool save_clo_xml
= VG_(clo_xml
);
307 Addr ips
[BACKTRACE_DEPTH
];
310 = VG_(get_ThreadState
)( VG_(lwpid_to_vgtid
)( VG_(gettid
)() ) );
312 // If necessary, fake up an ExeContext which is of our actual real CPU
313 // state. Could cause problems if we got the panic/exception within the
314 // execontext/stack dump/symtab code. But it's better than nothing.
315 UnwindStartRegs startRegs
;
316 VG_(memset
)(&startRegs
, 0, sizeof(startRegs
));
318 if (startRegsIN
== NULL
) {
319 GET_STARTREGS(&startRegs
);
321 startRegs
= *startRegsIN
;
324 stacktop
= tst
->os_state
.valgrind_stack_init_SP
;
327 VG_(get_StackTrace_wrk
)(
329 ips
, BACKTRACE_DEPTH
,
330 NULL
/*array to dump SP values in*/,
331 NULL
/*array to dump FP values in*/,
334 VG_(printf
)("\nhost stacktrace:\n");
335 VG_(clo_xml
) = False
;
336 VG_(pp_StackTrace
) (ips
, n_ips
);
337 VG_(clo_xml
) = save_clo_xml
;
340 VG_(printf
)("\nsched status:\n");
341 VG_(printf
)(" running_tid=%d\n", VG_(get_running_tid
)());
342 for (i
= 1; i
< VG_N_THREADS
; i
++) {
344 = (VgStack
*)VG_(threads
)[i
].os_state
.valgrind_stack_base
;
345 /* If a thread slot was never used (yet), valgrind_stack_base is 0.
346 If a thread slot is used by a thread or was used by a thread which
347 has exited, then valgrind_stack_base points to the stack base. */
348 if (VG_(threads
)[i
].status
== VgTs_Empty
349 && (!exited_threads
|| stack
== 0)) continue;
350 VG_(printf
)("\nThread %d: status = %s\n", i
,
351 VG_(name_of_ThreadStatus
)(VG_(threads
)[i
].status
) );
352 if (VG_(threads
)[i
].status
!= VgTs_Empty
)
353 VG_(get_and_pp_StackTrace
)( i
, BACKTRACE_DEPTH
);
354 if (stack_usage
&& VG_(threads
)[i
].client_stack_highest_byte
!= 0 ) {
358 VG_(stack_limits
)(VG_(threads
)[i
].client_stack_highest_byte
,
361 VG_(printf
)("client stack range: [%p %p] client SP: %p\n",
362 (void*)start
, (void*)end
, (void*)VG_(get_SP
)(i
));
364 VG_(printf
)("client stack range: ???????\n");
366 if (stack_usage
&& stack
!= 0)
367 VG_(printf
)("valgrind stack top usage: %ld of %ld\n",
369 - VG_(am_get_VgStack_unused_szB
)(stack
,
370 VG_STACK_ACTIVE_SZB
),
371 (SizeT
) VG_STACK_ACTIVE_SZB
);
376 void VG_(show_sched_status
) ( Bool host_stacktrace
,
380 show_sched_status_wrk (host_stacktrace
,
386 __attribute__ ((noreturn
))
387 static void report_and_quit ( const HChar
* report
,
388 const UnwindStartRegs
* startRegsIN
)
390 show_sched_status_wrk (True
, // host_stacktrace
391 False
, // stack_usage
392 False
, // exited_threads
396 "Note: see also the FAQ in the source distribution.\n"
397 "It contains workarounds to several common problems.\n"
398 "In particular, if Valgrind aborted or crashed after\n"
399 "identifying problems in your program, there's a good chance\n"
400 "that fixing those problems will prevent Valgrind aborting or\n"
401 "crashing, especially if it happened in m_mallocfree.c.\n"
403 "If that doesn't help, please report this bug to: %s\n\n"
404 "In the bug report, send all the above text, the valgrind\n"
405 "version, and what OS and version you are using. Thanks.\n\n",
410 void VG_(assert_fail
) ( Bool isCore
, const HChar
* expr
, const HChar
* file
,
411 Int line
, const HChar
* fn
, const HChar
* format
, ... )
413 va_list vargs
, vargs_copy
;
414 const HChar
* component
;
415 const HChar
* bugs_to
;
418 static Bool entered
= False
;
424 component
= "valgrind";
425 bugs_to
= VG_BUGS_TO
;
427 component
= VG_(details
).name
;
428 bugs_to
= VG_(details
).bug_reports_to
;
432 VG_(printf_xml
)("</valgrindoutput>\n");
434 // Treat vg_assert2(0, "foo") specially, as a panicky abort
435 if (VG_STREQ(expr
, "0")) {
436 VG_(printf
)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
437 component
, file
, line
, fn
);
439 VG_(printf
)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
440 component
, file
, line
, fn
, expr
);
443 /* Check whether anything will be written */
445 va_start(vargs
, format
);
446 va_copy(vargs_copy
, vargs
);
447 written
= VG_(vsnprintf
) ( buf
, sizeof(buf
), format
, vargs
);
451 VG_(printf
)("%s: ", component
);
452 VG_(vprintf
)(format
, vargs_copy
);
456 report_and_quit(bugs_to
, NULL
);
459 __attribute__ ((noreturn
))
460 static void panic ( const HChar
* name
, const HChar
* report
, const HChar
* str
,
461 const UnwindStartRegs
* startRegs
)
464 VG_(printf_xml
)("</valgrindoutput>\n");
465 VG_(printf
)("\n%s: the 'impossible' happened:\n %s\n", name
, str
);
466 report_and_quit(report
, startRegs
);
469 void VG_(core_panic_at
) ( const HChar
* str
, const UnwindStartRegs
* startRegs
)
471 panic("valgrind", VG_BUGS_TO
, str
, startRegs
);
474 void VG_(core_panic
) ( const HChar
* str
)
476 VG_(core_panic_at
)(str
, NULL
);
479 void VG_(tool_panic
) ( const HChar
* str
)
481 panic(VG_(details
).name
, VG_(details
).bug_reports_to
, str
, NULL
);
484 /* Print some helpful-ish text about unimplemented things, and give up. */
485 void VG_(unimplemented
) ( const HChar
* msg
)
488 VG_(printf_xml
)("</valgrindoutput>\n");
490 VG_(umsg
)("Valgrind detected that your program requires\n");
491 VG_(umsg
)("the following unimplemented functionality:\n");
492 VG_(umsg
)(" %s\n", msg
);
493 VG_(umsg
)("This may be because the functionality is hard to implement,\n");
494 VG_(umsg
)("or because no reasonable program would behave this way,\n");
495 VG_(umsg
)("or because nobody has yet needed it. "
496 "In any case, let us know at\n");
497 VG_(umsg
)("%s and/or try to work around the problem, if you can.\n",
500 VG_(umsg
)("Valgrind has to exit now. Sorry. Bye!\n");
502 VG_(show_sched_status
)(False
, // host_stacktrace
503 False
, // stack_usage
504 False
); // exited_threads
508 /*--------------------------------------------------------------------*/
510 /*--------------------------------------------------------------------*/