m_libcassert.c revision 5f5ef2ae9e7c2ce5ebc36c1e2fc98e5f81650be3
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-2009 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_vki.h"
33#include "pub_core_vkiscnums.h"
34#include "pub_core_threadstate.h"
35#include "pub_core_libcbase.h"
36#include "pub_core_libcassert.h"
37#include "pub_core_libcprint.h"
38#include "pub_core_libcproc.h"      // For VG_(gettid)()
39#include "pub_core_stacktrace.h"
40#include "pub_core_syscall.h"
41#include "pub_core_tooliface.h"     // For VG_(details).{name,bug_reports_to}
42#include "pub_core_options.h"       // For VG_(clo_xml)
43
44/* ---------------------------------------------------------------------
45   Assertery.
46   ------------------------------------------------------------------ */
47
48#if defined(VGP_x86_linux)
49#  define GET_REAL_PC_SP_AND_FP(pc, sp, fp)      \
50      asm("call 0f;" \
51          "0: popl %0;" \
52          "movl %%esp, %1;" \
53          "movl %%ebp, %2;" \
54          : "=r" (pc),\
55            "=r" (sp),\
56            "=r" (fp));
57#elif defined(VGP_amd64_linux)
58#  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),\
64            "=r" (fp));
65#elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5)
66#  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 */ );
79#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
80#  define GET_REAL_PC_SP_AND_FP(pc, sp, fp)                   \
81      asm("mflr 0;"                   /* r0 = lr */           \
82          "bl .m_libcassert_get_ip;"  /* lr = pc */           \
83          ".m_libcassert_get_ip:\n"                           \
84          "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 */ );
93#else
94#  error Unknown platform
95#endif
96
97#define BACKTRACE_DEPTH    100         // nice and deep!
98
99/* Pull down the entire world */
100void VG_(exit)( Int status )
101{
102#  if defined(VGO_linux)
103   (void)VG_(do_syscall1)(__NR_exit_group, status );
104#  endif
105   (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
112// Print the scheduler status.
113void VG_(show_sched_status) ( void )
114{
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}
126
127__attribute__ ((noreturn))
128static void report_and_quit ( const Char* report,
129                              Addr ip, Addr sp, Addr fp, Addr lr )
130{
131   Addr stacktop;
132   Addr ips[BACKTRACE_DEPTH];
133   Int  n_ips;
134   ThreadState *tst
135      = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
136
137   // If necessary, fake up an ExeContext which is of our actual real CPU
138   // state.  Could cause problems if we got the panic/exception within the
139   // execontext/stack dump/symtab code.  But it's better than nothing.
140   if (0 == ip && 0 == sp && 0 == fp) {
141       GET_REAL_PC_SP_AND_FP(ip, sp, fp);
142   }
143
144   stacktop = tst->os_state.valgrind_stack_init_SP;
145
146   n_ips =
147      VG_(get_StackTrace_wrk)(
148         0/*tid is unknown*/,
149         ips, BACKTRACE_DEPTH,
150         NULL/*array to dump SP values in*/,
151         NULL/*array to dump FP values in*/,
152         ip, sp, fp, lr, sp, stacktop
153      );
154   VG_(pp_StackTrace) (ips, n_ips);
155
156   VG_(show_sched_status)();
157   VG_(printf)(
158      "\n"
159      "Note: see also the FAQ in the source distribution.\n"
160      "It contains workarounds to several common problems.\n"
161      "In particular, if Valgrind aborted or crashed after\n"
162      "identifying problems in your program, there's a good chance\n"
163      "that fixing those problems will prevent Valgrind aborting or\n"
164      "crashing, especially if it happened in m_mallocfree.c.\n"
165      "\n"
166      "If that doesn't help, please report this bug to: %s\n\n"
167      "In the bug report, send all the above text, the valgrind\n"
168      "version, and what OS and version you are using.  Thanks.\n\n",
169      report);
170   VG_(exit)(1);
171}
172
173void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
174                        Int line, const Char* fn, const HChar* format, ... )
175{
176   va_list vargs;
177   Char buf[256];
178   Char* component;
179   Char* bugs_to;
180
181   static Bool entered = False;
182   if (entered)
183      VG_(exit)(2);
184   entered = True;
185
186   va_start(vargs, format);
187   VG_(vsprintf) ( buf, format, vargs );
188   va_end(vargs);
189
190   if (isCore) {
191      component = "valgrind";
192      bugs_to   = VG_BUGS_TO;
193   } else {
194      component = VG_(details).name;
195      bugs_to   = VG_(details).bug_reports_to;
196   }
197
198   if (VG_(clo_xml))
199      VG_UMSG("</valgrindoutput>\n");
200
201   // Treat vg_assert2(0, "foo") specially, as a panicky abort
202   if (VG_STREQ(expr, "0")) {
203      VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
204                  component, file, line, fn );
205   } else {
206      VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
207                  component, file, line, fn, expr );
208   }
209   if (!VG_STREQ(buf, ""))
210      VG_(printf)("%s: %s\n", component, buf );
211
212   report_and_quit(bugs_to, 0,0,0,0);
213}
214
215__attribute__ ((noreturn))
216static void panic ( Char* name, Char* report, Char* str,
217                    Addr ip, Addr sp, Addr fp, Addr lr )
218{
219   if (VG_(clo_xml))
220      VG_UMSG("</valgrindoutput>\n");
221   VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
222   report_and_quit(report, ip, sp, fp, lr);
223}
224
225void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp, Addr lr )
226{
227   panic("valgrind", VG_BUGS_TO, str, ip, sp, fp, lr);
228}
229
230void VG_(core_panic) ( Char* str )
231{
232   VG_(core_panic_at)(str, 0,0,0,0);
233}
234
235void VG_(tool_panic) ( Char* str )
236{
237   panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0,0);
238}
239
240/* Print some helpful-ish text about unimplemented things, and give up. */
241void VG_(unimplemented) ( Char* msg )
242{
243   if (VG_(clo_xml))
244      VG_UMSG("</valgrindoutput>\n");
245   VG_UMSG("");
246   VG_UMSG("Valgrind detected that your program requires");
247   VG_UMSG("the following unimplemented functionality:");
248   VG_UMSG("   %s", msg);
249   VG_UMSG("This may be because the functionality is hard to implement,");
250   VG_UMSG("or because no reasonable program would behave this way,");
251   VG_UMSG("or because nobody has yet needed it.  In any case, let us know at");
252   VG_UMSG("%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
253   VG_UMSG("");
254   VG_UMSG("Valgrind has to exit now.  Sorry.  Bye!");
255   VG_UMSG("");
256   VG_(show_sched_status)();
257   VG_(exit)(1);
258}
259
260/*--------------------------------------------------------------------*/
261/*--- end                                                          ---*/
262/*--------------------------------------------------------------------*/
263
264