blob: 1d7e5a7d9b1ba78c7c21fc65b9f9a84bd0b1fecf [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
njn9450d242005-06-26 20:50:05 +000048#if defined(VGP_x86_linux)
sewardj9a699e82005-11-05 14:22:03 +000049# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
njn70ecd6b2009-04-15 03:55:41 +000050 asm("call 0f;" \
51 "0: popl %0;" \
sewardj9a699e82005-11-05 14:22:03 +000052 "movl %%esp, %1;" \
53 "movl %%ebp, %2;" \
54 : "=r" (pc),\
55 "=r" (sp),\
njn9450d242005-06-26 20:50:05 +000056 "=r" (fp));
57#elif defined(VGP_amd64_linux)
sewardj9a699e82005-11-05 14:22:03 +000058# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
59 asm("leaq 0(%%rip), %0;" \
60 "movq %%rsp, %1;" \
61 "movq %%rbp, %2;" \
62 : "=r" (pc),\
63 "=r" (sp),\
njn9450d242005-06-26 20:50:05 +000064 "=r" (fp));
sewardj745fc452006-10-17 02:03:11 +000065#elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5)
sewardjde616ec2005-11-05 14:48:03 +000066# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
67 asm("mflr 0;" /* r0 = lr */ \
68 "bl m_libcassert_get_ip;" /* lr = pc */ \
69 "m_libcassert_get_ip:\n" \
70 "mflr %0;" \
71 "mtlr 0;" /* restore lr */ \
72 "mr %1,1;" \
73 "mr %2,1;" \
74 : "=r" (pc), \
75 "=r" (sp), \
76 "=r" (fp) \
77 : /* reads none */ \
78 : "r0" /* trashed */ );
sewardj745fc452006-10-17 02:03:11 +000079#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
sewardj2c48c7b2005-11-29 13:05:56 +000080# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \
81 asm("mflr 0;" /* r0 = lr */ \
cerion297c88f2005-12-22 15:53:12 +000082 "bl .m_libcassert_get_ip;" /* lr = pc */ \
83 ".m_libcassert_get_ip:\n" \
sewardj2c48c7b2005-11-29 13:05:56 +000084 "mflr %0;" \
85 "mtlr 0;" /* restore lr */ \
86 "mr %1,1;" \
87 "mr %2,1;" \
88 : "=r" (pc), \
89 "=r" (sp), \
90 "=r" (fp) \
91 : /* reads none */ \
92 : "r0" /* trashed */ );
njn9450d242005-06-26 20:50:05 +000093#else
94# error Unknown platform
95#endif
96
97#define BACKTRACE_DEPTH 100 // nice and deep!
njn3161e802005-06-20 03:38:27 +000098
njnf39e9a32005-06-12 02:43:17 +000099/* Pull down the entire world */
100void VG_(exit)( Int status )
101{
sewardj745fc452006-10-17 02:03:11 +0000102# if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000103 (void)VG_(do_syscall1)(__NR_exit_group, status );
sewardj745fc452006-10-17 02:03:11 +0000104# endif
njnf39e9a32005-06-12 02:43:17 +0000105 (void)VG_(do_syscall1)(__NR_exit, status );
106 /* Why are we still alive here? */
107 /*NOTREACHED*/
108 *(volatile Int *)0 = 'x';
109 vg_assert(2+2 == 5);
110}
111
njnc7561b92005-06-19 01:24:32 +0000112// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000113void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000114{
115 Int i;
116 VG_(printf)("\nsched status:\n");
117 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
118 for (i = 1; i < VG_N_THREADS; i++) {
119 if (VG_(threads)[i].status == VgTs_Empty) continue;
120 VG_(printf)( "\nThread %d: status = %s\n", i,
121 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
122 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
123 }
124 VG_(printf)("\n");
125}
njnc7561b92005-06-19 01:24:32 +0000126
njn132bfcc2005-06-04 19:16:06 +0000127__attribute__ ((noreturn))
sewardjacaec5f2005-08-19 16:02:59 +0000128static void report_and_quit ( const Char* report,
129 Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000130{
njn49b45ba2005-07-20 02:41:31 +0000131 Addr stacktop;
132 Addr ips[BACKTRACE_DEPTH];
sewardj42781722006-12-17 19:36:06 +0000133 ThreadState *tst
134 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000135
136 // If necessary, fake up an ExeContext which is of our actual real CPU
137 // state. Could cause problems if we got the panic/exception within the
138 // execontext/stack dump/symtab code. But it's better than nothing.
139 if (0 == ip && 0 == sp && 0 == fp) {
sewardj9a699e82005-11-05 14:22:03 +0000140 GET_REAL_PC_SP_AND_FP(ip, sp, fp);
njn49b45ba2005-07-20 02:41:31 +0000141 }
142
sewardj45f4e7c2005-09-27 19:20:21 +0000143 stacktop = tst->os_state.valgrind_stack_init_SP;
njn49b45ba2005-07-20 02:41:31 +0000144
sewardjb8b79ad2008-03-03 01:35:41 +0000145 VG_(get_StackTrace_wrk)(
146 0/*tid is unknown*/,
147 ips, BACKTRACE_DEPTH,
148 NULL/*array to dump SP values in*/,
149 NULL/*array to dump FP values in*/,
150 ip, sp, fp, lr, sp, stacktop
151 );
njn49b45ba2005-07-20 02:41:31 +0000152 VG_(pp_StackTrace) (ips, BACKTRACE_DEPTH);
153
sewardj745fc452006-10-17 02:03:11 +0000154 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000155 VG_(printf)(
156 "\n"
157 "Note: see also the FAQ in the source distribution.\n"
158 "It contains workarounds to several common problems.\n"
159 "In particular, if Valgrind aborted or crashed after\n"
160 "identifying problems in your program, there's a good chance\n"
161 "that fixing those problems will prevent Valgrind aborting or\n"
162 "crashing, especially if it happened in m_mallocfree.c.\n"
163 "\n"
164 "If that doesn't help, please report this bug to: %s\n\n"
165 "In the bug report, send all the above text, the valgrind\n"
166 "version, and what OS and version you are using. Thanks.\n\n",
167 report);
njn132bfcc2005-06-04 19:16:06 +0000168 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000169}
170
171void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
172 Int line, const Char* fn, const HChar* format, ... )
173{
174 va_list vargs;
175 Char buf[256];
njn132bfcc2005-06-04 19:16:06 +0000176 Char* component;
177 Char* bugs_to;
178
179 static Bool entered = False;
180 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000181 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000182 entered = True;
183
184 va_start(vargs, format);
njnaba25b42005-06-21 04:26:24 +0000185 VG_(vsprintf) ( buf, format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000186 va_end(vargs);
187
188 if (isCore) {
189 component = "valgrind";
190 bugs_to = VG_BUGS_TO;
191 } else {
192 component = VG_(details).name;
193 bugs_to = VG_(details).bug_reports_to;
194 }
195
sewardjf349d552005-11-14 17:01:01 +0000196 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000197 VG_UMSG("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000198
njn132bfcc2005-06-04 19:16:06 +0000199 // Treat vg_assert2(0, "foo") specially, as a panicky abort
200 if (VG_STREQ(expr, "0")) {
201 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000202 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000203 } else {
204 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
205 component, file, line, fn, expr );
206 }
207 if (!VG_STREQ(buf, ""))
208 VG_(printf)("%s: %s\n", component, buf );
209
sewardjacaec5f2005-08-19 16:02:59 +0000210 report_and_quit(bugs_to, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000211}
212
213__attribute__ ((noreturn))
214static void panic ( Char* name, Char* report, Char* str,
sewardjacaec5f2005-08-19 16:02:59 +0000215 Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000216{
sewardjf349d552005-11-14 17:01:01 +0000217 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000218 VG_UMSG("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000219 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardjacaec5f2005-08-19 16:02:59 +0000220 report_and_quit(report, ip, sp, fp, lr);
njn132bfcc2005-06-04 19:16:06 +0000221}
222
sewardjacaec5f2005-08-19 16:02:59 +0000223void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000224{
sewardjacaec5f2005-08-19 16:02:59 +0000225 panic("valgrind", VG_BUGS_TO, str, ip, sp, fp, lr);
njn132bfcc2005-06-04 19:16:06 +0000226}
227
228void VG_(core_panic) ( Char* str )
229{
sewardjacaec5f2005-08-19 16:02:59 +0000230 VG_(core_panic_at)(str, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000231}
232
233void VG_(tool_panic) ( Char* str )
234{
sewardjacaec5f2005-08-19 16:02:59 +0000235 panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000236}
237
njn49b45ba2005-07-20 02:41:31 +0000238/* Print some helpful-ish text about unimplemented things, and give up. */
njn132bfcc2005-06-04 19:16:06 +0000239void VG_(unimplemented) ( Char* msg )
240{
sewardjf349d552005-11-14 17:01:01 +0000241 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000242 VG_UMSG("</valgrindoutput>\n");
243 VG_UMSG("");
244 VG_UMSG("Valgrind detected that your program requires");
245 VG_UMSG("the following unimplemented functionality:");
246 VG_UMSG(" %s", msg);
247 VG_UMSG("This may be because the functionality is hard to implement,");
248 VG_UMSG("or because no reasonable program would behave this way,");
249 VG_UMSG("or because nobody has yet needed it. In any case, let us know at");
250 VG_UMSG("%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
251 VG_UMSG("");
252 VG_UMSG("Valgrind has to exit now. Sorry. Bye!");
253 VG_UMSG("");
sewardj745fc452006-10-17 02:03:11 +0000254 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000255 VG_(exit)(1);
256}
257
njn132bfcc2005-06-04 19:16:06 +0000258/*--------------------------------------------------------------------*/
259/*--- end ---*/
260/*--------------------------------------------------------------------*/
261