blob: 5d0b7589b447c51f4fb2d61ad8a80afcbde30918 [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
njn9f207462009-03-10 22:02:09 +000010 Copyright (C) 2000-2009 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) \
119 { UInt block[5]; \
120 __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];" \
126 : /* out */ \
127 : /* in */ "r"(&block[0]) \
128 : /* trash */ "memory" \
129 ); \
130 (srP)->r_pc = block[0] - 8; \
131 (srP)->r_sp = block[1]; \
132 (srP)->misc.ARM.r14 = block[2]; \
133 (srP)->misc.ARM.r12 = block[3]; \
134 (srP)->misc.ARM.r11 = block[4]; \
135 }
njn9450d242005-06-26 20:50:05 +0000136#else
137# error Unknown platform
138#endif
139
140#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +0000141
njnf39e9a32005-06-12 02:43:17 +0000142/* Pull down the entire world */
143void VG_(exit)( Int status )
144{
njn5b6b8fa2009-05-19 05:28:43 +0000145#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000146 (void)VG_(do_syscall1)(__NR_exit_group, status );
njnf76d27a2009-05-28 01:53:07 +0000147#elif defined(VGO_aix5) || defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000148 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000149#else
150# error Unknown OS
151#endif
njnf39e9a32005-06-12 02:43:17 +0000152 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000153 // We really shouldn't reach here. Just in case we do, use some very crude
154 // methods to force abort
155 __builtin_trap();
156 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000157}
158
njnc7561b92005-06-19 01:24:32 +0000159// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000160void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000161{
162 Int i;
163 VG_(printf)("\nsched status:\n");
164 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
165 for (i = 1; i < VG_N_THREADS; i++) {
166 if (VG_(threads)[i].status == VgTs_Empty) continue;
167 VG_(printf)( "\nThread %d: status = %s\n", i,
168 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
169 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
170 }
171 VG_(printf)("\n");
172}
njnc7561b92005-06-19 01:24:32 +0000173
njn132bfcc2005-06-04 19:16:06 +0000174__attribute__ ((noreturn))
sewardj59570ff2010-01-01 11:59:33 +0000175static void report_and_quit ( const Char* report,
176 UnwindStartRegs* startRegsIN )
njn132bfcc2005-06-04 19:16:06 +0000177{
njn49b45ba2005-07-20 02:41:31 +0000178 Addr stacktop;
179 Addr ips[BACKTRACE_DEPTH];
njn5f5ef2a2009-05-11 08:01:09 +0000180 Int n_ips;
sewardj42781722006-12-17 19:36:06 +0000181 ThreadState *tst
182 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000183
184 // If necessary, fake up an ExeContext which is of our actual real CPU
185 // state. Could cause problems if we got the panic/exception within the
186 // execontext/stack dump/symtab code. But it's better than nothing.
sewardj59570ff2010-01-01 11:59:33 +0000187 UnwindStartRegs startRegs;
188 VG_(memset)(&startRegs, 0, sizeof(startRegs));
189
190 if (startRegsIN == NULL) {
191 GET_STARTREGS(&startRegs);
192 } else {
193 startRegs = *startRegsIN;
njn49b45ba2005-07-20 02:41:31 +0000194 }
195
sewardj45f4e7c2005-09-27 19:20:21 +0000196 stacktop = tst->os_state.valgrind_stack_init_SP;
sewardj738856f2009-07-15 14:48:32 +0000197
198 n_ips =
njn5f5ef2a2009-05-11 08:01:09 +0000199 VG_(get_StackTrace_wrk)(
200 0/*tid is unknown*/,
201 ips, BACKTRACE_DEPTH,
202 NULL/*array to dump SP values in*/,
203 NULL/*array to dump FP values in*/,
sewardj59570ff2010-01-01 11:59:33 +0000204 &startRegs, stacktop
njn5f5ef2a2009-05-11 08:01:09 +0000205 );
sewardj738856f2009-07-15 14:48:32 +0000206 VG_(clo_xml) = False;
njn5f5ef2a2009-05-11 08:01:09 +0000207 VG_(pp_StackTrace) (ips, n_ips);
njn49b45ba2005-07-20 02:41:31 +0000208
sewardj745fc452006-10-17 02:03:11 +0000209 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000210 VG_(printf)(
211 "\n"
212 "Note: see also the FAQ in the source distribution.\n"
213 "It contains workarounds to several common problems.\n"
214 "In particular, if Valgrind aborted or crashed after\n"
215 "identifying problems in your program, there's a good chance\n"
216 "that fixing those problems will prevent Valgrind aborting or\n"
217 "crashing, especially if it happened in m_mallocfree.c.\n"
218 "\n"
219 "If that doesn't help, please report this bug to: %s\n\n"
220 "In the bug report, send all the above text, the valgrind\n"
221 "version, and what OS and version you are using. Thanks.\n\n",
222 report);
njn132bfcc2005-06-04 19:16:06 +0000223 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000224}
225
226void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
227 Int line, const Char* fn, const HChar* format, ... )
228{
229 va_list vargs;
230 Char buf[256];
njn132bfcc2005-06-04 19:16:06 +0000231 Char* component;
232 Char* bugs_to;
233
234 static Bool entered = False;
235 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000236 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000237 entered = True;
238
239 va_start(vargs, format);
njnaba25b42005-06-21 04:26:24 +0000240 VG_(vsprintf) ( buf, format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000241 va_end(vargs);
242
243 if (isCore) {
244 component = "valgrind";
245 bugs_to = VG_BUGS_TO;
246 } else {
247 component = VG_(details).name;
248 bugs_to = VG_(details).bug_reports_to;
249 }
250
sewardjf349d552005-11-14 17:01:01 +0000251 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000252 VG_(printf_xml)("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000253
njn132bfcc2005-06-04 19:16:06 +0000254 // Treat vg_assert2(0, "foo") specially, as a panicky abort
255 if (VG_STREQ(expr, "0")) {
256 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000257 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000258 } else {
259 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
260 component, file, line, fn, expr );
261 }
262 if (!VG_STREQ(buf, ""))
263 VG_(printf)("%s: %s\n", component, buf );
264
sewardj59570ff2010-01-01 11:59:33 +0000265 report_and_quit(bugs_to, NULL);
njn132bfcc2005-06-04 19:16:06 +0000266}
267
268__attribute__ ((noreturn))
269static void panic ( Char* name, Char* report, Char* str,
sewardj59570ff2010-01-01 11:59:33 +0000270 UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000271{
sewardjf349d552005-11-14 17:01:01 +0000272 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000273 VG_(printf_xml)("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000274 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardj59570ff2010-01-01 11:59:33 +0000275 report_and_quit(report, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000276}
277
sewardj59570ff2010-01-01 11:59:33 +0000278void VG_(core_panic_at) ( Char* str, UnwindStartRegs* startRegs )
njn132bfcc2005-06-04 19:16:06 +0000279{
sewardj59570ff2010-01-01 11:59:33 +0000280 panic("valgrind", VG_BUGS_TO, str, startRegs);
njn132bfcc2005-06-04 19:16:06 +0000281}
282
283void VG_(core_panic) ( Char* str )
284{
sewardj59570ff2010-01-01 11:59:33 +0000285 VG_(core_panic_at)(str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000286}
287
288void VG_(tool_panic) ( Char* str )
289{
sewardj59570ff2010-01-01 11:59:33 +0000290 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
njn132bfcc2005-06-04 19:16:06 +0000291}
292
njn49b45ba2005-07-20 02:41:31 +0000293/* Print some helpful-ish text about unimplemented things, and give up. */
njn132bfcc2005-06-04 19:16:06 +0000294void VG_(unimplemented) ( Char* msg )
295{
sewardjf349d552005-11-14 17:01:01 +0000296 if (VG_(clo_xml))
sewardj738856f2009-07-15 14:48:32 +0000297 VG_(printf_xml)("</valgrindoutput>\n");
298 VG_(umsg)("\n");
299 VG_(umsg)("Valgrind detected that your program requires\n");
300 VG_(umsg)("the following unimplemented functionality:\n");
301 VG_(umsg)(" %s\n", msg);
302 VG_(umsg)("This may be because the functionality is hard to implement,\n");
303 VG_(umsg)("or because no reasonable program would behave this way,\n");
304 VG_(umsg)("or because nobody has yet needed it. "
305 "In any case, let us know at\n");
306 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
307 VG_BUGS_TO);
308 VG_(umsg)("\n");
309 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
310 VG_(umsg)("\n");
sewardj745fc452006-10-17 02:03:11 +0000311 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000312 VG_(exit)(1);
313}
314
njn132bfcc2005-06-04 19:16:06 +0000315/*--------------------------------------------------------------------*/
316/*--- end ---*/
317/*--------------------------------------------------------------------*/
318