blob: e88afb018873a200ef07a953487dc162f5e5fdd3 [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"
philippe4f6f3362014-04-19 00:25:54 +000036#include "pub_core_aspacemgr.h"
njn132bfcc2005-06-04 19:16:06 +000037#include "pub_core_libcbase.h"
38#include "pub_core_libcassert.h"
39#include "pub_core_libcprint.h"
njn49b45ba2005-07-20 02:41:31 +000040#include "pub_core_libcproc.h" // For VG_(gettid)()
41#include "pub_core_stacktrace.h"
njn9abd6082005-06-17 21:31:45 +000042#include "pub_core_syscall.h"
njne070c202005-06-20 23:58:15 +000043#include "pub_core_tooliface.h" // For VG_(details).{name,bug_reports_to}
sewardjf349d552005-11-14 17:01:01 +000044#include "pub_core_options.h" // For VG_(clo_xml)
njn132bfcc2005-06-04 19:16:06 +000045
46/* ---------------------------------------------------------------------
47 Assertery.
48 ------------------------------------------------------------------ */
49
sewardj59570ff2010-01-01 11:59:33 +000050#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
51# define GET_STARTREGS(srP) \
52 { UInt eip, esp, ebp; \
53 __asm__ __volatile__( \
54 "call 0f;" \
55 "0: popl %0;" \
56 "movl %%esp, %1;" \
57 "movl %%ebp, %2;" \
58 : "=r" (eip), "=r" (esp), "=r" (ebp) \
59 : /* reads none */ \
60 : "memory" \
61 ); \
62 (srP)->r_pc = (ULong)eip; \
63 (srP)->r_sp = (ULong)esp; \
64 (srP)->misc.X86.r_ebp = ebp; \
65 }
66#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
67# define GET_STARTREGS(srP) \
68 { ULong rip, rsp, rbp; \
69 __asm__ __volatile__( \
70 "leaq 0(%%rip), %0;" \
71 "movq %%rsp, %1;" \
72 "movq %%rbp, %2;" \
73 : "=r" (rip), "=r" (rsp), "=r" (rbp) \
74 : /* reads none */ \
75 : "memory" \
76 ); \
77 (srP)->r_pc = rip; \
78 (srP)->r_sp = rsp; \
79 (srP)->misc.AMD64.r_rbp = rbp; \
80 }
sewardj6e9de462011-06-28 07:25:29 +000081#elif defined(VGP_ppc32_linux)
sewardj59570ff2010-01-01 11:59:33 +000082# define GET_STARTREGS(srP) \
83 { UInt cia, r1, lr; \
84 __asm__ __volatile__( \
85 "mflr 0;" /* r0 = lr */ \
86 "bl m_libcassert_get_ip;" /* lr = pc */ \
87 "m_libcassert_get_ip:\n" \
88 "mflr %0;" /* %0 = pc */ \
89 "mtlr 0;" /* restore lr */ \
90 "mr %1,1;" /* %1 = r1 */ \
91 "mr %2,0;" /* %2 = lr */ \
92 : "=r" (cia), "=r" (r1), "=r" (lr) \
93 : /* reads none */ \
94 : "r0" /* trashed */ \
95 ); \
sewardjf5f1e122010-01-02 13:24:58 +000096 (srP)->r_pc = (ULong)cia; \
97 (srP)->r_sp = (ULong)r1; \
98 (srP)->misc.PPC32.r_lr = lr; \
sewardj59570ff2010-01-01 11:59:33 +000099 }
sewardj6e9de462011-06-28 07:25:29 +0000100#elif defined(VGP_ppc64_linux)
sewardj59570ff2010-01-01 11:59:33 +0000101# define GET_STARTREGS(srP) \
102 { ULong cia, r1, lr; \
103 __asm__ __volatile__( \
104 "mflr 0;" /* r0 = lr */ \
105 "bl .m_libcassert_get_ip;" /* lr = pc */ \
106 ".m_libcassert_get_ip:\n" \
107 "mflr %0;" /* %0 = pc */ \
108 "mtlr 0;" /* restore lr */ \
109 "mr %1,1;" /* %1 = r1 */ \
110 "mr %2,0;" /* %2 = lr */ \
111 : "=r" (cia), "=r" (r1), "=r" (lr) \
112 : /* reads none */ \
113 : "r0" /* trashed */ \
114 ); \
sewardjf5f1e122010-01-02 13:24:58 +0000115 (srP)->r_pc = cia; \
116 (srP)->r_sp = r1; \
117 (srP)->misc.PPC64.r_lr = lr; \
sewardj59570ff2010-01-01 11:59:33 +0000118 }
119#elif defined(VGP_arm_linux)
120# define GET_STARTREGS(srP) \
sewardjfa5ce562010-09-23 22:05:59 +0000121 { UInt block[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000122 __asm__ __volatile__( \
123 "str r15, [%0, #+0];" \
124 "str r14, [%0, #+4];" \
125 "str r13, [%0, #+8];" \
126 "str r12, [%0, #+12];" \
127 "str r11, [%0, #+16];" \
sewardjfa5ce562010-09-23 22:05:59 +0000128 "str r7, [%0, #+20];" \
sewardj59570ff2010-01-01 11:59:33 +0000129 : /* out */ \
130 : /* in */ "r"(&block[0]) \
131 : /* trash */ "memory" \
132 ); \
133 (srP)->r_pc = block[0] - 8; \
134 (srP)->r_sp = block[1]; \
135 (srP)->misc.ARM.r14 = block[2]; \
136 (srP)->misc.ARM.r12 = block[3]; \
137 (srP)->misc.ARM.r11 = block[4]; \
sewardjfa5ce562010-09-23 22:05:59 +0000138 (srP)->misc.ARM.r7 = block[5]; \
sewardj59570ff2010-01-01 11:59:33 +0000139 }
sewardjf0c12502014-01-12 12:54:00 +0000140#elif defined(VGP_arm64_linux)
141# define GET_STARTREGS(srP) \
142 { ULong block[4]; \
143 __asm__ __volatile__( \
144 "adr x19, 0;" \
145 "str x19, [%0, #+0];" /* pc */ \
146 "mov x19, sp;" \
147 "str x19, [%0, #+8];" /* sp */ \
148 "str x29, [%0, #+16];" /* fp */ \
149 "str x30, [%0, #+24];" /* lr */ \
150 : /* out */ \
151 : /* in */ "r"(&block[0]) \
152 : /* trash */ "memory","x19" \
153 ); \
154 (srP)->r_pc = block[0]; \
155 (srP)->r_sp = block[1]; \
156 (srP)->misc.ARM64.x29 = block[2]; \
157 (srP)->misc.ARM64.x30 = block[3]; \
158 }
sewardjb5b87402011-03-07 16:05:35 +0000159#elif defined(VGP_s390x_linux)
160# define GET_STARTREGS(srP) \
161 { ULong ia, sp, fp, lr; \
162 __asm__ __volatile__( \
163 "bras %0,0f;" \
164 "0: lgr %1,15;" \
165 "lgr %2,11;" \
166 "lgr %3,14;" \
167 : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr) \
168 /* no read & clobber */ \
169 ); \
170 (srP)->r_pc = ia; \
171 (srP)->r_sp = sp; \
172 (srP)->misc.S390X.r_fp = fp; \
173 (srP)->misc.S390X.r_lr = lr; \
174 }
sewardj5db15402012-06-07 09:13:21 +0000175#elif defined(VGP_mips32_linux)
176# define GET_STARTREGS(srP) \
177 { UInt pc, sp, fp, ra, gp; \
178 asm("move $8, $31;" /* t0 = ra */ \
179 "bal m_libcassert_get_ip;" /* ra = pc */ \
180 "m_libcassert_get_ip:\n" \
181 "move %0, $31;" \
182 "move $31, $8;" /* restore lr */ \
183 "move %1, $29;" \
184 "move %2, $30;" \
185 "move %3, $31;" \
186 "move %4, $28;" \
187 : "=r" (pc), \
188 "=r" (sp), \
189 "=r" (fp), \
190 "=r" (ra), \
191 "=r" (gp) \
192 : /* reads none */ \
193 : "$8" /* trashed */ ); \
194 (srP)->r_pc = (ULong)pc - 8; \
195 (srP)->r_sp = (ULong)sp; \
196 (srP)->misc.MIPS32.r30 = (ULong)fp; \
197 (srP)->misc.MIPS32.r31 = (ULong)ra; \
198 (srP)->misc.MIPS32.r28 = (ULong)gp; \
199 }
petarj4df0bfc2013-02-27 23:17:33 +0000200#elif defined(VGP_mips64_linux)
201# define GET_STARTREGS(srP) \
202 { ULong pc, sp, fp, ra, gp; \
203 asm("move $8, $31;" /* t0 = ra */ \
204 "bal m_libcassert_get_ip;" /* ra = pc */ \
205 "m_libcassert_get_ip:\n" \
206 "move %0, $31;" \
207 "move $31, $8;" /* restore lr */ \
208 "move %1, $29;" \
209 "move %2, $30;" \
210 "move %3, $31;" \
211 "move %4, $28;" \
212 : "=r" (pc), \
213 "=r" (sp), \
214 "=r" (fp), \
215 "=r" (ra), \
216 "=r" (gp) \
217 : /* reads none */ \
218 : "$8" /* trashed */ ); \
219 (srP)->r_pc = (ULong)pc - 8; \
220 (srP)->r_sp = (ULong)sp; \
221 (srP)->misc.MIPS64.r30 = (ULong)fp; \
222 (srP)->misc.MIPS64.r31 = (ULong)ra; \
223 (srP)->misc.MIPS64.r28 = (ULong)gp; \
224 }
njn9450d242005-06-26 20:50:05 +0000225#else
226# error Unknown platform
227#endif
228
229#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +0000230
njnf39e9a32005-06-12 02:43:17 +0000231/* Pull down the entire world */
232void VG_(exit)( Int status )
233{
njn5b6b8fa2009-05-19 05:28:43 +0000234#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000235 (void)VG_(do_syscall1)(__NR_exit_group, status );
sewardj6e9de462011-06-28 07:25:29 +0000236#elif defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000237 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000238#else
239# error Unknown OS
240#endif
njnf39e9a32005-06-12 02:43:17 +0000241 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000242 // We really shouldn't reach here. Just in case we do, use some very crude
243 // methods to force abort
244 __builtin_trap();
245 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000246}
247
njnc7561b92005-06-19 01:24:32 +0000248// Print the scheduler status.
philippe4f6f3362014-04-19 00:25:54 +0000249static void show_sched_status_wrk ( Bool host_stacktrace,
250 Bool valgrind_stack_usage,
251 Bool exited_threads,
252 UnwindStartRegs* startRegsIN)
njn49b45ba2005-07-20 02:41:31 +0000253{
254 Int i;
philippe4f6f3362014-04-19 00:25:54 +0000255 if (host_stacktrace) {
256 const Bool save_clo_xml = VG_(clo_xml);
257 Addr stacktop;
258 Addr ips[BACKTRACE_DEPTH];
259 Int n_ips;
260 ThreadState *tst
261 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
262
263 // If necessary, fake up an ExeContext which is of our actual real CPU
264 // state. Could cause problems if we got the panic/exception within the
265 // execontext/stack dump/symtab code. But it's better than nothing.
266 UnwindStartRegs startRegs;
267 VG_(memset)(&startRegs, 0, sizeof(startRegs));
268
269 if (startRegsIN == NULL) {
270 GET_STARTREGS(&startRegs);
271 } else {
272 startRegs = *startRegsIN;
273 }
274
275 stacktop = tst->os_state.valgrind_stack_init_SP;
276
277 n_ips =
278 VG_(get_StackTrace_wrk)(
279 0/*tid is unknown*/,
280 ips, BACKTRACE_DEPTH,
281 NULL/*array to dump SP values in*/,
282 NULL/*array to dump FP values in*/,
283 &startRegs, stacktop
284 );
285 VG_(printf)("\nhost stacktrace:\n");
286 VG_(clo_xml) = False;
287 VG_(pp_StackTrace) (ips, n_ips);
288 VG_(clo_xml) = save_clo_xml;
289 }
290
njn49b45ba2005-07-20 02:41:31 +0000291 VG_(printf)("\nsched status:\n");
292 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
293 for (i = 1; i < VG_N_THREADS; i++) {
philippe4f6f3362014-04-19 00:25:54 +0000294 VgStack* stack
295 = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
296 /* If a thread slot was never used (yet), valgrind_stack_base is 0.
297 If a thread slot is used by a thread or was used by a thread which
298 has exited, then valgrind_stack_base points to the stack base. */
299 if (VG_(threads)[i].status == VgTs_Empty
300 && (!exited_threads || stack == 0)) continue;
301 VG_(printf)("\nThread %d: status = %s\n", i,
302 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
303 if (VG_(threads)[i].status != VgTs_Empty)
304 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
305 if (valgrind_stack_usage && stack != 0)
306 VG_(printf)("valgrind stack top usage: %ld of %ld\n",
307 VG_STACK_ACTIVE_SZB
308 - VG_(am_get_VgStack_unused_szB)(stack, VG_STACK_ACTIVE_SZB),
309 (SizeT) VG_STACK_ACTIVE_SZB);
njn49b45ba2005-07-20 02:41:31 +0000310 }
311 VG_(printf)("\n");
312}
njnc7561b92005-06-19 01:24:32 +0000313
philippe4f6f3362014-04-19 00:25:54 +0000314void VG_(show_sched_status) ( Bool host_stacktrace,
315 Bool valgrind_stack_usage,
316 Bool exited_threads)
317{
318 show_sched_status_wrk (host_stacktrace,
319 valgrind_stack_usage,
320 exited_threads,
321 NULL);
322}
323
njn132bfcc2005-06-04 19:16:06 +0000324__attribute__ ((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000325static void report_and_quit ( const HChar* report,
sewardj59570ff2010-01-01 11:59:33 +0000326 UnwindStartRegs* startRegsIN )
njn132bfcc2005-06-04 19:16:06 +0000327{
philippe4f6f3362014-04-19 00:25:54 +0000328 show_sched_status_wrk (True, // host_stacktrace
329 False, // valgrind_stack_usage
330 False, // exited_threads
331 startRegsIN);
njnb8329f02009-04-16 00:33:20 +0000332 VG_(printf)(
333 "\n"
334 "Note: see also the FAQ in the source distribution.\n"
335 "It contains workarounds to several common problems.\n"
336 "In particular, if Valgrind aborted or crashed after\n"
337 "identifying problems in your program, there's a good chance\n"
338 "that fixing those problems will prevent Valgrind aborting or\n"
339 "crashing, especially if it happened in m_mallocfree.c.\n"
340 "\n"
341 "If that doesn't help, please report this bug to: %s\n\n"
342 "In the bug report, send all the above text, the valgrind\n"
343 "version, and what OS and version you are using. Thanks.\n\n",
344 report);
njn132bfcc2005-06-04 19:16:06 +0000345 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000346}
347
florianbbd9a212012-10-14 00:16:28 +0000348void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
349 Int line, const HChar* fn, const HChar* format, ... )
njn132bfcc2005-06-04 19:16:06 +0000350{
351 va_list vargs;
florian5869ded2013-01-29 04:25:45 +0000352 HChar buf[512];
florianbbd9a212012-10-14 00:16:28 +0000353 const HChar* component;
354 const HChar* bugs_to;
florian5869ded2013-01-29 04:25:45 +0000355 UInt written;
njn132bfcc2005-06-04 19:16:06 +0000356
357 static Bool entered = False;
358 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000359 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000360 entered = True;
361
362 va_start(vargs, format);
florian5869ded2013-01-29 04:25:45 +0000363 written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000364 va_end(vargs);
365
florian5869ded2013-01-29 04:25:45 +0000366 if (written >= sizeof(buf)) {
367 VG_(printf)("\nvalgrind: %s: buf is too small, sizeof(buf) = %u, "
368 "written = %d\n", __func__, (unsigned)sizeof(buf), written);
369 }
370
njn132bfcc2005-06-04 19:16:06 +0000371 if (isCore) {
372 component = "valgrind";
373 bugs_to = VG_BUGS_TO;
374 } else {
375 component = VG_(details).name;
376 bugs_to = VG_(details).bug_reports_to;
377 }
378
sewardjf349d552005-11-14 17:01:01 +0000379 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000380 VG_(printf_xml)("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000381
njn132bfcc2005-06-04 19:16:06 +0000382 // Treat vg_assert2(0, "foo") specially, as a panicky abort
383 if (VG_STREQ(expr, "0")) {
384 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000385 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000386 } else {
387 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
388 component, file, line, fn, expr );
389 }
390 if (!VG_STREQ(buf, ""))
391 VG_(printf)("%s: %s\n", component, buf );
392
sewardj59570ff2010-01-01 11:59:33 +0000393 report_and_quit(bugs_to, NULL);
njn132bfcc2005-06-04 19:16:06 +0000394}
395
396__attribute__ ((noreturn))
florianbbd9a212012-10-14 00:16:28 +0000397static void panic ( const HChar* name, const HChar* report, const HChar* str,
sewardj59570ff2010-01-01 11:59:33 +0000398 UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000399{
sewardjf349d552005-11-14 17:01:01 +0000400 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000401 VG_(printf_xml)("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000402 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardj59570ff2010-01-01 11:59:33 +0000403 report_and_quit(report, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000404}
405
florianbbd9a212012-10-14 00:16:28 +0000406void VG_(core_panic_at) ( const HChar* str, UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000407{
sewardj59570ff2010-01-01 11:59:33 +0000408 panic("valgrind", VG_BUGS_TO, str, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000409}
410
florianbbd9a212012-10-14 00:16:28 +0000411void VG_(core_panic) ( const HChar* str )
njn132bfcc2005-06-04 19:16:06 +0000412{
sewardj59570ff2010-01-01 11:59:33 +0000413 VG_(core_panic_at)(str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000414}
415
florianbbd9a212012-10-14 00:16:28 +0000416void VG_(tool_panic) ( const HChar* str )
njn132bfcc2005-06-04 19:16:06 +0000417{
sewardj59570ff2010-01-01 11:59:33 +0000418 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000419}
420
njn49b45ba2005-07-20 02:41:31 +0000421/* Print some helpful-ish text about unimplemented things, and give up. */
florianbbd9a212012-10-14 00:16:28 +0000422void VG_(unimplemented) ( const HChar* msg )
njn132bfcc2005-06-04 19:16:06 +0000423{
sewardjf349d552005-11-14 17:01:01 +0000424 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000425 VG_(printf_xml)("</valgrindoutput>\n");
426 VG_(umsg)("\n");
427 VG_(umsg)("Valgrind detected that your program requires\n");
428 VG_(umsg)("the following unimplemented functionality:\n");
429 VG_(umsg)(" %s\n", msg);
430 VG_(umsg)("This may be because the functionality is hard to implement,\n");
431 VG_(umsg)("or because no reasonable program would behave this way,\n");
432 VG_(umsg)("or because nobody has yet needed it. "
433 "In any case, let us know at\n");
434 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
435 VG_BUGS_TO);
436 VG_(umsg)("\n");
437 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
438 VG_(umsg)("\n");
philippe4f6f3362014-04-19 00:25:54 +0000439 VG_(show_sched_status)(False, // host_stacktrace
440 False, // valgrind_stack_usage
441 False); // exited_threads
njn132bfcc2005-06-04 19:16:06 +0000442 VG_(exit)(1);
443}
444
njn132bfcc2005-06-04 19:16:06 +0000445/*--------------------------------------------------------------------*/
446/*--- end ---*/
447/*--------------------------------------------------------------------*/