blob: d7706dec8a7dfe8659b709dc2ccee72774f4d4f9 [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"
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 }
petarj4df0bfc2013-02-27 23:17:33 +0000180#elif defined(VGP_mips64_linux)
181# define GET_STARTREGS(srP) \
182 { ULong pc, sp, fp, ra, gp; \
183 asm("move $8, $31;" /* t0 = ra */ \
184 "bal m_libcassert_get_ip;" /* ra = pc */ \
185 "m_libcassert_get_ip:\n" \
186 "move %0, $31;" \
187 "move $31, $8;" /* restore lr */ \
188 "move %1, $29;" \
189 "move %2, $30;" \
190 "move %3, $31;" \
191 "move %4, $28;" \
192 : "=r" (pc), \
193 "=r" (sp), \
194 "=r" (fp), \
195 "=r" (ra), \
196 "=r" (gp) \
197 : /* reads none */ \
198 : "$8" /* trashed */ ); \
199 (srP)->r_pc = (ULong)pc - 8; \
200 (srP)->r_sp = (ULong)sp; \
201 (srP)->misc.MIPS64.r30 = (ULong)fp; \
202 (srP)->misc.MIPS64.r31 = (ULong)ra; \
203 (srP)->misc.MIPS64.r28 = (ULong)gp; \
204 }
njn9450d242005-06-26 20:50:05 +0000205#else
206# error Unknown platform
207#endif
208
209#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +0000210
njnf39e9a32005-06-12 02:43:17 +0000211/* Pull down the entire world */
212void VG_(exit)( Int status )
213{
njn5b6b8fa2009-05-19 05:28:43 +0000214#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000215 (void)VG_(do_syscall1)(__NR_exit_group, status );
sewardj6e9de462011-06-28 07:25:29 +0000216#elif defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000217 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000218#else
219# error Unknown OS
220#endif
njnf39e9a32005-06-12 02:43:17 +0000221 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000222 // We really shouldn't reach here. Just in case we do, use some very crude
223 // methods to force abort
224 __builtin_trap();
225 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000226}
227
njnc7561b92005-06-19 01:24:32 +0000228// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000229void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000230{
231 Int i;
232 VG_(printf)("\nsched status:\n");
233 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
234 for (i = 1; i < VG_N_THREADS; i++) {
235 if (VG_(threads)[i].status == VgTs_Empty) continue;
236 VG_(printf)( "\nThread %d: status = %s\n", i,
237 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
238 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
239 }
240 VG_(printf)("\n");
241}
njnc7561b92005-06-19 01:24:32 +0000242
njn132bfcc2005-06-04 19:16:06 +0000243__attribute__ ((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000244static void report_and_quit ( const HChar* report,
sewardj59570ff2010-01-01 11:59:33 +0000245 UnwindStartRegs* startRegsIN )
njn132bfcc2005-06-04 19:16:06 +0000246{
njn49b45ba2005-07-20 02:41:31 +0000247 Addr stacktop;
248 Addr ips[BACKTRACE_DEPTH];
njn5f5ef2a2009-05-11 08:01:09 +0000249 Int n_ips;
sewardj42781722006-12-17 19:36:06 +0000250 ThreadState *tst
251 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000252
253 // If necessary, fake up an ExeContext which is of our actual real CPU
254 // state. Could cause problems if we got the panic/exception within the
255 // execontext/stack dump/symtab code. But it's better than nothing.
sewardj59570ff2010-01-01 11:59:33 +0000256 UnwindStartRegs startRegs;
257 VG_(memset)(&startRegs, 0, sizeof(startRegs));
258
259 if (startRegsIN == NULL) {
260 GET_STARTREGS(&startRegs);
261 } else {
262 startRegs = *startRegsIN;
njn49b45ba2005-07-20 02:41:31 +0000263 }
264
sewardj45f4e7c2005-09-27 19:20:21 +0000265 stacktop = tst->os_state.valgrind_stack_init_SP;
sewardj738856f2009-07-15 14:48:32 +0000266
267 n_ips =
njn5f5ef2a2009-05-11 08:01:09 +0000268 VG_(get_StackTrace_wrk)(
269 0/*tid is unknown*/,
270 ips, BACKTRACE_DEPTH,
271 NULL/*array to dump SP values in*/,
272 NULL/*array to dump FP values in*/,
sewardj59570ff2010-01-01 11:59:33 +0000273 &startRegs, stacktop
njn5f5ef2a2009-05-11 08:01:09 +0000274 );
sewardj738856f2009-07-15 14:48:32 +0000275 VG_(clo_xml) = False;
njn5f5ef2a2009-05-11 08:01:09 +0000276 VG_(pp_StackTrace) (ips, n_ips);
njn49b45ba2005-07-20 02:41:31 +0000277
sewardj745fc452006-10-17 02:03:11 +0000278 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000279 VG_(printf)(
280 "\n"
281 "Note: see also the FAQ in the source distribution.\n"
282 "It contains workarounds to several common problems.\n"
283 "In particular, if Valgrind aborted or crashed after\n"
284 "identifying problems in your program, there's a good chance\n"
285 "that fixing those problems will prevent Valgrind aborting or\n"
286 "crashing, especially if it happened in m_mallocfree.c.\n"
287 "\n"
288 "If that doesn't help, please report this bug to: %s\n\n"
289 "In the bug report, send all the above text, the valgrind\n"
290 "version, and what OS and version you are using. Thanks.\n\n",
291 report);
njn132bfcc2005-06-04 19:16:06 +0000292 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000293}
294
florianbbd9a212012-10-14 00:16:28 +0000295void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
296 Int line, const HChar* fn, const HChar* format, ... )
njn132bfcc2005-06-04 19:16:06 +0000297{
298 va_list vargs;
florian5869ded2013-01-29 04:25:45 +0000299 HChar buf[512];
florianbbd9a212012-10-14 00:16:28 +0000300 const HChar* component;
301 const HChar* bugs_to;
florian5869ded2013-01-29 04:25:45 +0000302 UInt written;
njn132bfcc2005-06-04 19:16:06 +0000303
304 static Bool entered = False;
305 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000306 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000307 entered = True;
308
309 va_start(vargs, format);
florian5869ded2013-01-29 04:25:45 +0000310 written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000311 va_end(vargs);
312
florian5869ded2013-01-29 04:25:45 +0000313 if (written >= sizeof(buf)) {
314 VG_(printf)("\nvalgrind: %s: buf is too small, sizeof(buf) = %u, "
315 "written = %d\n", __func__, (unsigned)sizeof(buf), written);
316 }
317
njn132bfcc2005-06-04 19:16:06 +0000318 if (isCore) {
319 component = "valgrind";
320 bugs_to = VG_BUGS_TO;
321 } else {
322 component = VG_(details).name;
323 bugs_to = VG_(details).bug_reports_to;
324 }
325
sewardjf349d552005-11-14 17:01:01 +0000326 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000327 VG_(printf_xml)("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000328
njn132bfcc2005-06-04 19:16:06 +0000329 // Treat vg_assert2(0, "foo") specially, as a panicky abort
330 if (VG_STREQ(expr, "0")) {
331 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000332 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000333 } else {
334 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
335 component, file, line, fn, expr );
336 }
337 if (!VG_STREQ(buf, ""))
338 VG_(printf)("%s: %s\n", component, buf );
339
sewardj59570ff2010-01-01 11:59:33 +0000340 report_and_quit(bugs_to, NULL);
njn132bfcc2005-06-04 19:16:06 +0000341}
342
343__attribute__ ((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000344static void panic ( const HChar* name, const HChar* report, const HChar* str,
sewardj59570ff2010-01-01 11:59:33 +0000345 UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000346{
sewardjf349d552005-11-14 17:01:01 +0000347 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000348 VG_(printf_xml)("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000349 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardj59570ff2010-01-01 11:59:33 +0000350 report_and_quit(report, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000351}
352
florianbbd9a212012-10-14 00:16:28 +0000353void VG_(core_panic_at) ( const HChar* str, UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000354{
sewardj59570ff2010-01-01 11:59:33 +0000355 panic("valgrind", VG_BUGS_TO, str, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000356}
357
florianbbd9a212012-10-14 00:16:28 +0000358void VG_(core_panic) ( const HChar* str )
njn132bfcc2005-06-04 19:16:06 +0000359{
sewardj59570ff2010-01-01 11:59:33 +0000360 VG_(core_panic_at)(str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000361}
362
florianbbd9a212012-10-14 00:16:28 +0000363void VG_(tool_panic) ( const HChar* str )
njn132bfcc2005-06-04 19:16:06 +0000364{
sewardj59570ff2010-01-01 11:59:33 +0000365 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000366}
367
njn49b45ba2005-07-20 02:41:31 +0000368/* Print some helpful-ish text about unimplemented things, and give up. */
florianbbd9a212012-10-14 00:16:28 +0000369void VG_(unimplemented) ( const HChar* msg )
njn132bfcc2005-06-04 19:16:06 +0000370{
sewardjf349d552005-11-14 17:01:01 +0000371 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000372 VG_(printf_xml)("</valgrindoutput>\n");
373 VG_(umsg)("\n");
374 VG_(umsg)("Valgrind detected that your program requires\n");
375 VG_(umsg)("the following unimplemented functionality:\n");
376 VG_(umsg)(" %s\n", msg);
377 VG_(umsg)("This may be because the functionality is hard to implement,\n");
378 VG_(umsg)("or because no reasonable program would behave this way,\n");
379 VG_(umsg)("or because nobody has yet needed it. "
380 "In any case, let us know at\n");
381 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
382 VG_BUGS_TO);
383 VG_(umsg)("\n");
384 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
385 VG_(umsg)("\n");
sewardj745fc452006-10-17 02:03:11 +0000386 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000387 VG_(exit)(1);
388}
389
njn132bfcc2005-06-04 19:16:06 +0000390/*--------------------------------------------------------------------*/
391/*--- end ---*/
392/*--------------------------------------------------------------------*/