blob: 49c5ad634314e466ea423c730dffcf1342ffee67 [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
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2000-2010 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"
njn132bfcc2005-06-04 19:16:06 +000036#include "pub_core_libcbase.h"
37#include "pub_core_libcassert.h"
38#include "pub_core_libcprint.h"
njn49b45ba2005-07-20 02:41:31 +000039#include "pub_core_libcproc.h" // For VG_(gettid)()
40#include "pub_core_stacktrace.h"
njn9abd6082005-06-17 21:31:45 +000041#include "pub_core_syscall.h"
njne070c202005-06-20 23:58:15 +000042#include "pub_core_tooliface.h" // For VG_(details).{name,bug_reports_to}
sewardjf349d552005-11-14 17:01:01 +000043#include "pub_core_options.h" // For VG_(clo_xml)
njn132bfcc2005-06-04 19:16:06 +000044
45/* ---------------------------------------------------------------------
46 Assertery.
47 ------------------------------------------------------------------ */
48
sewardj59570ff2010-01-01 11:59:33 +000049#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
50# define GET_STARTREGS(srP) \
51 { UInt eip, esp, ebp; \
52 __asm__ __volatile__( \
53 "call 0f;" \
54 "0: popl %0;" \
55 "movl %%esp, %1;" \
56 "movl %%ebp, %2;" \
57 : "=r" (eip), "=r" (esp), "=r" (ebp) \
58 : /* reads none */ \
59 : "memory" \
60 ); \
61 (srP)->r_pc = (ULong)eip; \
62 (srP)->r_sp = (ULong)esp; \
63 (srP)->misc.X86.r_ebp = ebp; \
64 }
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;" \
70 "movq %%rsp, %1;" \
71 "movq %%rbp, %2;" \
72 : "=r" (rip), "=r" (rsp), "=r" (rbp) \
73 : /* reads none */ \
74 : "memory" \
75 ); \
76 (srP)->r_pc = rip; \
77 (srP)->r_sp = rsp; \
78 (srP)->misc.AMD64.r_rbp = rbp; \
79 }
sewardj745fc452006-10-17 02:03:11 +000080#elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5)
sewardj59570ff2010-01-01 11:59:33 +000081# define GET_STARTREGS(srP) \
82 { UInt cia, r1, lr; \
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) \
92 : /* reads none */ \
93 : "r0" /* trashed */ \
94 ); \
sewardjf5f1e122010-01-02 13:24:58 +000095 (srP)->r_pc = (ULong)cia; \
96 (srP)->r_sp = (ULong)r1; \
97 (srP)->misc.PPC32.r_lr = lr; \
sewardj59570ff2010-01-01 11:59:33 +000098 }
sewardj745fc452006-10-17 02:03:11 +000099#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
sewardj59570ff2010-01-01 11:59:33 +0000100# 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) \
111 : /* reads none */ \
112 : "r0" /* trashed */ \
113 ); \
sewardjf5f1e122010-01-02 13:24:58 +0000114 (srP)->r_pc = cia; \
115 (srP)->r_sp = r1; \
116 (srP)->misc.PPC64.r_lr = lr; \
sewardj59570ff2010-01-01 11:59:33 +0000117 }
118#elif defined(VGP_arm_linux)
119# define GET_STARTREGS(srP) \
sewardjfa5ce562010-09-23 22:05:59 +0000120 { UInt block[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000121 __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];" \
sewardjfa5ce562010-09-23 22:05:59 +0000127 "str r7, [%0, #+20];" \
sewardj59570ff2010-01-01 11:59:33 +0000128 : /* out */ \
129 : /* in */ "r"(&block[0]) \
130 : /* trash */ "memory" \
131 ); \
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]; \
sewardjfa5ce562010-09-23 22:05:59 +0000137 (srP)->misc.ARM.r7 = block[5]; \
sewardj59570ff2010-01-01 11:59:33 +0000138 }
sewardjb5b87402011-03-07 16:05:35 +0000139#elif defined(VGP_s390x_linux)
140# define GET_STARTREGS(srP) \
141 { ULong ia, sp, fp, lr; \
142 __asm__ __volatile__( \
143 "bras %0,0f;" \
144 "0: lgr %1,15;" \
145 "lgr %2,11;" \
146 "lgr %3,14;" \
147 : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr) \
148 /* no read & clobber */ \
149 ); \
150 (srP)->r_pc = ia; \
151 (srP)->r_sp = sp; \
152 (srP)->misc.S390X.r_fp = fp; \
153 (srP)->misc.S390X.r_lr = lr; \
154 }
njn9450d242005-06-26 20:50:05 +0000155#else
156# error Unknown platform
157#endif
158
159#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +0000160
njnf39e9a32005-06-12 02:43:17 +0000161/* Pull down the entire world */
162void VG_(exit)( Int status )
163{
njn5b6b8fa2009-05-19 05:28:43 +0000164#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000165 (void)VG_(do_syscall1)(__NR_exit_group, status );
njnf76d27a2009-05-28 01:53:07 +0000166#elif defined(VGO_aix5) || defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000167 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000168#else
169# error Unknown OS
170#endif
njnf39e9a32005-06-12 02:43:17 +0000171 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000172 // We really shouldn't reach here. Just in case we do, use some very crude
173 // methods to force abort
174 __builtin_trap();
175 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000176}
177
njnc7561b92005-06-19 01:24:32 +0000178// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000179void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000180{
181 Int i;
182 VG_(printf)("\nsched status:\n");
183 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
184 for (i = 1; i < VG_N_THREADS; i++) {
185 if (VG_(threads)[i].status == VgTs_Empty) continue;
186 VG_(printf)( "\nThread %d: status = %s\n", i,
187 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
188 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
189 }
190 VG_(printf)("\n");
191}
njnc7561b92005-06-19 01:24:32 +0000192
njn132bfcc2005-06-04 19:16:06 +0000193__attribute__ ((noreturn))
sewardj59570ff2010-01-01 11:59:33 +0000194static void report_and_quit ( const Char* report,
195 UnwindStartRegs* startRegsIN )
njn132bfcc2005-06-04 19:16:06 +0000196{
njn49b45ba2005-07-20 02:41:31 +0000197 Addr stacktop;
198 Addr ips[BACKTRACE_DEPTH];
njn5f5ef2a2009-05-11 08:01:09 +0000199 Int n_ips;
sewardj42781722006-12-17 19:36:06 +0000200 ThreadState *tst
201 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000202
203 // If necessary, fake up an ExeContext which is of our actual real CPU
204 // state. Could cause problems if we got the panic/exception within the
205 // execontext/stack dump/symtab code. But it's better than nothing.
sewardj59570ff2010-01-01 11:59:33 +0000206 UnwindStartRegs startRegs;
207 VG_(memset)(&startRegs, 0, sizeof(startRegs));
208
209 if (startRegsIN == NULL) {
210 GET_STARTREGS(&startRegs);
211 } else {
212 startRegs = *startRegsIN;
njn49b45ba2005-07-20 02:41:31 +0000213 }
214
sewardj45f4e7c2005-09-27 19:20:21 +0000215 stacktop = tst->os_state.valgrind_stack_init_SP;
sewardj738856f2009-07-15 14:48:32 +0000216
217 n_ips =
njn5f5ef2a2009-05-11 08:01:09 +0000218 VG_(get_StackTrace_wrk)(
219 0/*tid is unknown*/,
220 ips, BACKTRACE_DEPTH,
221 NULL/*array to dump SP values in*/,
222 NULL/*array to dump FP values in*/,
sewardj59570ff2010-01-01 11:59:33 +0000223 &startRegs, stacktop
njn5f5ef2a2009-05-11 08:01:09 +0000224 );
sewardj738856f2009-07-15 14:48:32 +0000225 VG_(clo_xml) = False;
njn5f5ef2a2009-05-11 08:01:09 +0000226 VG_(pp_StackTrace) (ips, n_ips);
njn49b45ba2005-07-20 02:41:31 +0000227
sewardj745fc452006-10-17 02:03:11 +0000228 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000229 VG_(printf)(
230 "\n"
231 "Note: see also the FAQ in the source distribution.\n"
232 "It contains workarounds to several common problems.\n"
233 "In particular, if Valgrind aborted or crashed after\n"
234 "identifying problems in your program, there's a good chance\n"
235 "that fixing those problems will prevent Valgrind aborting or\n"
236 "crashing, especially if it happened in m_mallocfree.c.\n"
237 "\n"
238 "If that doesn't help, please report this bug to: %s\n\n"
239 "In the bug report, send all the above text, the valgrind\n"
240 "version, and what OS and version you are using. Thanks.\n\n",
241 report);
njn132bfcc2005-06-04 19:16:06 +0000242 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000243}
244
245void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
246 Int line, const Char* fn, const HChar* format, ... )
247{
248 va_list vargs;
249 Char buf[256];
njn132bfcc2005-06-04 19:16:06 +0000250 Char* component;
251 Char* bugs_to;
252
253 static Bool entered = False;
254 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000255 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000256 entered = True;
257
258 va_start(vargs, format);
njnaba25b42005-06-21 04:26:24 +0000259 VG_(vsprintf) ( buf, format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000260 va_end(vargs);
261
262 if (isCore) {
263 component = "valgrind";
264 bugs_to = VG_BUGS_TO;
265 } else {
266 component = VG_(details).name;
267 bugs_to = VG_(details).bug_reports_to;
268 }
269
sewardjf349d552005-11-14 17:01:01 +0000270 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000271 VG_(printf_xml)("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000272
njn132bfcc2005-06-04 19:16:06 +0000273 // Treat vg_assert2(0, "foo") specially, as a panicky abort
274 if (VG_STREQ(expr, "0")) {
275 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000276 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000277 } else {
278 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
279 component, file, line, fn, expr );
280 }
281 if (!VG_STREQ(buf, ""))
282 VG_(printf)("%s: %s\n", component, buf );
283
sewardj59570ff2010-01-01 11:59:33 +0000284 report_and_quit(bugs_to, NULL);
njn132bfcc2005-06-04 19:16:06 +0000285}
286
287__attribute__ ((noreturn))
288static void panic ( Char* name, Char* report, Char* str,
sewardj59570ff2010-01-01 11:59:33 +0000289 UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000290{
sewardjf349d552005-11-14 17:01:01 +0000291 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000292 VG_(printf_xml)("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000293 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardj59570ff2010-01-01 11:59:33 +0000294 report_and_quit(report, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000295}
296
sewardj59570ff2010-01-01 11:59:33 +0000297void VG_(core_panic_at) ( Char* str, UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000298{
sewardj59570ff2010-01-01 11:59:33 +0000299 panic("valgrind", VG_BUGS_TO, str, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000300}
301
302void VG_(core_panic) ( Char* str )
303{
sewardj59570ff2010-01-01 11:59:33 +0000304 VG_(core_panic_at)(str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000305}
306
307void VG_(tool_panic) ( Char* str )
308{
sewardj59570ff2010-01-01 11:59:33 +0000309 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000310}
311
njn49b45ba2005-07-20 02:41:31 +0000312/* Print some helpful-ish text about unimplemented things, and give up. */
njn132bfcc2005-06-04 19:16:06 +0000313void VG_(unimplemented) ( Char* msg )
314{
sewardjf349d552005-11-14 17:01:01 +0000315 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000316 VG_(printf_xml)("</valgrindoutput>\n");
317 VG_(umsg)("\n");
318 VG_(umsg)("Valgrind detected that your program requires\n");
319 VG_(umsg)("the following unimplemented functionality:\n");
320 VG_(umsg)(" %s\n", msg);
321 VG_(umsg)("This may be because the functionality is hard to implement,\n");
322 VG_(umsg)("or because no reasonable program would behave this way,\n");
323 VG_(umsg)("or because nobody has yet needed it. "
324 "In any case, let us know at\n");
325 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
326 VG_BUGS_TO);
327 VG_(umsg)("\n");
328 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
329 VG_(umsg)("\n");
sewardj745fc452006-10-17 02:03:11 +0000330 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000331 VG_(exit)(1);
332}
333
njn132bfcc2005-06-04 19:16:06 +0000334/*--------------------------------------------------------------------*/
335/*--- end ---*/
336/*--------------------------------------------------------------------*/
337