2 /*--------------------------------------------------------------------*/
3 /*--- Assertions and panics. m_libcassert.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2010 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_libcbase.h"
37 #include "pub_core_libcassert.h"
38 #include "pub_core_libcprint.h"
39 #include "pub_core_libcproc.h" // For VG_(gettid)()
40 #include "pub_core_stacktrace.h"
41 #include "pub_core_syscall.h"
42 #include "pub_core_tooliface.h" // For VG_(details).{name,bug_reports_to}
43 #include "pub_core_options.h" // For VG_(clo_xml)
45 /* ---------------------------------------------------------------------
47 ------------------------------------------------------------------ */
49 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) || defined(VGP_x86_l4re)
50 # define GET_STARTREGS(srP) \
51 { UInt eip, esp, ebp; \
52 __asm__ __volatile__( \
57 : "=r" (eip), "=r" (esp), "=r" (ebp) \
61 (srP)->r_pc = (ULong)eip; \
62 (srP)->r_sp = (ULong)esp; \
63 (srP)->misc.X86.r_ebp = ebp; \
65 #elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
66 # define GET_STARTREGS(srP) \
67 { ULong rip, rsp, rbp; \
68 __asm__ __volatile__( \
69 "leaq 0(%%rip), %0;" \
72 : "=r" (rip), "=r" (rsp), "=r" (rbp) \
78 (srP)->misc.AMD64.r_rbp = rbp; \
80 #elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5)
81 # define GET_STARTREGS(srP) \
83 __asm__ __volatile__( \
84 "mflr 0;" /* r0 = lr */ \
85 "bl m_libcassert_get_ip;" /* lr = pc */ \
86 "m_libcassert_get_ip:\n" \
87 "mflr %0;" /* %0 = pc */ \
88 "mtlr 0;" /* restore lr */ \
89 "mr %1,1;" /* %1 = r1 */ \
90 "mr %2,0;" /* %2 = lr */ \
91 : "=r" (cia), "=r" (r1), "=r" (lr) \
93 : "r0" /* trashed */ \
95 (srP)->r_pc = (ULong)cia; \
96 (srP)->r_sp = (ULong)r1; \
97 (srP)->misc.PPC32.r_lr = lr; \
99 #elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
100 # define GET_STARTREGS(srP) \
101 { ULong cia, r1, lr; \
102 __asm__ __volatile__( \
103 "mflr 0;" /* r0 = lr */ \
104 "bl .m_libcassert_get_ip;" /* lr = pc */ \
105 ".m_libcassert_get_ip:\n" \
106 "mflr %0;" /* %0 = pc */ \
107 "mtlr 0;" /* restore lr */ \
108 "mr %1,1;" /* %1 = r1 */ \
109 "mr %2,0;" /* %2 = lr */ \
110 : "=r" (cia), "=r" (r1), "=r" (lr) \
112 : "r0" /* trashed */ \
116 (srP)->misc.PPC64.r_lr = lr; \
118 #elif defined(VGP_arm_linux)
119 # define GET_STARTREGS(srP) \
121 __asm__ __volatile__( \
122 "str r15, [%0, #+0];" \
123 "str r14, [%0, #+4];" \
124 "str r13, [%0, #+8];" \
125 "str r12, [%0, #+12];" \
126 "str r11, [%0, #+16];" \
127 "str r7, [%0, #+20];" \
129 : /* in */ "r"(&block[0]) \
130 : /* trash */ "memory" \
132 (srP)->r_pc = block[0] - 8; \
133 (srP)->r_sp = block[1]; \
134 (srP)->misc.ARM.r14 = block[2]; \
135 (srP)->misc.ARM.r12 = block[3]; \
136 (srP)->misc.ARM.r11 = block[4]; \
137 (srP)->misc.ARM.r7 = block[5]; \
139 #elif defined(VGP_s390x_linux)
140 # define GET_STARTREGS(srP) \
141 { ULong ia, sp, fp, lr; \
142 __asm__ __volatile__( \
147 : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr) \
148 /* no read & clobber */ \
152 (srP)->misc.S390X.r_fp = fp; \
153 (srP)->misc.S390X.r_lr = lr; \
156 # error Unknown platform
159 #define BACKTRACE_DEPTH 100 // nice and deep!
161 /* Pull down the entire world */
162 void VG_(exit)( Int status )
164 #if defined(VGO_linux)
165 (void)VG_(do_syscall1)(__NR_exit_group, status );
166 #elif defined(VGO_aix5) || defined(VGO_darwin)
167 (void)VG_(do_syscall1)(__NR_exit, status );
168 #elif defined(VGO_l4re)
169 VG_(printf)("Valgrind exitting. Status = %lx\n", status);
170 enter_kdebug("VG_(exit)");
176 // We really shouldn't reach here. Just in case we do, use some very crude
177 // methods to force abort
179 *(volatile Int*)0 = 'x';
182 // Print the scheduler status.
183 void VG_(show_sched_status) ( void )
186 VG_(printf)("\nsched status:\n");
187 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
188 for (i = 1; i < VG_N_THREADS; i++) {
189 if (VG_(threads)[i].status == VgTs_Empty) continue;
190 VG_(printf)( "\nThread %d: status = %s\n", i,
191 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
192 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
197 __attribute__ ((noreturn))
198 static void report_and_quit ( const Char* report,
199 UnwindStartRegs* startRegsIN )
202 Addr ips[BACKTRACE_DEPTH];
205 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
207 // If necessary, fake up an ExeContext which is of our actual real CPU
208 // state. Could cause problems if we got the panic/exception within the
209 // execontext/stack dump/symtab code. But it's better than nothing.
210 UnwindStartRegs startRegs;
211 VG_(memset)(&startRegs, 0, sizeof(startRegs));
213 if (startRegsIN == NULL) {
214 GET_STARTREGS(&startRegs);
216 startRegs = *startRegsIN;
219 stacktop = tst->os_state.valgrind_stack_init_SP;
222 VG_(get_StackTrace_wrk)(
224 ips, BACKTRACE_DEPTH,
225 NULL/*array to dump SP values in*/,
226 NULL/*array to dump FP values in*/,
229 VG_(clo_xml) = False;
230 VG_(pp_StackTrace) (ips, n_ips);
232 VG_(show_sched_status)();
235 "Note: see also the FAQ in the source distribution.\n"
236 "It contains workarounds to several common problems.\n"
237 "In particular, if Valgrind aborted or crashed after\n"
238 "identifying problems in your program, there's a good chance\n"
239 "that fixing those problems will prevent Valgrind aborting or\n"
240 "crashing, especially if it happened in m_mallocfree.c.\n"
242 "If that doesn't help, please report this bug to: %s\n\n"
243 "In the bug report, send all the above text, the valgrind\n"
244 "version, and what OS and version you are using. Thanks.\n\n",
249 void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
250 Int line, const Char* fn, const HChar* format, ... )
257 static Bool entered = False;
262 va_start(vargs, format);
263 VG_(vsprintf) ( buf, format, vargs );
267 component = "valgrind";
268 bugs_to = VG_BUGS_TO;
270 component = VG_(details).name;
271 bugs_to = VG_(details).bug_reports_to;
275 VG_(printf_xml)("</valgrindoutput>\n");
277 // Treat vg_assert2(0, "foo") specially, as a panicky abort
278 if (VG_STREQ(expr, "0")) {
279 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
280 component, file, line, fn );
282 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
283 component, file, line, fn, expr );
285 if (!VG_STREQ(buf, ""))
286 VG_(printf)("%s: %s\n", component, buf );
288 report_and_quit(bugs_to, NULL);
291 __attribute__ ((noreturn))
292 static void panic ( Char* name, Char* report, Char* str,
293 UnwindStartRegs* startRegs )
296 VG_(printf_xml)("</valgrindoutput>\n");
297 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
298 report_and_quit(report, startRegs);
301 void VG_(core_panic_at) ( Char* str, UnwindStartRegs* startRegs )
303 panic("valgrind", VG_BUGS_TO, str, startRegs);
306 void VG_(core_panic) ( Char* str )
308 VG_(core_panic_at)(str, NULL);
311 void VG_(tool_panic) ( Char* str )
313 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
316 /* Print some helpful-ish text about unimplemented things, and give up. */
317 void VG_(unimplemented) ( Char* msg )
320 VG_(printf_xml)("</valgrindoutput>\n");
322 VG_(umsg)("Valgrind detected that your program requires\n");
323 VG_(umsg)("the following unimplemented functionality:\n");
324 VG_(umsg)(" %s\n", msg);
325 VG_(umsg)("This may be because the functionality is hard to implement,\n");
326 VG_(umsg)("or because no reasonable program would behave this way,\n");
327 VG_(umsg)("or because nobody has yet needed it. "
328 "In any case, let us know at\n");
329 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
332 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
334 VG_(show_sched_status)();
338 /*--------------------------------------------------------------------*/
340 /*--------------------------------------------------------------------*/