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__))
exit_wrk(Int status,Bool gdbserver_call_allowed)259 static 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__))
VG_(exit_now)292 void 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 */
VG_(exit)309 void VG_(exit)( Int status )
310 {
311 exit_wrk (status, True);
312 }
313
314 /* Pull down the entire world */
VG_(client_exit)315 void VG_(client_exit)( Int status )
316 {
317 exit_wrk (status, False);
318 }
319
320
321 // Print the scheduler status.
show_sched_status_wrk(Bool host_stacktrace,Bool stack_usage,Bool exited_threads,const UnwindStartRegs * startRegsIN)322 static 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
VG_(show_sched_status)401 void 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))
report_and_quit(const HChar * report,const UnwindStartRegs * startRegsIN)412 static 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
VG_(assert_fail)435 void 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))
panic(const HChar * name,const HChar * report,const HChar * str,const UnwindStartRegs * startRegs)485 static 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
VG_(core_panic_at)494 void VG_(core_panic_at) ( const HChar* str, const UnwindStartRegs* startRegs )
495 {
496 panic("valgrind", VG_BUGS_TO, str, startRegs);
497 }
498
VG_(core_panic)499 void VG_(core_panic) ( const HChar* str )
500 {
501 VG_(core_panic_at)(str, NULL);
502 }
503
VG_(tool_panic)504 void 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. */
VG_(unimplemented)510 void 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