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