blob: 63e3f1cd7d86c74b009459b46000da315f80e5e1 [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"
njn49b45ba2005-07-20 02:41:31 +000034#include "pub_core_threadstate.h"
njn132bfcc2005-06-04 19:16:06 +000035#include "pub_core_libcbase.h"
36#include "pub_core_libcassert.h"
37#include "pub_core_libcprint.h"
njn49b45ba2005-07-20 02:41:31 +000038#include "pub_core_libcproc.h" // For VG_(gettid)()
39#include "pub_core_stacktrace.h"
njn9abd6082005-06-17 21:31:45 +000040#include "pub_core_syscall.h"
njne070c202005-06-20 23:58:15 +000041#include "pub_core_tooliface.h" // For VG_(details).{name,bug_reports_to}
sewardjf349d552005-11-14 17:01:01 +000042#include "pub_core_options.h" // For VG_(clo_xml)
njn132bfcc2005-06-04 19:16:06 +000043
44/* ---------------------------------------------------------------------
45 Assertery.
46 ------------------------------------------------------------------ */
47
sewardj59570ff2010-01-01 11:59:33 +000048#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
49# define GET_STARTREGS(srP) \
50 { UInt eip, esp, ebp; \
51 __asm__ __volatile__( \
52 "call 0f;" \
53 "0: popl %0;" \
54 "movl %%esp, %1;" \
55 "movl %%ebp, %2;" \
56 : "=r" (eip), "=r" (esp), "=r" (ebp) \
57 : /* reads none */ \
58 : "memory" \
59 ); \
60 (srP)->r_pc = (ULong)eip; \
61 (srP)->r_sp = (ULong)esp; \
62 (srP)->misc.X86.r_ebp = ebp; \
63 }
64#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
65# define GET_STARTREGS(srP) \
66 { ULong rip, rsp, rbp; \
67 __asm__ __volatile__( \
68 "leaq 0(%%rip), %0;" \
69 "movq %%rsp, %1;" \
70 "movq %%rbp, %2;" \
71 : "=r" (rip), "=r" (rsp), "=r" (rbp) \
72 : /* reads none */ \
73 : "memory" \
74 ); \
75 (srP)->r_pc = rip; \
76 (srP)->r_sp = rsp; \
77 (srP)->misc.AMD64.r_rbp = rbp; \
78 }
sewardj745fc452006-10-17 02:03:11 +000079#elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5)
sewardj59570ff2010-01-01 11:59:33 +000080# define GET_STARTREGS(srP) \
81 { UInt cia, r1, lr; \
82 __asm__ __volatile__( \
83 "mflr 0;" /* r0 = lr */ \
84 "bl m_libcassert_get_ip;" /* lr = pc */ \
85 "m_libcassert_get_ip:\n" \
86 "mflr %0;" /* %0 = pc */ \
87 "mtlr 0;" /* restore lr */ \
88 "mr %1,1;" /* %1 = r1 */ \
89 "mr %2,0;" /* %2 = lr */ \
90 : "=r" (cia), "=r" (r1), "=r" (lr) \
91 : /* reads none */ \
92 : "r0" /* trashed */ \
93 ); \
sewardjf5f1e122010-01-02 13:24:58 +000094 (srP)->r_pc = (ULong)cia; \
95 (srP)->r_sp = (ULong)r1; \
96 (srP)->misc.PPC32.r_lr = lr; \
sewardj59570ff2010-01-01 11:59:33 +000097 }
sewardj745fc452006-10-17 02:03:11 +000098#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
sewardj59570ff2010-01-01 11:59:33 +000099# define GET_STARTREGS(srP) \
100 { ULong cia, r1, lr; \
101 __asm__ __volatile__( \
102 "mflr 0;" /* r0 = lr */ \
103 "bl .m_libcassert_get_ip;" /* lr = pc */ \
104 ".m_libcassert_get_ip:\n" \
105 "mflr %0;" /* %0 = pc */ \
106 "mtlr 0;" /* restore lr */ \
107 "mr %1,1;" /* %1 = r1 */ \
108 "mr %2,0;" /* %2 = lr */ \
109 : "=r" (cia), "=r" (r1), "=r" (lr) \
110 : /* reads none */ \
111 : "r0" /* trashed */ \
112 ); \
sewardjf5f1e122010-01-02 13:24:58 +0000113 (srP)->r_pc = cia; \
114 (srP)->r_sp = r1; \
115 (srP)->misc.PPC64.r_lr = lr; \
sewardj59570ff2010-01-01 11:59:33 +0000116 }
117#elif defined(VGP_arm_linux)
118# define GET_STARTREGS(srP) \
sewardjfa5ce562010-09-23 22:05:59 +0000119 { UInt block[6]; \
sewardj59570ff2010-01-01 11:59:33 +0000120 __asm__ __volatile__( \
121 "str r15, [%0, #+0];" \
122 "str r14, [%0, #+4];" \
123 "str r13, [%0, #+8];" \
124 "str r12, [%0, #+12];" \
125 "str r11, [%0, #+16];" \
sewardjfa5ce562010-09-23 22:05:59 +0000126 "str r7, [%0, #+20];" \
sewardj59570ff2010-01-01 11:59:33 +0000127 : /* out */ \
128 : /* in */ "r"(&block[0]) \
129 : /* trash */ "memory" \
130 ); \
131 (srP)->r_pc = block[0] - 8; \
132 (srP)->r_sp = block[1]; \
133 (srP)->misc.ARM.r14 = block[2]; \
134 (srP)->misc.ARM.r12 = block[3]; \
135 (srP)->misc.ARM.r11 = block[4]; \
sewardjfa5ce562010-09-23 22:05:59 +0000136 (srP)->misc.ARM.r7 = block[5]; \
sewardj59570ff2010-01-01 11:59:33 +0000137 }
sewardjb5b87402011-03-07 16:05:35 +0000138#elif defined(VGP_s390x_linux)
139# define GET_STARTREGS(srP) \
140 { ULong ia, sp, fp, lr; \
141 __asm__ __volatile__( \
142 "bras %0,0f;" \
143 "0: lgr %1,15;" \
144 "lgr %2,11;" \
145 "lgr %3,14;" \
146 : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr) \
147 /* no read & clobber */ \
148 ); \
149 (srP)->r_pc = ia; \
150 (srP)->r_sp = sp; \
151 (srP)->misc.S390X.r_fp = fp; \
152 (srP)->misc.S390X.r_lr = lr; \
153 }
njn9450d242005-06-26 20:50:05 +0000154#else
155# error Unknown platform
156#endif
157
158#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +0000159
njnf39e9a32005-06-12 02:43:17 +0000160/* Pull down the entire world */
161void VG_(exit)( Int status )
162{
njn5b6b8fa2009-05-19 05:28:43 +0000163#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000164 (void)VG_(do_syscall1)(__NR_exit_group, status );
njnf76d27a2009-05-28 01:53:07 +0000165#elif defined(VGO_aix5) || defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000166 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000167#else
168# error Unknown OS
169#endif
njnf39e9a32005-06-12 02:43:17 +0000170 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000171 // We really shouldn't reach here. Just in case we do, use some very crude
172 // methods to force abort
173 __builtin_trap();
174 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000175}
176
njnc7561b92005-06-19 01:24:32 +0000177// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000178void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000179{
180 Int i;
181 VG_(printf)("\nsched status:\n");
182 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
183 for (i = 1; i < VG_N_THREADS; i++) {
184 if (VG_(threads)[i].status == VgTs_Empty) continue;
185 VG_(printf)( "\nThread %d: status = %s\n", i,
186 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
187 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
188 }
189 VG_(printf)("\n");
190}
njnc7561b92005-06-19 01:24:32 +0000191
njn132bfcc2005-06-04 19:16:06 +0000192__attribute__ ((noreturn))
sewardj59570ff2010-01-01 11:59:33 +0000193static void report_and_quit ( const Char* report,
194 UnwindStartRegs* startRegsIN )
njn132bfcc2005-06-04 19:16:06 +0000195{
njn49b45ba2005-07-20 02:41:31 +0000196 Addr stacktop;
197 Addr ips[BACKTRACE_DEPTH];
njn5f5ef2a2009-05-11 08:01:09 +0000198 Int n_ips;
sewardj42781722006-12-17 19:36:06 +0000199 ThreadState *tst
200 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000201
202 // If necessary, fake up an ExeContext which is of our actual real CPU
203 // state. Could cause problems if we got the panic/exception within the
204 // execontext/stack dump/symtab code. But it's better than nothing.
sewardj59570ff2010-01-01 11:59:33 +0000205 UnwindStartRegs startRegs;
206 VG_(memset)(&startRegs, 0, sizeof(startRegs));
207
208 if (startRegsIN == NULL) {
209 GET_STARTREGS(&startRegs);
210 } else {
211 startRegs = *startRegsIN;
njn49b45ba2005-07-20 02:41:31 +0000212 }
213
sewardj45f4e7c2005-09-27 19:20:21 +0000214 stacktop = tst->os_state.valgrind_stack_init_SP;
sewardj738856f2009-07-15 14:48:32 +0000215
216 n_ips =
njn5f5ef2a2009-05-11 08:01:09 +0000217 VG_(get_StackTrace_wrk)(
218 0/*tid is unknown*/,
219 ips, BACKTRACE_DEPTH,
220 NULL/*array to dump SP values in*/,
221 NULL/*array to dump FP values in*/,
sewardj59570ff2010-01-01 11:59:33 +0000222 &startRegs, stacktop
njn5f5ef2a2009-05-11 08:01:09 +0000223 );
sewardj738856f2009-07-15 14:48:32 +0000224 VG_(clo_xml) = False;
njn5f5ef2a2009-05-11 08:01:09 +0000225 VG_(pp_StackTrace) (ips, n_ips);
njn49b45ba2005-07-20 02:41:31 +0000226
sewardj745fc452006-10-17 02:03:11 +0000227 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000228 VG_(printf)(
229 "\n"
230 "Note: see also the FAQ in the source distribution.\n"
231 "It contains workarounds to several common problems.\n"
232 "In particular, if Valgrind aborted or crashed after\n"
233 "identifying problems in your program, there's a good chance\n"
234 "that fixing those problems will prevent Valgrind aborting or\n"
235 "crashing, especially if it happened in m_mallocfree.c.\n"
236 "\n"
237 "If that doesn't help, please report this bug to: %s\n\n"
238 "In the bug report, send all the above text, the valgrind\n"
239 "version, and what OS and version you are using. Thanks.\n\n",
240 report);
njn132bfcc2005-06-04 19:16:06 +0000241 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000242}
243
244void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
245 Int line, const Char* fn, const HChar* format, ... )
246{
247 va_list vargs;
248 Char buf[256];
njn132bfcc2005-06-04 19:16:06 +0000249 Char* component;
250 Char* bugs_to;
251
252 static Bool entered = False;
253 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000254 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000255 entered = True;
256
257 va_start(vargs, format);
njnaba25b42005-06-21 04:26:24 +0000258 VG_(vsprintf) ( buf, format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000259 va_end(vargs);
260
261 if (isCore) {
262 component = "valgrind";
263 bugs_to = VG_BUGS_TO;
264 } else {
265 component = VG_(details).name;
266 bugs_to = VG_(details).bug_reports_to;
267 }
268
sewardjf349d552005-11-14 17:01:01 +0000269 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000270 VG_(printf_xml)("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000271
njn132bfcc2005-06-04 19:16:06 +0000272 // Treat vg_assert2(0, "foo") specially, as a panicky abort
273 if (VG_STREQ(expr, "0")) {
274 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000275 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000276 } else {
277 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
278 component, file, line, fn, expr );
279 }
280 if (!VG_STREQ(buf, ""))
281 VG_(printf)("%s: %s\n", component, buf );
282
sewardj59570ff2010-01-01 11:59:33 +0000283 report_and_quit(bugs_to, NULL);
njn132bfcc2005-06-04 19:16:06 +0000284}
285
286__attribute__ ((noreturn))
287static void panic ( Char* name, Char* report, Char* str,
sewardj59570ff2010-01-01 11:59:33 +0000288 UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000289{
sewardjf349d552005-11-14 17:01:01 +0000290 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000291 VG_(printf_xml)("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000292 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardj59570ff2010-01-01 11:59:33 +0000293 report_and_quit(report, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000294}
295
sewardj59570ff2010-01-01 11:59:33 +0000296void VG_(core_panic_at) ( Char* str, UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000297{
sewardj59570ff2010-01-01 11:59:33 +0000298 panic("valgrind", VG_BUGS_TO, str, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000299}
300
301void VG_(core_panic) ( Char* str )
302{
sewardj59570ff2010-01-01 11:59:33 +0000303 VG_(core_panic_at)(str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000304}
305
306void VG_(tool_panic) ( Char* str )
307{
sewardj59570ff2010-01-01 11:59:33 +0000308 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000309}
310
njn49b45ba2005-07-20 02:41:31 +0000311/* Print some helpful-ish text about unimplemented things, and give up. */
njn132bfcc2005-06-04 19:16:06 +0000312void VG_(unimplemented) ( Char* msg )
313{
sewardjf349d552005-11-14 17:01:01 +0000314 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000315 VG_(printf_xml)("</valgrindoutput>\n");
316 VG_(umsg)("\n");
317 VG_(umsg)("Valgrind detected that your program requires\n");
318 VG_(umsg)("the following unimplemented functionality:\n");
319 VG_(umsg)(" %s\n", msg);
320 VG_(umsg)("This may be because the functionality is hard to implement,\n");
321 VG_(umsg)("or because no reasonable program would behave this way,\n");
322 VG_(umsg)("or because nobody has yet needed it. "
323 "In any case, let us know at\n");
324 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
325 VG_BUGS_TO);
326 VG_(umsg)("\n");
327 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
328 VG_(umsg)("\n");
sewardj745fc452006-10-17 02:03:11 +0000329 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000330 VG_(exit)(1);
331}
332
njn132bfcc2005-06-04 19:16:06 +0000333/*--------------------------------------------------------------------*/
334/*--- end ---*/
335/*--------------------------------------------------------------------*/
336