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-2010 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) || defined(VGP_x86_darwin)
49#  define GET_STARTREGS(srP)                              \
50      { UInt eip, esp, ebp;                               \
51        __asm__ __volatile__(                             \
52           "call 0f;"                                     \
53           "0: popl %0;"                                  \
54           "movl %%esp, %1;"                              \
55           "movl %%ebp, %2;"                              \
56           : "=r" (eip), "=r" (esp), "=r" (ebp)           \
57           : /* reads none */                             \
58           : "memory"                                     \
59        );                                                \
60        (srP)->r_pc = (ULong)eip;                         \
61        (srP)->r_sp = (ULong)esp;                         \
62        (srP)->misc.X86.r_ebp = ebp;                      \
63      }
64#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
65#  define GET_STARTREGS(srP)                              \
66      { ULong rip, rsp, rbp;                              \
67        __asm__ __volatile__(                             \
68           "leaq 0(%%rip), %0;"                           \
69           "movq %%rsp, %1;"                              \
70           "movq %%rbp, %2;"                              \
71           : "=r" (rip), "=r" (rsp), "=r" (rbp)           \
72           : /* reads none */                             \
73           : "memory"                                     \
74        );                                                \
75        (srP)->r_pc = rip;                                \
76        (srP)->r_sp = rsp;                                \
77        (srP)->misc.AMD64.r_rbp = rbp;                    \
78      }
79#elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5)
80#  define GET_STARTREGS(srP)                              \
81      { UInt cia, r1, lr;                                 \
82        __asm__ __volatile__(                             \
83           "mflr 0;"                   /* r0 = lr */      \
84           "bl m_libcassert_get_ip;"   /* lr = pc */      \
85           "m_libcassert_get_ip:\n"                       \
86           "mflr %0;"                  /* %0 = pc */      \
87           "mtlr 0;"                   /* restore lr */   \
88           "mr %1,1;"                  /* %1 = r1 */      \
89           "mr %2,0;"                  /* %2 = lr */      \
90           : "=r" (cia), "=r" (r1), "=r" (lr)             \
91           : /* reads none */                             \
92           : "r0" /* trashed */                           \
93        );                                                \
94        (srP)->r_pc = (ULong)cia;                         \
95        (srP)->r_sp = (ULong)r1;                          \
96        (srP)->misc.PPC32.r_lr = lr;                      \
97      }
98#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
99#  define GET_STARTREGS(srP)                              \
100      { ULong cia, r1, lr;                                \
101        __asm__ __volatile__(                             \
102           "mflr 0;"                   /* r0 = lr */      \
103           "bl .m_libcassert_get_ip;"  /* lr = pc */      \
104           ".m_libcassert_get_ip:\n"                      \
105           "mflr %0;"                  /* %0 = pc */      \
106           "mtlr 0;"                   /* restore lr */   \
107           "mr %1,1;"                  /* %1 = r1 */      \
108           "mr %2,0;"                  /* %2 = lr */      \
109           : "=r" (cia), "=r" (r1), "=r" (lr)             \
110           : /* reads none */                             \
111           : "r0" /* trashed */                           \
112        );                                                \
113        (srP)->r_pc = cia;                                \
114        (srP)->r_sp = r1;                                 \
115        (srP)->misc.PPC64.r_lr = lr;                      \
116      }
117#elif defined(VGP_arm_linux)
118#  define GET_STARTREGS(srP)                              \
119      { UInt block[6];                                    \
120        __asm__ __volatile__(                             \
121           "str r15, [%0, #+0];"                          \
122           "str r14, [%0, #+4];"                          \
123           "str r13, [%0, #+8];"                          \
124           "str r12, [%0, #+12];"                         \
125           "str r11, [%0, #+16];"                         \
126           "str r7,  [%0, #+20];"                         \
127           : /* out */                                    \
128           : /* in */ "r"(&block[0])                      \
129           : /* trash */ "memory"                         \
130        );                                                \
131        (srP)->r_pc = block[0] - 8;                       \
132        (srP)->r_sp = block[1];                           \
133        (srP)->misc.ARM.r14 = block[2];                   \
134        (srP)->misc.ARM.r12 = block[3];                   \
135        (srP)->misc.ARM.r11 = block[4];                   \
136        (srP)->misc.ARM.r7  = block[5];                   \
137      }
138#else
139#  error Unknown platform
140#endif
141
142#define BACKTRACE_DEPTH    100         // nice and deep!
143
144/* Pull down the entire world */
145void VG_(exit)( Int status )
146{
147#if defined(VGO_linux)
148   (void)VG_(do_syscall1)(__NR_exit_group, status );
149#elif defined(VGO_aix5) || defined(VGO_darwin)
150   (void)VG_(do_syscall1)(__NR_exit, status );
151#else
152#  error Unknown OS
153#endif
154   /*NOTREACHED*/
155   // We really shouldn't reach here.  Just in case we do, use some very crude
156   // methods to force abort
157   __builtin_trap();
158   *(volatile Int*)0 = 'x';
159}
160
161// Print the scheduler status.
162void VG_(show_sched_status) ( void )
163{
164   Int i;
165   VG_(printf)("\nsched status:\n");
166   VG_(printf)("  running_tid=%d\n", VG_(get_running_tid)());
167   for (i = 1; i < VG_N_THREADS; i++) {
168      if (VG_(threads)[i].status == VgTs_Empty) continue;
169      VG_(printf)( "\nThread %d: status = %s\n", i,
170                   VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
171      VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
172   }
173   VG_(printf)("\n");
174}
175
176__attribute__ ((noreturn))
177static void report_and_quit ( const Char* report,
178                              UnwindStartRegs* startRegsIN )
179{
180   Addr stacktop;
181   Addr ips[BACKTRACE_DEPTH];
182   Int  n_ips;
183   ThreadState *tst
184      = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
185
186   // If necessary, fake up an ExeContext which is of our actual real CPU
187   // state.  Could cause problems if we got the panic/exception within the
188   // execontext/stack dump/symtab code.  But it's better than nothing.
189   UnwindStartRegs startRegs;
190   VG_(memset)(&startRegs, 0, sizeof(startRegs));
191
192   if (startRegsIN == NULL) {
193      GET_STARTREGS(&startRegs);
194   } else {
195      startRegs = *startRegsIN;
196   }
197
198   stacktop = tst->os_state.valgrind_stack_init_SP;
199
200   n_ips =
201      VG_(get_StackTrace_wrk)(
202         0/*tid is unknown*/,
203         ips, BACKTRACE_DEPTH,
204         NULL/*array to dump SP values in*/,
205         NULL/*array to dump FP values in*/,
206         &startRegs, stacktop
207      );
208   VG_(clo_xml) = False;
209   VG_(pp_StackTrace) (ips, n_ips);
210
211   VG_(show_sched_status)();
212   VG_(printf)(
213      "\n"
214      "Note: see also the FAQ in the source distribution.\n"
215      "It contains workarounds to several common problems.\n"
216      "In particular, if Valgrind aborted or crashed after\n"
217      "identifying problems in your program, there's a good chance\n"
218      "that fixing those problems will prevent Valgrind aborting or\n"
219      "crashing, especially if it happened in m_mallocfree.c.\n"
220      "\n"
221      "If that doesn't help, please report this bug to: %s\n\n"
222      "In the bug report, send all the above text, the valgrind\n"
223      "version, and what OS and version you are using.  Thanks.\n\n",
224      report);
225   VG_(exit)(1);
226}
227
228void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
229                        Int line, const Char* fn, const HChar* format, ... )
230{
231   va_list vargs;
232   Char buf[256];
233   Char* component;
234   Char* bugs_to;
235
236   static Bool entered = False;
237   if (entered)
238      VG_(exit)(2);
239   entered = True;
240
241   va_start(vargs, format);
242   VG_(vsprintf) ( buf, format, vargs );
243   va_end(vargs);
244
245   if (isCore) {
246      component = "valgrind";
247      bugs_to   = VG_BUGS_TO;
248   } else {
249      component = VG_(details).name;
250      bugs_to   = VG_(details).bug_reports_to;
251   }
252
253   if (VG_(clo_xml))
254      VG_(printf_xml)("</valgrindoutput>\n");
255
256   // Treat vg_assert2(0, "foo") specially, as a panicky abort
257   if (VG_STREQ(expr, "0")) {
258      VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
259                  component, file, line, fn );
260   } else {
261      VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
262                  component, file, line, fn, expr );
263   }
264   if (!VG_STREQ(buf, ""))
265      VG_(printf)("%s: %s\n", component, buf );
266
267   report_and_quit(bugs_to, NULL);
268}
269
270__attribute__ ((noreturn))
271static void panic ( Char* name, Char* report, Char* str,
272                    UnwindStartRegs* startRegs )
273{
274   if (VG_(clo_xml))
275      VG_(printf_xml)("</valgrindoutput>\n");
276   VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
277   report_and_quit(report, startRegs);
278}
279
280void VG_(core_panic_at) ( Char* str, UnwindStartRegs* startRegs )
281{
282   panic("valgrind", VG_BUGS_TO, str, startRegs);
283}
284
285void VG_(core_panic) ( Char* str )
286{
287   VG_(core_panic_at)(str, NULL);
288}
289
290void VG_(tool_panic) ( Char* str )
291{
292   panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
293}
294
295/* Print some helpful-ish text about unimplemented things, and give up. */
296void VG_(unimplemented) ( Char* msg )
297{
298   if (VG_(clo_xml))
299      VG_(printf_xml)("</valgrindoutput>\n");
300   VG_(umsg)("\n");
301   VG_(umsg)("Valgrind detected that your program requires\n");
302   VG_(umsg)("the following unimplemented functionality:\n");
303   VG_(umsg)("   %s\n", msg);
304   VG_(umsg)("This may be because the functionality is hard to implement,\n");
305   VG_(umsg)("or because no reasonable program would behave this way,\n");
306   VG_(umsg)("or because nobody has yet needed it.  "
307             "In any case, let us know at\n");
308   VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
309             VG_BUGS_TO);
310   VG_(umsg)("\n");
311   VG_(umsg)("Valgrind has to exit now.  Sorry.  Bye!\n");
312   VG_(umsg)("\n");
313   VG_(show_sched_status)();
314   VG_(exit)(1);
315}
316
317/*--------------------------------------------------------------------*/
318/*--- end                                                          ---*/
319/*--------------------------------------------------------------------*/
320
321