blob: 8dbded319e70487800b5da9fb69d36e0fe623389 [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{
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 );
njn5b6b8fa2009-05-19 05:28:43 +0000104#elif defined(VGO_aix5)
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*/
njn5b6b8fa2009-05-19 05:28:43 +0000110 VG_(core_panic)("VG_(exit) didn't work?");
njnf39e9a32005-06-12 02:43:17 +0000111}
112
njnc7561b92005-06-19 01:24:32 +0000113// Print the scheduler status.
sewardj745fc452006-10-17 02:03:11 +0000114void VG_(show_sched_status) ( void )
njn49b45ba2005-07-20 02:41:31 +0000115{
116 Int i;
117 VG_(printf)("\nsched status:\n");
118 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)());
119 for (i = 1; i < VG_N_THREADS; i++) {
120 if (VG_(threads)[i].status == VgTs_Empty) continue;
121 VG_(printf)( "\nThread %d: status = %s\n", i,
122 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
123 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
124 }
125 VG_(printf)("\n");
126}
njnc7561b92005-06-19 01:24:32 +0000127
njn132bfcc2005-06-04 19:16:06 +0000128__attribute__ ((noreturn))
sewardjacaec5f2005-08-19 16:02:59 +0000129static void report_and_quit ( const Char* report,
130 Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000131{
njn49b45ba2005-07-20 02:41:31 +0000132 Addr stacktop;
133 Addr ips[BACKTRACE_DEPTH];
njn5f5ef2a2009-05-11 08:01:09 +0000134 Int n_ips;
sewardj42781722006-12-17 19:36:06 +0000135 ThreadState *tst
136 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
njn49b45ba2005-07-20 02:41:31 +0000137
138 // If necessary, fake up an ExeContext which is of our actual real CPU
139 // state. Could cause problems if we got the panic/exception within the
140 // execontext/stack dump/symtab code. But it's better than nothing.
141 if (0 == ip && 0 == sp && 0 == fp) {
sewardj9a699e82005-11-05 14:22:03 +0000142 GET_REAL_PC_SP_AND_FP(ip, sp, fp);
njn49b45ba2005-07-20 02:41:31 +0000143 }
144
sewardj45f4e7c2005-09-27 19:20:21 +0000145 stacktop = tst->os_state.valgrind_stack_init_SP;
njn49b45ba2005-07-20 02:41:31 +0000146
njn5f5ef2a2009-05-11 08:01:09 +0000147 n_ips =
148 VG_(get_StackTrace_wrk)(
149 0/*tid is unknown*/,
150 ips, BACKTRACE_DEPTH,
151 NULL/*array to dump SP values in*/,
152 NULL/*array to dump FP values in*/,
153 ip, sp, fp, lr, sp, stacktop
154 );
155 VG_(pp_StackTrace) (ips, n_ips);
njn49b45ba2005-07-20 02:41:31 +0000156
sewardj745fc452006-10-17 02:03:11 +0000157 VG_(show_sched_status)();
njnb8329f02009-04-16 00:33:20 +0000158 VG_(printf)(
159 "\n"
160 "Note: see also the FAQ in the source distribution.\n"
161 "It contains workarounds to several common problems.\n"
162 "In particular, if Valgrind aborted or crashed after\n"
163 "identifying problems in your program, there's a good chance\n"
164 "that fixing those problems will prevent Valgrind aborting or\n"
165 "crashing, especially if it happened in m_mallocfree.c.\n"
166 "\n"
167 "If that doesn't help, please report this bug to: %s\n\n"
168 "In the bug report, send all the above text, the valgrind\n"
169 "version, and what OS and version you are using. Thanks.\n\n",
170 report);
njn132bfcc2005-06-04 19:16:06 +0000171 VG_(exit)(1);
njn132bfcc2005-06-04 19:16:06 +0000172}
173
174void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
175 Int line, const Char* fn, const HChar* format, ... )
176{
177 va_list vargs;
178 Char buf[256];
njn132bfcc2005-06-04 19:16:06 +0000179 Char* component;
180 Char* bugs_to;
181
182 static Bool entered = False;
183 if (entered)
sewardj745fc452006-10-17 02:03:11 +0000184 VG_(exit)(2);
njn132bfcc2005-06-04 19:16:06 +0000185 entered = True;
186
187 va_start(vargs, format);
njnaba25b42005-06-21 04:26:24 +0000188 VG_(vsprintf) ( buf, format, vargs );
njn132bfcc2005-06-04 19:16:06 +0000189 va_end(vargs);
190
191 if (isCore) {
192 component = "valgrind";
193 bugs_to = VG_BUGS_TO;
194 } else {
195 component = VG_(details).name;
196 bugs_to = VG_(details).bug_reports_to;
197 }
198
sewardjf349d552005-11-14 17:01:01 +0000199 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000200 VG_UMSG("</valgrindoutput>\n");
sewardjf349d552005-11-14 17:01:01 +0000201
njn132bfcc2005-06-04 19:16:06 +0000202 // Treat vg_assert2(0, "foo") specially, as a panicky abort
203 if (VG_STREQ(expr, "0")) {
204 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
njn8a7b41b2007-09-23 00:51:24 +0000205 component, file, line, fn );
njn132bfcc2005-06-04 19:16:06 +0000206 } else {
207 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
208 component, file, line, fn, expr );
209 }
210 if (!VG_STREQ(buf, ""))
211 VG_(printf)("%s: %s\n", component, buf );
212
sewardjacaec5f2005-08-19 16:02:59 +0000213 report_and_quit(bugs_to, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000214}
215
216__attribute__ ((noreturn))
217static void panic ( Char* name, Char* report, Char* str,
sewardjacaec5f2005-08-19 16:02:59 +0000218 Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000219{
sewardjf349d552005-11-14 17:01:01 +0000220 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000221 VG_UMSG("</valgrindoutput>\n");
njn132bfcc2005-06-04 19:16:06 +0000222 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
sewardjacaec5f2005-08-19 16:02:59 +0000223 report_and_quit(report, ip, sp, fp, lr);
njn132bfcc2005-06-04 19:16:06 +0000224}
225
sewardjacaec5f2005-08-19 16:02:59 +0000226void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp, Addr lr )
njn132bfcc2005-06-04 19:16:06 +0000227{
sewardjacaec5f2005-08-19 16:02:59 +0000228 panic("valgrind", VG_BUGS_TO, str, ip, sp, fp, lr);
njn132bfcc2005-06-04 19:16:06 +0000229}
230
231void VG_(core_panic) ( Char* str )
232{
sewardjacaec5f2005-08-19 16:02:59 +0000233 VG_(core_panic_at)(str, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000234}
235
236void VG_(tool_panic) ( Char* str )
237{
sewardjacaec5f2005-08-19 16:02:59 +0000238 panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0,0);
njn132bfcc2005-06-04 19:16:06 +0000239}
240
njn49b45ba2005-07-20 02:41:31 +0000241/* Print some helpful-ish text about unimplemented things, and give up. */
njn132bfcc2005-06-04 19:16:06 +0000242void VG_(unimplemented) ( Char* msg )
243{
sewardjf349d552005-11-14 17:01:01 +0000244 if (VG_(clo_xml))
njn6f74a7e2009-03-12 00:06:45 +0000245 VG_UMSG("</valgrindoutput>\n");
246 VG_UMSG("");
247 VG_UMSG("Valgrind detected that your program requires");
248 VG_UMSG("the following unimplemented functionality:");
249 VG_UMSG(" %s", msg);
250 VG_UMSG("This may be because the functionality is hard to implement,");
251 VG_UMSG("or because no reasonable program would behave this way,");
252 VG_UMSG("or because nobody has yet needed it. In any case, let us know at");
253 VG_UMSG("%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
254 VG_UMSG("");
255 VG_UMSG("Valgrind has to exit now. Sorry. Bye!");
256 VG_UMSG("");
sewardj745fc452006-10-17 02:03:11 +0000257 VG_(show_sched_status)();
njn132bfcc2005-06-04 19:16:06 +0000258 VG_(exit)(1);
259}
260
njn132bfcc2005-06-04 19:16:06 +0000261/*--------------------------------------------------------------------*/
262/*--- end ---*/
263/*--------------------------------------------------------------------*/
264