blob: 8e3eba2f9f7cc6e3cfef0405a2569e42cde34408 [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
njnf76d27a2009-05-28 01:53:07 +000048#if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
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));
njnf76d27a2009-05-28 01:53:07 +000057#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
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{
njn5b6b8fa2009-05-19 05:28:43 +0000102#if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000103 (void)VG_(do_syscall1)(__NR_exit_group, status );
njnf76d27a2009-05-28 01:53:07 +0000104#elif defined(VGO_aix5) || defined(VGO_darwin)
njnf39e9a32005-06-12 02:43:17 +0000105 (void)VG_(do_syscall1)(__NR_exit, status );
njn5b6b8fa2009-05-19 05:28:43 +0000106#else
107# error Unknown OS
108#endif
njnf39e9a32005-06-12 02:43:17 +0000109 /*NOTREACHED*/
njn4eeb0e52009-06-09 22:46:32 +0000110 // We really shouldn't reach here. Just in case we do, use some very crude
111 // methods to force abort
112 __builtin_trap();
113 *(volatile Int*)0 = 'x';
njnf39e9a32005-06-12 02:43:17 +0000114}
115
njnc7561b92005-06-19 01:24:32 +0000116// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000117void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000118{
119 Int i;
120 VG_(printf)("\nsched status:\n");
121 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
122 for (i = 1; i < VG_N_THREADS; i++) {
123 if (VG_(threads)[i].status == VgTs_Empty) continue;
124 VG_(printf)( "\nThread %d: status = %s\n", i,
125 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
126 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
127 }
128 VG_(printf)("\n");
129}
njnc7561b92005-06-19 01:24:32 +0000130
njn132bfcc2005-06-04 19:16:06 +0000131__attribute__ ((noreturn))
sewardjacaec5f2005-08-19 16:02:59 +0000132static void report_and_quit ( const Char* report,
133 Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000134{
njn49b45ba2005-07-20 02:41:31 +0000135 Addr stacktop;
136 Addr ips[BACKTRACE_DEPTH];
njn5f5ef2a2009-05-11 08:01:09 +0000137 Int n_ips;
sewardj42781722006-12-17 19:36:06 +0000138 ThreadState *tst
139 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000140
141 // If necessary, fake up an ExeContext which is of our actual real CPU
142 // state. Could cause problems if we got the panic/exception within the
143 // execontext/stack dump/symtab code. But it's better than nothing.
144 if (0 == ip && 0 == sp && 0 == fp) {
sewardj9a699e82005-11-05 14:22:03 +0000145 GET_REAL_PC_SP_AND_FP(ip, sp, fp);
njn49b45ba2005-07-20 02:41:31 +0000146 }
147
sewardj45f4e7c2005-09-27 19:20:21 +0000148 stacktop = tst->os_state.valgrind_stack_init_SP;
njn49b45ba2005-07-20 02:41:31 +0000149
njn5f5ef2a2009-05-11 08:01:09 +0000150 n_ips =
151 VG_(get_StackTrace_wrk)(
152 0/*tid is unknown*/,
153 ips, BACKTRACE_DEPTH,
154 NULL/*array to dump SP values in*/,
155 NULL/*array to dump FP values in*/,
156 ip, sp, fp, lr, sp, stacktop
157 );
158 VG_(pp_StackTrace) (ips, n_ips);
njn49b45ba2005-07-20 02:41:31 +0000159
sewardj745fc452006-10-17 02:03:11 +0000160 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000161 VG_(printf)(
162 "\n"
163 "Note: see also the FAQ in the source distribution.\n"
164 "It contains workarounds to several common problems.\n"
165 "In particular, if Valgrind aborted or crashed after\n"
166 "identifying problems in your program, there's a good chance\n"
167 "that fixing those problems will prevent Valgrind aborting or\n"
168 "crashing, especially if it happened in m_mallocfree.c.\n"
169 "\n"
170 "If that doesn't help, please report this bug to: %s\n\n"
171 "In the bug report, send all the above text, the valgrind\n"
172 "version, and what OS and version you are using. Thanks.\n\n",
173 report);
njn132bfcc2005-06-04 19:16:06 +0000174 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000175}
176
177void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
178 Int line, const Char* fn, const HChar* format, ... )
179{
180 va_list vargs;
181 Char buf[256];
njn132bfcc2005-06-04 19:16:06 +0000182 Char* component;
183 Char* bugs_to;
184
185 static Bool entered = False;
186 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000187 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000188 entered = True;
189
190 va_start(vargs, format);
njnaba25b42005-06-21 04:26:24 +0000191 VG_(vsprintf) ( buf, format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000192 va_end(vargs);
193
194 if (isCore) {
195 component = "valgrind";
196 bugs_to = VG_BUGS_TO;
197 } else {
198 component = VG_(details).name;
199 bugs_to = VG_(details).bug_reports_to;
200 }
201
sewardjf349d552005-11-14 17:01:01 +0000202 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000203 VG_UMSG("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000204
njn132bfcc2005-06-04 19:16:06 +0000205 // Treat vg_assert2(0, "foo") specially, as a panicky abort
206 if (VG_STREQ(expr, "0")) {
207 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000208 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000209 } else {
210 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
211 component, file, line, fn, expr );
212 }
213 if (!VG_STREQ(buf, ""))
214 VG_(printf)("%s: %s\n", component, buf );
215
sewardjacaec5f2005-08-19 16:02:59 +0000216 report_and_quit(bugs_to, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000217}
218
219__attribute__ ((noreturn))
220static void panic ( Char* name, Char* report, Char* str,
sewardjacaec5f2005-08-19 16:02:59 +0000221 Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000222{
sewardjf349d552005-11-14 17:01:01 +0000223 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000224 VG_UMSG("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000225 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardjacaec5f2005-08-19 16:02:59 +0000226 report_and_quit(report, ip, sp, fp, lr);
njn132bfcc2005-06-04 19:16:06 +0000227}
228
sewardjacaec5f2005-08-19 16:02:59 +0000229void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000230{
sewardjacaec5f2005-08-19 16:02:59 +0000231 panic("valgrind", VG_BUGS_TO, str, ip, sp, fp, lr);
njn132bfcc2005-06-04 19:16:06 +0000232}
233
234void VG_(core_panic) ( Char* str )
235{
sewardjacaec5f2005-08-19 16:02:59 +0000236 VG_(core_panic_at)(str, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000237}
238
239void VG_(tool_panic) ( Char* str )
240{
sewardjacaec5f2005-08-19 16:02:59 +0000241 panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000242}
243
njn49b45ba2005-07-20 02:41:31 +0000244/* Print some helpful-ish text about unimplemented things, and give up. */
njn132bfcc2005-06-04 19:16:06 +0000245void VG_(unimplemented) ( Char* msg )
246{
sewardjf349d552005-11-14 17:01:01 +0000247 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000248 VG_UMSG("</valgrindoutput>\n");
249 VG_UMSG("");
250 VG_UMSG("Valgrind detected that your program requires");
251 VG_UMSG("the following unimplemented functionality:");
252 VG_UMSG(" %s", msg);
253 VG_UMSG("This may be because the functionality is hard to implement,");
254 VG_UMSG("or because no reasonable program would behave this way,");
255 VG_UMSG("or because nobody has yet needed it. In any case, let us know at");
256 VG_UMSG("%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
257 VG_UMSG("");
258 VG_UMSG("Valgrind has to exit now. Sorry. Bye!");
259 VG_UMSG("");
sewardj745fc452006-10-17 02:03:11 +0000260 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000261 VG_(exit)(1);
262}
263
njn132bfcc2005-06-04 19:16:06 +0000264/*--------------------------------------------------------------------*/
265/*--- end ---*/
266/*--------------------------------------------------------------------*/
267