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-2017 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#else
230#  error Unknown platform
231#endif
232
233#define BACKTRACE_DEPTH    100         // nice and deep!
234
235__attribute__ ((__noreturn__))
236static void exit_wrk( Int status, Bool gdbserver_call_allowed)
237{
238   static Bool exit_called = False;
239   // avoid recursive exit during gdbserver call.
240
241   if (gdbserver_call_allowed && !exit_called) {
242      const ThreadId atid = 1; // Arbitrary tid used to call/terminate gdbsrv.
243      exit_called = True;
244      if (status != 0
245          && VgdbStopAtiS(VgdbStopAt_ValgrindAbExit, VG_(clo_vgdb_stop_at))) {
246         if (VG_(gdbserver_init_done)()) {
247            VG_(umsg)("(action at valgrind abnormal exit) vgdb me ... \n");
248            VG_(gdbserver) (atid);
249         } else {
250            VG_(umsg)("(action at valgrind abnormal exit)\n"
251                      "valgrind exit is too early => vgdb not yet usable\n");
252         }
253      }
254      if (VG_(gdbserver_init_done)()) {
255         // Always terminate the gdbserver when Valgrind exits, so as
256         // to e.g. cleanup the FIFOs.
257         VG_(gdbserver_exit) (atid,
258                              status == 0 ? VgSrc_ExitProcess : VgSrc_FatalSig);
259      }
260   }
261   exit_called = True;
262
263   VG_(exit_now) (status);
264}
265
266/* Call the appropriate system call and nothing else. This function should
267   be called in places where the dependencies of VG_(exit) need to be
268   avoided. */
269__attribute__ ((__noreturn__))
270void VG_(exit_now)( Int status )
271{
272#if defined(VGO_linux)
273   (void)VG_(do_syscall1)(__NR_exit_group, status );
274#elif defined(VGO_darwin) || defined(VGO_solaris)
275   (void)VG_(do_syscall1)(__NR_exit, status );
276#else
277#  error Unknown OS
278#endif
279   /*NOTREACHED*/
280   // We really shouldn't reach here.  Just in case we do, use some very crude
281   // methods to force abort
282   __builtin_trap();
283   *(volatile Int*)0 = 'x';
284}
285
286/* Pull down the entire world */
287void VG_(exit)( Int status )
288{
289   exit_wrk (status, True);
290}
291
292/* Pull down the entire world */
293void VG_(client_exit)( Int status )
294{
295   exit_wrk (status, False);
296}
297
298static void print_thread_state (Bool stack_usage,
299                                const HChar* prefix, ThreadId i)
300{
301   VgStack *stack
302      = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
303
304   VG_(printf)("\n%sThread %d: status = %s (lwpid %d)\n", prefix, i,
305               VG_(name_of_ThreadStatus)(VG_(threads)[i].status),
306               VG_(threads)[i].os_state.lwpid);
307   if (VG_(threads)[i].status != VgTs_Empty)
308      VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
309   if (stack_usage && VG_(threads)[i].client_stack_highest_byte != 0 ) {
310      Addr start, end;
311
312      start = end = 0;
313      VG_(stack_limits)(VG_(get_SP)(i), &start, &end);
314      if (start != end)
315         VG_(printf)("%sclient stack range: [%p %p] client SP: %p\n",
316                     prefix,
317                     (void*)start, (void*)end, (void*)VG_(get_SP)(i));
318      else
319         VG_(printf)("%sclient stack range: ??????? client SP: %p\n",
320                     prefix,
321                     (void*)VG_(get_SP)(i));
322   }
323   if (stack_usage && stack != 0)
324      VG_(printf)
325         ("%svalgrind stack top usage: %lu of %lu\n",
326          prefix,
327          VG_(clo_valgrind_stacksize)
328          - VG_(am_get_VgStack_unused_szB) (stack,
329                                            VG_(clo_valgrind_stacksize)),
330          (SizeT) VG_(clo_valgrind_stacksize));
331}
332
333// Print the scheduler status.
334static void show_sched_status_wrk ( Bool host_stacktrace,
335                                    Bool stack_usage,
336                                    Bool exited_threads,
337                                    const UnwindStartRegs* startRegsIN)
338{
339   Int i;
340   if (host_stacktrace) {
341      const Bool save_clo_xml = VG_(clo_xml);
342      Addr stacktop;
343      Addr ips[BACKTRACE_DEPTH];
344      Int  n_ips;
345      ThreadState *tst
346         = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
347
348      // If necessary, fake up an ExeContext which is of our actual real CPU
349      // state.  Could cause problems if we got the panic/exception within the
350      // execontext/stack dump/symtab code.  But it's better than nothing.
351      UnwindStartRegs startRegs;
352      VG_(memset)(&startRegs, 0, sizeof(startRegs));
353
354      if (startRegsIN == NULL) {
355         GET_STARTREGS(&startRegs);
356      } else {
357         startRegs = *startRegsIN;
358      }
359
360      stacktop = tst->os_state.valgrind_stack_init_SP;
361
362      n_ips =
363         VG_(get_StackTrace_wrk)(
364            0/*tid is unknown*/,
365            ips, BACKTRACE_DEPTH,
366            NULL/*array to dump SP values in*/,
367            NULL/*array to dump FP values in*/,
368            &startRegs, stacktop
369         );
370      VG_(printf)("\nhost stacktrace:\n");
371      VG_(clo_xml) = False;
372      VG_(pp_StackTrace) (ips, n_ips);
373      VG_(clo_xml) = save_clo_xml;
374   }
375
376   VG_(printf)("\nsched status:\n");
377   if (VG_(threads) == NULL) {
378      VG_(printf)("  scheduler not yet initialised\n");
379   } else {
380      VG_(printf)("  running_tid=%u\n", VG_(get_running_tid)());
381      for (i = 1; i < VG_N_THREADS; i++) {
382         VgStack *stack
383            = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
384         /* If a thread slot was never used (yet), valgrind_stack_base is 0.
385            If a thread slot is used by a thread or was used by a thread which
386            has exited, then valgrind_stack_base points to the stack base. */
387         if (VG_(threads)[i].status == VgTs_Empty
388             && (!exited_threads || stack == 0)) continue;
389         print_thread_state(stack_usage, "", i);
390         if (VG_(inner_threads) != NULL) {
391            /* An inner V has informed us (the outer) of its thread array.
392               Report the inner guest stack trace. */
393            UInt inner_tid;
394
395            for (inner_tid = 1; inner_tid < VG_N_THREADS; inner_tid++) {
396               if (VG_(threads)[i].os_state.lwpid
397                   == VG_(inner_threads)[inner_tid].os_state.lwpid) {
398                  ThreadState* save_outer_vg_threads = VG_(threads);
399
400                  VG_(threads) = VG_(inner_threads);
401                  print_thread_state(stack_usage, "INNER ", inner_tid);
402                  VG_(threads) = save_outer_vg_threads;
403                  break;
404               }
405            }
406         }
407      }
408   }
409   VG_(printf)("\n");
410}
411
412void VG_(show_sched_status) ( Bool host_stacktrace,
413                              Bool stack_usage,
414                              Bool exited_threads)
415{
416   show_sched_status_wrk (host_stacktrace,
417                          stack_usage,
418                          exited_threads,
419                          NULL);
420}
421
422__attribute__ ((noreturn))
423static void report_and_quit ( const HChar* report,
424                              const UnwindStartRegs* startRegsIN )
425{
426   show_sched_status_wrk (True,  // host_stacktrace
427                          False, // stack_usage
428                          False, // exited_threads
429                          startRegsIN);
430   VG_(printf)(
431      "\n"
432      "Note: see also the FAQ in the source distribution.\n"
433      "It contains workarounds to several common problems.\n"
434      "In particular, if Valgrind aborted or crashed after\n"
435      "identifying problems in your program, there's a good chance\n"
436      "that fixing those problems will prevent Valgrind aborting or\n"
437      "crashing, especially if it happened in m_mallocfree.c.\n"
438      "\n"
439      "If that doesn't help, please report this bug to: %s\n\n"
440      "In the bug report, send all the above text, the valgrind\n"
441      "version, and what OS and version you are using.  Thanks.\n\n",
442      report);
443   VG_(exit)(1);
444}
445
446void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
447                        Int line, const HChar* fn, const HChar* format, ... )
448{
449   va_list vargs, vargs_copy;
450   const HChar* component;
451   const HChar* bugs_to;
452   UInt written;
453
454   static Bool entered = False;
455   if (entered)
456      VG_(exit)(2);
457   entered = True;
458
459   if (isCore) {
460      component = "valgrind";
461      bugs_to   = VG_BUGS_TO;
462   } else {
463      component = VG_(details).name;
464      bugs_to   = VG_(details).bug_reports_to;
465   }
466
467   if (VG_(clo_xml))
468      VG_(printf_xml)("</valgrindoutput>\n");
469
470   // Treat vg_assert2(0, "foo") specially, as a panicky abort
471   if (VG_STREQ(expr, "0")) {
472      VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
473                  component, file, line, fn );
474   } else {
475      VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
476                  component, file, line, fn, expr );
477   }
478
479   /* Check whether anything will be written */
480   HChar buf[5];
481   va_start(vargs, format);
482   va_copy(vargs_copy, vargs);
483   written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
484   va_end(vargs);
485
486   if (written > 0) {
487      VG_(printf)("%s: ", component);
488      VG_(vprintf)(format, vargs_copy);
489      VG_(printf)("\n");
490   }
491
492   report_and_quit(bugs_to, NULL);
493}
494
495__attribute__ ((noreturn))
496static void panic ( const HChar* name, const HChar* report, const HChar* str,
497                    const UnwindStartRegs* startRegs )
498{
499   if (VG_(clo_xml))
500      VG_(printf_xml)("</valgrindoutput>\n");
501   VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
502   report_and_quit(report, startRegs);
503}
504
505void VG_(core_panic_at) ( const HChar* str, const UnwindStartRegs* startRegs )
506{
507   panic("valgrind", VG_BUGS_TO, str, startRegs);
508}
509
510void VG_(core_panic) ( const HChar* str )
511{
512   VG_(core_panic_at)(str, NULL);
513}
514
515void VG_(tool_panic) ( const HChar* str )
516{
517   panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
518}
519
520/* Print some helpful-ish text about unimplemented things, and give up. */
521void VG_(unimplemented) ( const HChar* format, ... )
522{
523   va_list vargs;
524   HChar msg[256];
525
526   va_start(vargs, format);
527   VG_(vsnprintf)(msg, sizeof(msg), format, vargs);
528   va_end(vargs);
529
530   if (VG_(clo_xml))
531      VG_(printf_xml)("</valgrindoutput>\n");
532   VG_(umsg)("\n");
533   VG_(umsg)("Valgrind detected that your program requires\n");
534   VG_(umsg)("the following unimplemented functionality:\n");
535   VG_(umsg)("   %s\n", msg);
536   VG_(umsg)("This may be because the functionality is hard to implement,\n");
537   VG_(umsg)("or because no reasonable program would behave this way,\n");
538   VG_(umsg)("or because nobody has yet needed it.  "
539             "In any case, let us know at\n");
540   VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
541             VG_BUGS_TO);
542   VG_(umsg)("\n");
543   VG_(umsg)("Valgrind has to exit now.  Sorry.  Bye!\n");
544   VG_(umsg)("\n");
545   VG_(show_sched_status)(False,  // host_stacktrace
546                          False,  // stack_usage
547                          False); // exited_threads
548   VG_(exit)(1);
549}
550
551/*--------------------------------------------------------------------*/
552/*--- end                                                          ---*/
553/*--------------------------------------------------------------------*/
554