m_libcassert.c revision 49b45ba90382fd313e40555559f5f5aaa23033b4
1
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
10   Copyright (C) 2000-2005 Julian Seward
11      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
31#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
33#include "pub_core_libcbase.h"
34#include "pub_core_libcassert.h"
35#include "pub_core_libcprint.h"
36#include "pub_core_libcproc.h"      // For VG_(gettid)()
37#include "pub_core_stacktrace.h"
38#include "pub_core_syscall.h"
39#include "pub_core_tooliface.h"     // For VG_(details).{name,bug_reports_to}
40#include "vki_unistd.h"
41
42/* ---------------------------------------------------------------------
43   Assertery.
44   ------------------------------------------------------------------ */
45
46#if defined(VGP_x86_linux)
47#  define GET_REAL_SP_AND_FP(sp, fp) \
48      asm("movl %%esp, %0;" \
49          "movl %%ebp, %1;" \
50          : "=r" (sp),\
51            "=r" (fp));
52#elif defined(VGP_amd64_linux)
53#  define GET_REAL_SP_AND_FP(sp, fp) \
54      asm("movq %%rsp, %0;" \
55          "movq %%rbp, %1;" \
56          : "=r" (sp),\
57            "=r" (fp));
58#elif defined(VGP_ppc32_linux)
59#  define GET_REAL_SP_AND_FP(sp, fp) \
60      asm("mr %0,1;" \
61          "mr %1,1;" \
62          : "=r" (sp),\
63            "=r" (fp));
64#else
65#  error Unknown platform
66#endif
67
68#define BACKTRACE_DEPTH    100         // nice and deep!
69
70/* Pull down the entire world */
71void VG_(exit)( Int status )
72{
73   (void)VG_(do_syscall1)(__NR_exit_group, status );
74   (void)VG_(do_syscall1)(__NR_exit, status );
75   /* Why are we still alive here? */
76   /*NOTREACHED*/
77   *(volatile Int *)0 = 'x';
78   vg_assert(2+2 == 5);
79}
80
81// Print the scheduler status.
82static void pp_sched_status ( void )
83{
84   Int i;
85   VG_(printf)("\nsched status:\n");
86   VG_(printf)("  running_tid=%d\n", VG_(get_running_tid)());
87   for (i = 1; i < VG_N_THREADS; i++) {
88      if (VG_(threads)[i].status == VgTs_Empty) continue;
89      VG_(printf)( "\nThread %d: status = %s\n", i,
90                   VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
91      VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
92   }
93   VG_(printf)("\n");
94}
95
96__attribute__ ((noreturn))
97static void report_and_quit ( const Char* report, Addr ip, Addr sp, Addr fp )
98{
99   Addr stacktop;
100   Addr ips[BACKTRACE_DEPTH];
101   ThreadState *tst = VG_(get_ThreadState)( VG_(get_lwp_tid)(VG_(gettid)()) );
102
103   // If necessary, fake up an ExeContext which is of our actual real CPU
104   // state.  Could cause problems if we got the panic/exception within the
105   // execontext/stack dump/symtab code.  But it's better than nothing.
106   if (0 == ip && 0 == sp && 0 == fp) {
107       ip = (Addr)__builtin_return_address(0);
108       GET_REAL_SP_AND_FP(sp, fp);
109   }
110
111   stacktop = tst->os_state.valgrind_stack_base +
112              tst->os_state.valgrind_stack_szB;
113
114   VG_(get_StackTrace2)(ips, BACKTRACE_DEPTH, ip, sp, fp, sp, stacktop);
115   VG_(pp_StackTrace)  (ips, BACKTRACE_DEPTH);
116
117   // Don't print this, as it's not terribly interesting and avoids a
118   // dependence on m_scheduler/, which would be crazy.
119   //VG_(printf)("\nBasic block ctr is approximately %llu\n", VG_(bbs_done) );
120
121   pp_sched_status();
122   VG_(printf)("\n");
123   VG_(printf)("Note: see also the FAQ.txt in the source distribution.\n");
124   VG_(printf)("It contains workarounds to several common problems.\n");
125   VG_(printf)("\n");
126   VG_(printf)("If that doesn't help, please report this bug to: %s\n\n",
127               report);
128   VG_(printf)("In the bug report, send all the above text, the valgrind\n");
129   VG_(printf)("version, and what Linux distro you are using.  Thanks.\n\n");
130   VG_(exit)(1);
131}
132
133void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
134                        Int line, const Char* fn, const HChar* format, ... )
135{
136   va_list vargs;
137   Char buf[256];
138   Char* component;
139   Char* bugs_to;
140
141   static Bool entered = False;
142   if (entered)
143     VG_(exit)(2);
144   entered = True;
145
146   va_start(vargs, format);
147   VG_(vsprintf) ( buf, format, vargs );
148   va_end(vargs);
149
150   if (isCore) {
151      component = "valgrind";
152      bugs_to   = VG_BUGS_TO;
153   } else {
154      component = VG_(details).name;
155      bugs_to   = VG_(details).bug_reports_to;
156   }
157
158   // Treat vg_assert2(0, "foo") specially, as a panicky abort
159   if (VG_STREQ(expr, "0")) {
160      VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
161                  component, file, line, fn, expr );
162   } else {
163      VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
164                  component, file, line, fn, expr );
165   }
166   if (!VG_STREQ(buf, ""))
167      VG_(printf)("%s: %s\n", component, buf );
168
169   report_and_quit(bugs_to, 0,0,0);
170}
171
172__attribute__ ((noreturn))
173static void panic ( Char* name, Char* report, Char* str,
174                    Addr ip, Addr sp, Addr fp )
175{
176   VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
177   report_and_quit(report, ip, sp, fp);
178}
179
180void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp )
181{
182   panic("valgrind", VG_BUGS_TO, str, ip, sp, fp);
183}
184
185void VG_(core_panic) ( Char* str )
186{
187   VG_(core_panic_at)(str, 0,0,0);
188}
189
190void VG_(tool_panic) ( Char* str )
191{
192   panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0);
193}
194
195/* Print some helpful-ish text about unimplemented things, and give up. */
196void VG_(unimplemented) ( Char* msg )
197{
198   VG_(message)(Vg_UserMsg, "");
199   VG_(message)(Vg_UserMsg,
200      "Valgrind detected that your program requires");
201   VG_(message)(Vg_UserMsg,
202      "the following unimplemented functionality:");
203   VG_(message)(Vg_UserMsg, "   %s", msg);
204   VG_(message)(Vg_UserMsg,
205      "This may be because the functionality is hard to implement,");
206   VG_(message)(Vg_UserMsg,
207      "or because no reasonable program would behave this way,");
208   VG_(message)(Vg_UserMsg,
209      "or because nobody has yet needed it.  In any case, let us know at");
210   VG_(message)(Vg_UserMsg,
211      "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
212   VG_(message)(Vg_UserMsg,
213      "");
214   VG_(message)(Vg_UserMsg,
215      "Valgrind has to exit now.  Sorry.  Bye!");
216   VG_(message)(Vg_UserMsg,
217      "");
218   pp_sched_status();
219   VG_(exit)(1);
220}
221
222/*--------------------------------------------------------------------*/
223/*--- end                                                          ---*/
224/*--------------------------------------------------------------------*/
225
226