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-2015 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_gdbserver.h"
36#include "pub_core_aspacemgr.h"
37#include "pub_core_libcbase.h"
38#include "pub_core_libcassert.h"
39#include "pub_core_libcprint.h"
40#include "pub_core_libcproc.h"      // For VG_(gettid)()
41#include "pub_core_machine.h"
42#include "pub_core_stacks.h"
43#include "pub_core_stacktrace.h"
44#include "pub_core_syscall.h"
45#include "pub_core_tooliface.h"     // For VG_(details).{name,bug_reports_to}
46#include "pub_core_options.h"       // For VG_(clo_xml)
47
48/* ---------------------------------------------------------------------
49   Assertery.
50   ------------------------------------------------------------------ */
51
52#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) \
53    || defined(VGP_x86_solaris)
54#  define GET_STARTREGS(srP)                              \
55      { UInt eip, esp, ebp;                               \
56        __asm__ __volatile__(                             \
57           "call 0f;"                                     \
58           "0: popl %0;"                                  \
59           "movl %%esp, %1;"                              \
60           "movl %%ebp, %2;"                              \
61           : "=r" (eip), "=r" (esp), "=r" (ebp)           \
62           : /* reads none */                             \
63           : "memory"                                     \
64        );                                                \
65        (srP)->r_pc = (ULong)eip;                         \
66        (srP)->r_sp = (ULong)esp;                         \
67        (srP)->misc.X86.r_ebp = ebp;                      \
68      }
69#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) \
70      || defined(VGP_amd64_solaris)
71#  define GET_STARTREGS(srP)                              \
72      { ULong rip, rsp, rbp;                              \
73        __asm__ __volatile__(                             \
74           "leaq 0(%%rip), %0;"                           \
75           "movq %%rsp, %1;"                              \
76           "movq %%rbp, %2;"                              \
77           : "=r" (rip), "=r" (rsp), "=r" (rbp)           \
78           : /* reads none */                             \
79           : "memory"                                     \
80        );                                                \
81        (srP)->r_pc = rip;                                \
82        (srP)->r_sp = rsp;                                \
83        (srP)->misc.AMD64.r_rbp = rbp;                    \
84      }
85#elif defined(VGP_ppc32_linux)
86#  define GET_STARTREGS(srP)                              \
87      { UInt cia, r1, lr;                                 \
88        __asm__ __volatile__(                             \
89           "mflr 0;"                   /* r0 = lr */      \
90           "bl 0f;"                    /* lr = pc */      \
91           "0:\n"                                         \
92           "mflr %0;"                  /* %0 = pc */      \
93           "mtlr 0;"                   /* restore lr */   \
94           "mr %1,1;"                  /* %1 = r1 */      \
95           "mr %2,0;"                  /* %2 = lr */      \
96           : "=r" (cia), "=r" (r1), "=r" (lr)             \
97           : /* reads none */                             \
98           : "r0" /* trashed */                           \
99        );                                                \
100        (srP)->r_pc = (ULong)cia;                         \
101        (srP)->r_sp = (ULong)r1;                          \
102        (srP)->misc.PPC32.r_lr = lr;                      \
103      }
104#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
105#  define GET_STARTREGS(srP)                              \
106      { ULong cia, r1, lr;                                \
107        __asm__ __volatile__(                             \
108           "mflr 0;"                   /* r0 = lr */      \
109           "bl 0f;"                    /* lr = pc */      \
110           "0:\n"                                         \
111           "mflr %0;"                  /* %0 = pc */      \
112           "mtlr 0;"                   /* restore lr */   \
113           "mr %1,1;"                  /* %1 = r1 */      \
114           "mr %2,0;"                  /* %2 = lr */      \
115           : "=r" (cia), "=r" (r1), "=r" (lr)             \
116           : /* reads none */                             \
117           : "r0" /* trashed */                           \
118        );                                                \
119        (srP)->r_pc = cia;                                \
120        (srP)->r_sp = r1;                                 \
121        (srP)->misc.PPC64.r_lr = lr;                      \
122      }
123#elif defined(VGP_arm_linux)
124#  define GET_STARTREGS(srP)                              \
125      { UInt block[6];                                    \
126        __asm__ __volatile__(                             \
127           "str r15, [%0, #+0];"                          \
128           "str r14, [%0, #+4];"                          \
129           "str r13, [%0, #+8];"                          \
130           "str r12, [%0, #+12];"                         \
131           "str r11, [%0, #+16];"                         \
132           "str r7,  [%0, #+20];"                         \
133           : /* out */                                    \
134           : /* in */ "r"(&block[0])                      \
135           : /* trash */ "memory"                         \
136        );                                                \
137        (srP)->r_pc = block[0] - 8;                       \
138        (srP)->misc.ARM.r14 = block[1];                   \
139        (srP)->r_sp = block[2];                           \
140        (srP)->misc.ARM.r12 = block[3];                   \
141        (srP)->misc.ARM.r11 = block[4];                   \
142        (srP)->misc.ARM.r7  = block[5];                   \
143      }
144#elif defined(VGP_arm64_linux)
145#  define GET_STARTREGS(srP)                              \
146      { ULong block[4];                                   \
147        __asm__ __volatile__(                             \
148           "adr x19, 0;"                                  \
149           "str x19, [%0, #+0];"   /* pc */               \
150           "mov x19, sp;"                                 \
151           "str x19, [%0, #+8];"   /* sp */               \
152           "str x29, [%0, #+16];"  /* fp */               \
153           "str x30, [%0, #+24];"  /* lr */               \
154           : /* out */                                    \
155           : /* in */ "r"(&block[0])                      \
156           : /* trash */ "memory","x19"                   \
157        );                                                \
158        (srP)->r_pc = block[0];                           \
159        (srP)->r_sp = block[1];                           \
160        (srP)->misc.ARM64.x29 = block[2];                 \
161        (srP)->misc.ARM64.x30 = block[3];                 \
162      }
163#elif defined(VGP_s390x_linux)
164#  define GET_STARTREGS(srP)                              \
165      { ULong ia, sp, fp, lr;                             \
166        __asm__ __volatile__(                             \
167           "bras %0,0f;"                                  \
168           "0: lgr %1,15;"                                \
169           "lgr %2,11;"                                   \
170           "lgr %3,14;"                                   \
171           : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr)     \
172           /* no read & clobber */                        \
173        );                                                \
174        (srP)->r_pc = ia;                                 \
175        (srP)->r_sp = sp;                                 \
176        (srP)->misc.S390X.r_fp = fp;                      \
177        (srP)->misc.S390X.r_lr = lr;                      \
178      }
179#elif defined(VGP_mips32_linux)
180#  define GET_STARTREGS(srP)                              \
181      { UInt pc, sp, fp, ra, gp;                          \
182      asm("move $8, $31;"             /* t0 = ra */       \
183          "bal 0f;"                   /* ra = pc */       \
184          "0:\n"                                          \
185          "move %0, $31;"                                 \
186          "move $31, $8;"             /* restore lr */    \
187          "move %1, $29;"                                 \
188          "move %2, $30;"                                 \
189          "move %3, $31;"                                 \
190          "move %4, $28;"                                 \
191          : "=r" (pc),                                    \
192            "=r" (sp),                                    \
193            "=r" (fp),                                    \
194            "=r" (ra),                                    \
195            "=r" (gp)                                     \
196          : /* reads none */                              \
197          : "$8" /* trashed */ );                         \
198        (srP)->r_pc = (ULong)pc - 8;                      \
199        (srP)->r_sp = (ULong)sp;                          \
200        (srP)->misc.MIPS32.r30 = (ULong)fp;               \
201        (srP)->misc.MIPS32.r31 = (ULong)ra;               \
202        (srP)->misc.MIPS32.r28 = (ULong)gp;               \
203      }
204#elif defined(VGP_mips64_linux)
205#  define GET_STARTREGS(srP)                              \
206      { ULong pc, sp, fp, ra, gp;                         \
207      asm("move $8, $31;"             /* t0 = ra */       \
208          "bal 0f;"                   /* ra = pc */       \
209          "0:\n"                                          \
210          "move %0, $31;"                                 \
211          "move $31, $8;"             /* restore lr */    \
212          "move %1, $29;"                                 \
213          "move %2, $30;"                                 \
214          "move %3, $31;"                                 \
215          "move %4, $28;"                                 \
216          : "=r" (pc),                                    \
217            "=r" (sp),                                    \
218            "=r" (fp),                                    \
219            "=r" (ra),                                    \
220            "=r" (gp)                                     \
221          : /* reads none */                              \
222          : "$8" /* trashed */ );                         \
223        (srP)->r_pc = (ULong)pc - 8;                      \
224        (srP)->r_sp = (ULong)sp;                          \
225        (srP)->misc.MIPS64.r30 = (ULong)fp;               \
226        (srP)->misc.MIPS64.r31 = (ULong)ra;               \
227        (srP)->misc.MIPS64.r28 = (ULong)gp;               \
228      }
229#elif defined(VGP_tilegx_linux)
230#  define GET_STARTREGS(srP)                              \
231      { ULong pc, sp, fp, ra;                              \
232        __asm__ __volatile__(                             \
233          "move r8, lr \n"                                \
234          "jal 0f \n"                                     \
235          "0:\n"                                          \
236          "move %0, lr \n"                                \
237          "move lr, r8 \n"      /* put old lr back*/      \
238          "move %1, sp \n"                                \
239          "move %2, r52 \n"                               \
240          "move %3, lr \n"                                \
241          : "=r" (pc),                                    \
242            "=r" (sp),                                    \
243            "=r" (fp),                                    \
244            "=r" (ra)                                     \
245          : /* reads none */                              \
246          : "%r8" /* trashed */ );                        \
247        (srP)->r_pc = (ULong)pc - 8;                      \
248        (srP)->r_sp = (ULong)sp;                          \
249        (srP)->misc.TILEGX.r52 = (ULong)fp;               \
250        (srP)->misc.TILEGX.r55 = (ULong)ra;               \
251      }
252#else
253#  error Unknown platform
254#endif
255
256#define BACKTRACE_DEPTH    100         // nice and deep!
257
258__attribute__ ((__noreturn__))
259static void exit_wrk( Int status, Bool gdbserver_call_allowed)
260{
261   static Bool exit_called = False;
262   // avoid recursive exit during gdbserver call.
263
264   if (gdbserver_call_allowed && !exit_called) {
265      const ThreadId atid = 1; // Arbitrary tid used to call/terminate gdbsrv.
266      exit_called = True;
267      if (status != 0 && VG_(gdbserver_stop_at) (VgdbStopAt_ValgrindAbExit)) {
268         if (VG_(gdbserver_init_done)()) {
269            VG_(umsg)("(action at valgrind abnormal exit) vgdb me ... \n");
270            VG_(gdbserver) (atid);
271         } else {
272            VG_(umsg)("(action at valgrind abnormal exit) "
273                      "Early valgrind exit : vgdb not yet usable\n");
274         }
275      }
276      if (VG_(gdbserver_init_done)()) {
277         // Always terminate the gdbserver when Valgrind exits, so as
278         // to e.g. cleanup the FIFOs.
279         VG_(gdbserver_exit) (atid,
280                              status == 0 ? VgSrc_ExitProcess : VgSrc_FatalSig);
281      }
282   }
283   exit_called = True;
284
285   VG_(exit_now) (status);
286}
287
288/* Call the appropriate system call and nothing else. This function should
289   be called in places where the dependencies of VG_(exit) need to be
290   avoided. */
291__attribute__ ((__noreturn__))
292void VG_(exit_now)( Int status )
293{
294#if defined(VGO_linux)
295   (void)VG_(do_syscall1)(__NR_exit_group, status );
296#elif defined(VGO_darwin) || defined(VGO_solaris)
297   (void)VG_(do_syscall1)(__NR_exit, status );
298#else
299#  error Unknown OS
300#endif
301   /*NOTREACHED*/
302   // We really shouldn't reach here.  Just in case we do, use some very crude
303   // methods to force abort
304   __builtin_trap();
305   *(volatile Int*)0 = 'x';
306}
307
308/* Pull down the entire world */
309void VG_(exit)( Int status )
310{
311   exit_wrk (status, True);
312}
313
314/* Pull down the entire world */
315void VG_(client_exit)( Int status )
316{
317   exit_wrk (status, False);
318}
319
320
321// Print the scheduler status.
322static void show_sched_status_wrk ( Bool host_stacktrace,
323                                    Bool stack_usage,
324                                    Bool exited_threads,
325                                    const UnwindStartRegs* startRegsIN)
326{
327   Int i;
328   if (host_stacktrace) {
329      const Bool save_clo_xml = VG_(clo_xml);
330      Addr stacktop;
331      Addr ips[BACKTRACE_DEPTH];
332      Int  n_ips;
333      ThreadState *tst
334         = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
335
336      // If necessary, fake up an ExeContext which is of our actual real CPU
337      // state.  Could cause problems if we got the panic/exception within the
338      // execontext/stack dump/symtab code.  But it's better than nothing.
339      UnwindStartRegs startRegs;
340      VG_(memset)(&startRegs, 0, sizeof(startRegs));
341
342      if (startRegsIN == NULL) {
343         GET_STARTREGS(&startRegs);
344      } else {
345         startRegs = *startRegsIN;
346      }
347
348      stacktop = tst->os_state.valgrind_stack_init_SP;
349
350      n_ips =
351         VG_(get_StackTrace_wrk)(
352            0/*tid is unknown*/,
353            ips, BACKTRACE_DEPTH,
354            NULL/*array to dump SP values in*/,
355            NULL/*array to dump FP values in*/,
356            &startRegs, stacktop
357         );
358      VG_(printf)("\nhost stacktrace:\n");
359      VG_(clo_xml) = False;
360      VG_(pp_StackTrace) (ips, n_ips);
361      VG_(clo_xml) = save_clo_xml;
362   }
363
364   VG_(printf)("\nsched status:\n");
365   VG_(printf)("  running_tid=%u\n", VG_(get_running_tid)());
366   for (i = 1; i < VG_N_THREADS; i++) {
367      VgStack* stack
368         = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
369      /* If a thread slot was never used (yet), valgrind_stack_base is 0.
370         If a thread slot is used by a thread or was used by a thread which
371         has exited, then valgrind_stack_base points to the stack base. */
372      if (VG_(threads)[i].status == VgTs_Empty
373          && (!exited_threads || stack == 0)) continue;
374      VG_(printf)("\nThread %d: status = %s (lwpid %d)\n", i,
375                  VG_(name_of_ThreadStatus)(VG_(threads)[i].status),
376                  VG_(threads)[i].os_state.lwpid);
377      if (VG_(threads)[i].status != VgTs_Empty)
378         VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
379      if (stack_usage && VG_(threads)[i].client_stack_highest_byte != 0 ) {
380         Addr start, end;
381
382         start = end = 0;
383         VG_(stack_limits)(VG_(threads)[i].client_stack_highest_byte,
384                           &start, &end);
385         if (start != end)
386            VG_(printf)("client stack range: [%p %p] client SP: %p\n",
387                        (void*)start, (void*)end, (void*)VG_(get_SP)(i));
388         else
389            VG_(printf)("client stack range: ???????\n");
390      }
391      if (stack_usage && stack != 0)
392          VG_(printf)("valgrind stack top usage: %lu of %lu\n",
393                      VG_(clo_valgrind_stacksize)
394                        - VG_(am_get_VgStack_unused_szB)
395                               (stack, VG_(clo_valgrind_stacksize)),
396                      (SizeT) VG_(clo_valgrind_stacksize));
397   }
398   VG_(printf)("\n");
399}
400
401void VG_(show_sched_status) ( Bool host_stacktrace,
402                              Bool stack_usage,
403                              Bool exited_threads)
404{
405   show_sched_status_wrk (host_stacktrace,
406                          stack_usage,
407                          exited_threads,
408                          NULL);
409}
410
411__attribute__ ((noreturn))
412static void report_and_quit ( const HChar* report,
413                              const UnwindStartRegs* startRegsIN )
414{
415   show_sched_status_wrk (True,  // host_stacktrace
416                          False, // stack_usage
417                          False, // exited_threads
418                          startRegsIN);
419   VG_(printf)(
420      "\n"
421      "Note: see also the FAQ in the source distribution.\n"
422      "It contains workarounds to several common problems.\n"
423      "In particular, if Valgrind aborted or crashed after\n"
424      "identifying problems in your program, there's a good chance\n"
425      "that fixing those problems will prevent Valgrind aborting or\n"
426      "crashing, especially if it happened in m_mallocfree.c.\n"
427      "\n"
428      "If that doesn't help, please report this bug to: %s\n\n"
429      "In the bug report, send all the above text, the valgrind\n"
430      "version, and what OS and version you are using.  Thanks.\n\n",
431      report);
432   VG_(exit)(1);
433}
434
435void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
436                        Int line, const HChar* fn, const HChar* format, ... )
437{
438   va_list vargs, vargs_copy;
439   const HChar* component;
440   const HChar* bugs_to;
441   UInt written;
442
443   static Bool entered = False;
444   if (entered)
445      VG_(exit)(2);
446   entered = True;
447
448   if (isCore) {
449      component = "valgrind";
450      bugs_to   = VG_BUGS_TO;
451   } else {
452      component = VG_(details).name;
453      bugs_to   = VG_(details).bug_reports_to;
454   }
455
456   if (VG_(clo_xml))
457      VG_(printf_xml)("</valgrindoutput>\n");
458
459   // Treat vg_assert2(0, "foo") specially, as a panicky abort
460   if (VG_STREQ(expr, "0")) {
461      VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
462                  component, file, line, fn );
463   } else {
464      VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
465                  component, file, line, fn, expr );
466   }
467
468   /* Check whether anything will be written */
469   HChar buf[5];
470   va_start(vargs, format);
471   va_copy(vargs_copy, vargs);
472   written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
473   va_end(vargs);
474
475   if (written > 0) {
476      VG_(printf)("%s: ", component);
477      VG_(vprintf)(format, vargs_copy);
478      VG_(printf)("\n");
479   }
480
481   report_and_quit(bugs_to, NULL);
482}
483
484__attribute__ ((noreturn))
485static void panic ( const HChar* name, const HChar* report, const HChar* str,
486                    const UnwindStartRegs* startRegs )
487{
488   if (VG_(clo_xml))
489      VG_(printf_xml)("</valgrindoutput>\n");
490   VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
491   report_and_quit(report, startRegs);
492}
493
494void VG_(core_panic_at) ( const HChar* str, const UnwindStartRegs* startRegs )
495{
496   panic("valgrind", VG_BUGS_TO, str, startRegs);
497}
498
499void VG_(core_panic) ( const HChar* str )
500{
501   VG_(core_panic_at)(str, NULL);
502}
503
504void VG_(tool_panic) ( const HChar* str )
505{
506   panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
507}
508
509/* Print some helpful-ish text about unimplemented things, and give up. */
510void VG_(unimplemented) ( const HChar* format, ... )
511{
512   va_list vargs;
513   HChar msg[256];
514
515   va_start(vargs, format);
516   VG_(vsnprintf)(msg, sizeof(msg), format, vargs);
517   va_end(vargs);
518
519   if (VG_(clo_xml))
520      VG_(printf_xml)("</valgrindoutput>\n");
521   VG_(umsg)("\n");
522   VG_(umsg)("Valgrind detected that your program requires\n");
523   VG_(umsg)("the following unimplemented functionality:\n");
524   VG_(umsg)("   %s\n", msg);
525   VG_(umsg)("This may be because the functionality is hard to implement,\n");
526   VG_(umsg)("or because no reasonable program would behave this way,\n");
527   VG_(umsg)("or because nobody has yet needed it.  "
528             "In any case, let us know at\n");
529   VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
530             VG_BUGS_TO);
531   VG_(umsg)("\n");
532   VG_(umsg)("Valgrind has to exit now.  Sorry.  Bye!\n");
533   VG_(umsg)("\n");
534   VG_(show_sched_status)(False,  // host_stacktrace
535                          False,  // stack_usage
536                          False); // exited_threads
537   VG_(exit)(1);
538}
539
540/*--------------------------------------------------------------------*/
541/*--- end                                                          ---*/
542/*--------------------------------------------------------------------*/
543