blob: c38fe84548d1c252f78cd226dd4882c813774d1d [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
sewardj03f8d3f2012-08-05 15:46:46 +000010 Copyright (C) 2000-2012 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 }
sewardj6e9de462011-06-28 07:25:29 +000080#elif defined(VGP_ppc32_linux)
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 }
sewardj6e9de462011-06-28 07:25:29 +000099#elif defined(VGP_ppc64_linux)
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 }
sewardj5db15402012-06-07 09:13:21 +0000155#elif defined(VGP_mips32_linux)
156# define GET_STARTREGS(srP) \
157 { UInt pc, sp, fp, ra, gp; \
158 asm("move $8, $31;" /* t0 = ra */ \
159 "bal m_libcassert_get_ip;" /* ra = pc */ \
160 "m_libcassert_get_ip:\n" \
161 "move %0, $31;" \
162 "move $31, $8;" /* restore lr */ \
163 "move %1, $29;" \
164 "move %2, $30;" \
165 "move %3, $31;" \
166 "move %4, $28;" \
167 : "=r" (pc), \
168 "=r" (sp), \
169 "=r" (fp), \
170 "=r" (ra), \
171 "=r" (gp) \
172 : /* reads none */ \
173 : "$8" /* trashed */ ); \
174 (srP)->r_pc = (ULong)pc - 8; \
175 (srP)->r_sp = (ULong)sp; \
176 (srP)->misc.MIPS32.r30 = (ULong)fp; \
177 (srP)->misc.MIPS32.r31 = (ULong)ra; \
178 (srP)->misc.MIPS32.r28 = (ULong)gp; \
179 }
njn9450d242005-06-26 20:50:05 +0000180#else
181# error Unknown platform
182#endif
183
184#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +0000185
njnf39e9a32005-06-12 02:43:17 +0000186/* Pull down the entire world */
187void VG_(exit)( Int status )
188{
njn5b6b8fa2009-05-19 05:28:43 +0000189#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000190 (void)VG_(do_syscall1)(__NR_exit_group, status );
sewardj6e9de462011-06-28 07:25:29 +0000191#elif defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000192 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000193#else
194# error Unknown OS
195#endif
njnf39e9a32005-06-12 02:43:17 +0000196 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000197 // We really shouldn't reach here. Just in case we do, use some very crude
198 // methods to force abort
199 __builtin_trap();
200 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000201}
202
njnc7561b92005-06-19 01:24:32 +0000203// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000204void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000205{
206 Int i;
207 VG_(printf)("\nsched status:\n");
208 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
209 for (i = 1; i < VG_N_THREADS; i++) {
210 if (VG_(threads)[i].status == VgTs_Empty) continue;
211 VG_(printf)( "\nThread %d: status = %s\n", i,
212 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
213 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
214 }
215 VG_(printf)("\n");
216}
njnc7561b92005-06-19 01:24:32 +0000217
njn132bfcc2005-06-04 19:16:06 +0000218__attribute__ ((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000219static void report_and_quit ( const HChar* report,
sewardj59570ff2010-01-01 11:59:33 +0000220 UnwindStartRegs* startRegsIN )
njn132bfcc2005-06-04 19:16:06 +0000221{
njn49b45ba2005-07-20 02:41:31 +0000222 Addr stacktop;
223 Addr ips[BACKTRACE_DEPTH];
njn5f5ef2a2009-05-11 08:01:09 +0000224 Int n_ips;
sewardj42781722006-12-17 19:36:06 +0000225 ThreadState *tst
226 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000227
228 // If necessary, fake up an ExeContext which is of our actual real CPU
229 // state. Could cause problems if we got the panic/exception within the
230 // execontext/stack dump/symtab code. But it's better than nothing.
sewardj59570ff2010-01-01 11:59:33 +0000231 UnwindStartRegs startRegs;
232 VG_(memset)(&startRegs, 0, sizeof(startRegs));
233
234 if (startRegsIN == NULL) {
235 GET_STARTREGS(&startRegs);
236 } else {
237 startRegs = *startRegsIN;
njn49b45ba2005-07-20 02:41:31 +0000238 }
239
sewardj45f4e7c2005-09-27 19:20:21 +0000240 stacktop = tst->os_state.valgrind_stack_init_SP;
sewardj738856f2009-07-15 14:48:32 +0000241
242 n_ips =
njn5f5ef2a2009-05-11 08:01:09 +0000243 VG_(get_StackTrace_wrk)(
244 0/*tid is unknown*/,
245 ips, BACKTRACE_DEPTH,
246 NULL/*array to dump SP values in*/,
247 NULL/*array to dump FP values in*/,
sewardj59570ff2010-01-01 11:59:33 +0000248 &startRegs, stacktop
njn5f5ef2a2009-05-11 08:01:09 +0000249 );
sewardj738856f2009-07-15 14:48:32 +0000250 VG_(clo_xml) = False;
njn5f5ef2a2009-05-11 08:01:09 +0000251 VG_(pp_StackTrace) (ips, n_ips);
njn49b45ba2005-07-20 02:41:31 +0000252
sewardj745fc452006-10-17 02:03:11 +0000253 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000254 VG_(printf)(
255 "\n"
256 "Note: see also the FAQ in the source distribution.\n"
257 "It contains workarounds to several common problems.\n"
258 "In particular, if Valgrind aborted or crashed after\n"
259 "identifying problems in your program, there's a good chance\n"
260 "that fixing those problems will prevent Valgrind aborting or\n"
261 "crashing, especially if it happened in m_mallocfree.c.\n"
262 "\n"
263 "If that doesn't help, please report this bug to: %s\n\n"
264 "In the bug report, send all the above text, the valgrind\n"
265 "version, and what OS and version you are using. Thanks.\n\n",
266 report);
njn132bfcc2005-06-04 19:16:06 +0000267 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000268}
269
florianbbd9a212012-10-14 00:16:28 +0000270void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
271 Int line, const HChar* fn, const HChar* format, ... )
njn132bfcc2005-06-04 19:16:06 +0000272{
273 va_list vargs;
florian5869ded2013-01-29 04:25:45 +0000274 HChar buf[512];
florianbbd9a212012-10-14 00:16:28 +0000275 const HChar* component;
276 const HChar* bugs_to;
florian5869ded2013-01-29 04:25:45 +0000277 UInt written;
njn132bfcc2005-06-04 19:16:06 +0000278
279 static Bool entered = False;
280 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000281 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000282 entered = True;
283
284 va_start(vargs, format);
florian5869ded2013-01-29 04:25:45 +0000285 written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000286 va_end(vargs);
287
florian5869ded2013-01-29 04:25:45 +0000288 if (written >= sizeof(buf)) {
289 VG_(printf)("\nvalgrind: %s: buf is too small, sizeof(buf) = %u, "
290 "written = %d\n", __func__, (unsigned)sizeof(buf), written);
291 }
292
njn132bfcc2005-06-04 19:16:06 +0000293 if (isCore) {
294 component = "valgrind";
295 bugs_to = VG_BUGS_TO;
296 } else {
297 component = VG_(details).name;
298 bugs_to = VG_(details).bug_reports_to;
299 }
300
sewardjf349d552005-11-14 17:01:01 +0000301 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000302 VG_(printf_xml)("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000303
njn132bfcc2005-06-04 19:16:06 +0000304 // Treat vg_assert2(0, "foo") specially, as a panicky abort
305 if (VG_STREQ(expr, "0")) {
306 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000307 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000308 } else {
309 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
310 component, file, line, fn, expr );
311 }
312 if (!VG_STREQ(buf, ""))
313 VG_(printf)("%s: %s\n", component, buf );
314
sewardj59570ff2010-01-01 11:59:33 +0000315 report_and_quit(bugs_to, NULL);
njn132bfcc2005-06-04 19:16:06 +0000316}
317
318__attribute__ ((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000319static void panic ( const HChar* name, const HChar* report, const HChar* str,
sewardj59570ff2010-01-01 11:59:33 +0000320 UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000321{
sewardjf349d552005-11-14 17:01:01 +0000322 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000323 VG_(printf_xml)("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000324 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardj59570ff2010-01-01 11:59:33 +0000325 report_and_quit(report, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000326}
327
florianbbd9a212012-10-14 00:16:28 +0000328void VG_(core_panic_at) ( const HChar* str, UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000329{
sewardj59570ff2010-01-01 11:59:33 +0000330 panic("valgrind", VG_BUGS_TO, str, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000331}
332
florianbbd9a212012-10-14 00:16:28 +0000333void VG_(core_panic) ( const HChar* str )
njn132bfcc2005-06-04 19:16:06 +0000334{
sewardj59570ff2010-01-01 11:59:33 +0000335 VG_(core_panic_at)(str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000336}
337
florianbbd9a212012-10-14 00:16:28 +0000338void VG_(tool_panic) ( const HChar* str )
njn132bfcc2005-06-04 19:16:06 +0000339{
sewardj59570ff2010-01-01 11:59:33 +0000340 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000341}
342
njn49b45ba2005-07-20 02:41:31 +0000343/* Print some helpful-ish text about unimplemented things, and give up. */
florianbbd9a212012-10-14 00:16:28 +0000344void VG_(unimplemented) ( const HChar* msg )
njn132bfcc2005-06-04 19:16:06 +0000345{
sewardjf349d552005-11-14 17:01:01 +0000346 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000347 VG_(printf_xml)("</valgrindoutput>\n");
348 VG_(umsg)("\n");
349 VG_(umsg)("Valgrind detected that your program requires\n");
350 VG_(umsg)("the following unimplemented functionality:\n");
351 VG_(umsg)(" %s\n", msg);
352 VG_(umsg)("This may be because the functionality is hard to implement,\n");
353 VG_(umsg)("or because no reasonable program would behave this way,\n");
354 VG_(umsg)("or because nobody has yet needed it. "
355 "In any case, let us know at\n");
356 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
357 VG_BUGS_TO);
358 VG_(umsg)("\n");
359 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
360 VG_(umsg)("\n");
sewardj745fc452006-10-17 02:03:11 +0000361 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000362 VG_(exit)(1);
363}
364
njn132bfcc2005-06-04 19:16:06 +0000365/*--------------------------------------------------------------------*/
366/*--- end ---*/
367/*--------------------------------------------------------------------*/