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