blob: 731864ff26000838b39aac322131b6d65dda7e79 [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 }
njn9450d242005-06-26 20:50:05 +0000138#else
139# error Unknown platform
140#endif
141
142#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +0000143
njnf39e9a32005-06-12 02:43:17 +0000144/* Pull down the entire world */
145void VG_(exit)( Int status )
146{
njn5b6b8fa2009-05-19 05:28:43 +0000147#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000148 (void)VG_(do_syscall1)(__NR_exit_group, status );
njnf76d27a2009-05-28 01:53:07 +0000149#elif defined(VGO_aix5) || defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000150 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000151#else
152# error Unknown OS
153#endif
njnf39e9a32005-06-12 02:43:17 +0000154 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000155 // We really shouldn't reach here. Just in case we do, use some very crude
156 // methods to force abort
157 __builtin_trap();
158 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000159}
160
njnc7561b92005-06-19 01:24:32 +0000161// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000162void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000163{
164 Int i;
165 VG_(printf)("\nsched status:\n");
166 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
167 for (i = 1; i < VG_N_THREADS; i++) {
168 if (VG_(threads)[i].status == VgTs_Empty) continue;
169 VG_(printf)( "\nThread %d: status = %s\n", i,
170 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
171 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
172 }
173 VG_(printf)("\n");
174}
njnc7561b92005-06-19 01:24:32 +0000175
njn132bfcc2005-06-04 19:16:06 +0000176__attribute__ ((noreturn))
sewardj59570ff2010-01-01 11:59:33 +0000177static void report_and_quit ( const Char* report,
178 UnwindStartRegs* startRegsIN )
njn132bfcc2005-06-04 19:16:06 +0000179{
njn49b45ba2005-07-20 02:41:31 +0000180 Addr stacktop;
181 Addr ips[BACKTRACE_DEPTH];
njn5f5ef2a2009-05-11 08:01:09 +0000182 Int n_ips;
sewardj42781722006-12-17 19:36:06 +0000183 ThreadState *tst
184 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000185
186 // If necessary, fake up an ExeContext which is of our actual real CPU
187 // state. Could cause problems if we got the panic/exception within the
188 // execontext/stack dump/symtab code. But it's better than nothing.
sewardj59570ff2010-01-01 11:59:33 +0000189 UnwindStartRegs startRegs;
190 VG_(memset)(&startRegs, 0, sizeof(startRegs));
191
192 if (startRegsIN == NULL) {
193 GET_STARTREGS(&startRegs);
194 } else {
195 startRegs = *startRegsIN;
njn49b45ba2005-07-20 02:41:31 +0000196 }
197
sewardj45f4e7c2005-09-27 19:20:21 +0000198 stacktop = tst->os_state.valgrind_stack_init_SP;
sewardj738856f2009-07-15 14:48:32 +0000199
200 n_ips =
njn5f5ef2a2009-05-11 08:01:09 +0000201 VG_(get_StackTrace_wrk)(
202 0/*tid is unknown*/,
203 ips, BACKTRACE_DEPTH,
204 NULL/*array to dump SP values in*/,
205 NULL/*array to dump FP values in*/,
sewardj59570ff2010-01-01 11:59:33 +0000206 &startRegs, stacktop
njn5f5ef2a2009-05-11 08:01:09 +0000207 );
sewardj738856f2009-07-15 14:48:32 +0000208 VG_(clo_xml) = False;
njn5f5ef2a2009-05-11 08:01:09 +0000209 VG_(pp_StackTrace) (ips, n_ips);
njn49b45ba2005-07-20 02:41:31 +0000210
sewardj745fc452006-10-17 02:03:11 +0000211 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000212 VG_(printf)(
213 "\n"
214 "Note: see also the FAQ in the source distribution.\n"
215 "It contains workarounds to several common problems.\n"
216 "In particular, if Valgrind aborted or crashed after\n"
217 "identifying problems in your program, there's a good chance\n"
218 "that fixing those problems will prevent Valgrind aborting or\n"
219 "crashing, especially if it happened in m_mallocfree.c.\n"
220 "\n"
221 "If that doesn't help, please report this bug to: %s\n\n"
222 "In the bug report, send all the above text, the valgrind\n"
223 "version, and what OS and version you are using. Thanks.\n\n",
224 report);
njn132bfcc2005-06-04 19:16:06 +0000225 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000226}
227
228void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
229 Int line, const Char* fn, const HChar* format, ... )
230{
231 va_list vargs;
232 Char buf[256];
njn132bfcc2005-06-04 19:16:06 +0000233 Char* component;
234 Char* bugs_to;
235
236 static Bool entered = False;
237 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000238 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000239 entered = True;
240
241 va_start(vargs, format);
njnaba25b42005-06-21 04:26:24 +0000242 VG_(vsprintf) ( buf, format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000243 va_end(vargs);
244
245 if (isCore) {
246 component = "valgrind";
247 bugs_to = VG_BUGS_TO;
248 } else {
249 component = VG_(details).name;
250 bugs_to = VG_(details).bug_reports_to;
251 }
252
sewardjf349d552005-11-14 17:01:01 +0000253 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000254 VG_(printf_xml)("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000255
njn132bfcc2005-06-04 19:16:06 +0000256 // Treat vg_assert2(0, "foo") specially, as a panicky abort
257 if (VG_STREQ(expr, "0")) {
258 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000259 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000260 } else {
261 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
262 component, file, line, fn, expr );
263 }
264 if (!VG_STREQ(buf, ""))
265 VG_(printf)("%s: %s\n", component, buf );
266
sewardj59570ff2010-01-01 11:59:33 +0000267 report_and_quit(bugs_to, NULL);
njn132bfcc2005-06-04 19:16:06 +0000268}
269
270__attribute__ ((noreturn))
271static void panic ( Char* name, Char* report, Char* str,
sewardj59570ff2010-01-01 11:59:33 +0000272 UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000273{
sewardjf349d552005-11-14 17:01:01 +0000274 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000275 VG_(printf_xml)("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000276 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardj59570ff2010-01-01 11:59:33 +0000277 report_and_quit(report, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000278}
279
sewardj59570ff2010-01-01 11:59:33 +0000280void VG_(core_panic_at) ( Char* str, UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000281{
sewardj59570ff2010-01-01 11:59:33 +0000282 panic("valgrind", VG_BUGS_TO, str, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000283}
284
285void VG_(core_panic) ( Char* str )
286{
sewardj59570ff2010-01-01 11:59:33 +0000287 VG_(core_panic_at)(str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000288}
289
290void VG_(tool_panic) ( Char* str )
291{
sewardj59570ff2010-01-01 11:59:33 +0000292 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000293}
294
njn49b45ba2005-07-20 02:41:31 +0000295/* Print some helpful-ish text about unimplemented things, and give up. */
njn132bfcc2005-06-04 19:16:06 +0000296void VG_(unimplemented) ( Char* msg )
297{
sewardjf349d552005-11-14 17:01:01 +0000298 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000299 VG_(printf_xml)("</valgrindoutput>\n");
300 VG_(umsg)("\n");
301 VG_(umsg)("Valgrind detected that your program requires\n");
302 VG_(umsg)("the following unimplemented functionality:\n");
303 VG_(umsg)(" %s\n", msg);
304 VG_(umsg)("This may be because the functionality is hard to implement,\n");
305 VG_(umsg)("or because no reasonable program would behave this way,\n");
306 VG_(umsg)("or because nobody has yet needed it. "
307 "In any case, let us know at\n");
308 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
309 VG_BUGS_TO);
310 VG_(umsg)("\n");
311 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
312 VG_(umsg)("\n");
sewardj745fc452006-10-17 02:03:11 +0000313 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000314 VG_(exit)(1);
315}
316
njn132bfcc2005-06-04 19:16:06 +0000317/*--------------------------------------------------------------------*/
318/*--- end ---*/
319/*--------------------------------------------------------------------*/
320