drd/tests/tsan_unittest: Avoid that this test reads from uninitialized memory
[valgrind.git] / coregrind / m_libcassert.c
blobbb9b92b5a9426a36308c0b0cc60558e3fbe4380e
2 /*--------------------------------------------------------------------*/
3 /*--- Assertions and panics. m_libcassert.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2000-2017 Julian Seward
11 jseward@acm.org
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.
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.
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.
28 The GNU General Public License is contained in the file COPYING.
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)
49 /* ---------------------------------------------------------------------
50 Assertery.
51 ------------------------------------------------------------------ */
53 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin) \
54 || defined(VGP_x86_solaris)
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; \
70 #elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) \
71 || defined(VGP_amd64_solaris)
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; \
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; \
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; \
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]; \
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]; \
164 #elif defined(VGP_s390x_linux)
165 # define GET_STARTREGS(srP) \
166 { ULong ia; \
167 ULong block[11]; \
168 __asm__ __volatile__( \
169 "bras %0, 0f;" \
170 "0: " \
171 "stg %%r15, 0(%1);" \
172 "stg %%r11, 8(%1);" \
173 "stg %%r14, 16(%1);" \
174 "std %%f0, 24(%1);" \
175 "std %%f1, 32(%1);" \
176 "std %%f2, 40(%1);" \
177 "std %%f3, 48(%1);" \
178 "std %%f4, 56(%1);" \
179 "std %%f5, 64(%1);" \
180 "std %%f6, 72(%1);" \
181 "std %%f7, 80(%1);" \
182 : /* out */ "=r" (ia) \
183 : /* in */ "a" (&block[0]) \
184 : /* trash */ "memory" \
185 ); \
186 (srP)->r_pc = ia; \
187 (srP)->r_sp = block[0]; \
188 (srP)->misc.S390X.r_fp = block[1]; \
189 (srP)->misc.S390X.r_lr = block[2]; \
190 (srP)->misc.S390X.r_f0 = block[3]; \
191 (srP)->misc.S390X.r_f1 = block[4]; \
192 (srP)->misc.S390X.r_f2 = block[5]; \
193 (srP)->misc.S390X.r_f3 = block[6]; \
194 (srP)->misc.S390X.r_f4 = block[7]; \
195 (srP)->misc.S390X.r_f5 = block[8]; \
196 (srP)->misc.S390X.r_f6 = block[9]; \
197 (srP)->misc.S390X.r_f7 = block[10]; \
199 #elif defined(VGP_mips32_linux)
200 # define GET_STARTREGS(srP) \
201 { UInt pc, sp, fp, ra, gp; \
202 asm("move $8, $31;" /* t0 = ra */ \
203 "bal 0f;" /* ra = pc */ \
204 "0:\n" \
205 "move %0, $31;" \
206 "move $31, $8;" /* restore lr */ \
207 "move %1, $29;" \
208 "move %2, $30;" \
209 "move %3, $31;" \
210 "move %4, $28;" \
211 : "=r" (pc), \
212 "=r" (sp), \
213 "=r" (fp), \
214 "=r" (ra), \
215 "=r" (gp) \
216 : /* reads none */ \
217 : "$8" /* trashed */ ); \
218 (srP)->r_pc = (ULong)pc - 8; \
219 (srP)->r_sp = (ULong)sp; \
220 (srP)->misc.MIPS32.r30 = (ULong)fp; \
221 (srP)->misc.MIPS32.r31 = (ULong)ra; \
222 (srP)->misc.MIPS32.r28 = (ULong)gp; \
224 #elif defined(VGP_mips64_linux)
225 # define GET_STARTREGS(srP) \
226 { ULong pc, sp, fp, ra, gp; \
227 asm("move $8, $31;" /* t0 = ra */ \
228 "bal 0f;" /* ra = pc */ \
229 "0:\n" \
230 "move %0, $31;" \
231 "move $31, $8;" /* restore lr */ \
232 "move %1, $29;" \
233 "move %2, $30;" \
234 "move %3, $31;" \
235 "move %4, $28;" \
236 : "=r" (pc), \
237 "=r" (sp), \
238 "=r" (fp), \
239 "=r" (ra), \
240 "=r" (gp) \
241 : /* reads none */ \
242 : "$8" /* trashed */ ); \
243 (srP)->r_pc = (ULong)pc - 8; \
244 (srP)->r_sp = (ULong)sp; \
245 (srP)->misc.MIPS64.r30 = (ULong)fp; \
246 (srP)->misc.MIPS64.r31 = (ULong)ra; \
247 (srP)->misc.MIPS64.r28 = (ULong)gp; \
249 #else
250 # error Unknown platform
251 #endif
253 #define BACKTRACE_DEPTH 100 // nice and deep!
255 __attribute__ ((__noreturn__))
256 static void exit_wrk( Int status, Bool gdbserver_call_allowed)
258 static Bool exit_called = False;
259 // avoid recursive exit during gdbserver call.
261 if (gdbserver_call_allowed && !exit_called) {
262 const ThreadId atid = 1; // Arbitrary tid used to call/terminate gdbsrv.
263 exit_called = True;
264 if (status != 0
265 && VgdbStopAtiS(VgdbStopAt_ValgrindAbExit, VG_(clo_vgdb_stop_at))) {
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)\n"
271 "valgrind exit is too early => vgdb not yet usable\n");
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);
281 exit_called = True;
283 VG_(exit_now) (status);
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__))
290 void VG_(exit_now)( Int status )
292 #if defined(VGO_linux)
293 (void)VG_(do_syscall1)(__NR_exit_group, status );
294 #elif defined(VGO_darwin) || defined(VGO_solaris)
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';
306 /* Pull down the entire world */
307 void VG_(exit)( Int status )
309 exit_wrk (status, True);
312 /* Pull down the entire world */
313 void VG_(client_exit)( Int status )
315 exit_wrk (status, False);
318 static void print_thread_state (Bool stack_usage,
319 const HChar* prefix, ThreadId i)
321 VgStack *stack
322 = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
323 HChar syscallno[50];
324 // must be large enough for VG_SYSNUM_STRING result + 10.
326 if (VG_(is_in_syscall) (i))
327 VG_(sprintf)(syscallno, " syscall %s",
328 VG_SYSNUM_STRING(VG_(is_in_syscall_no)(i)));
329 else
330 syscallno[0] = 0;
331 VG_(printf)("\n%sThread %u: status = %s%s (lwpid %d)\n", prefix, i,
332 VG_(name_of_ThreadStatus)(VG_(threads)[i].status),
333 syscallno,
334 VG_(threads)[i].os_state.lwpid);
335 if (VG_(threads)[i].status != VgTs_Empty)
336 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
337 if (stack_usage && VG_(threads)[i].client_stack_highest_byte != 0 ) {
338 Addr start, end;
340 start = end = 0;
341 VG_(stack_limits)(VG_(get_SP)(i), &start, &end);
342 if (start != end)
343 VG_(printf)("%sclient stack range: [%p %p] client SP: %p\n",
344 prefix,
345 (void*)start, (void*)end, (void*)VG_(get_SP)(i));
346 else
347 VG_(printf)("%sclient stack range: ??????? client SP: %p\n",
348 prefix,
349 (void*)VG_(get_SP)(i));
351 if (stack_usage && stack != 0) {
352 Addr stack_low_addr = VG_(am_valgrind_stack_low_addr) (stack);
354 VG_(printf)
355 ("%svalgrind stack range: [%p %p] top usage: %lu of %lu\n",
356 prefix,
357 (void*)stack_low_addr,
358 (void*)(stack_low_addr + VG_(clo_valgrind_stacksize) - 1),
359 VG_(clo_valgrind_stacksize)
360 - VG_(am_get_VgStack_unused_szB) (stack,
361 VG_(clo_valgrind_stacksize)),
362 (SizeT) VG_(clo_valgrind_stacksize));
366 // Print the scheduler status.
367 static void show_sched_status_wrk ( Bool host_stacktrace,
368 Bool stack_usage,
369 Bool exited_threads,
370 const UnwindStartRegs* startRegsIN)
372 Int i;
373 if (host_stacktrace) {
374 const Bool save_clo_xml = VG_(clo_xml);
375 Addr stacktop;
376 Addr ips[BACKTRACE_DEPTH];
377 Int n_ips;
378 ThreadState *tst
379 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid_dead_ok)(VG_(gettid)()));
381 // If necessary, fake up an ExeContext which is of our actual real CPU
382 // state. Could cause problems if we got the panic/exception within the
383 // execontext/stack dump/symtab code. But it's better than nothing.
384 UnwindStartRegs startRegs;
385 VG_(memset)(&startRegs, 0, sizeof(startRegs));
387 if (startRegsIN == NULL) {
388 GET_STARTREGS(&startRegs);
389 } else {
390 startRegs = *startRegsIN;
393 stacktop = tst->os_state.valgrind_stack_init_SP;
395 n_ips =
396 VG_(get_StackTrace_wrk)(
397 0/*tid is unknown*/,
398 ips, BACKTRACE_DEPTH,
399 NULL/*array to dump SP values in*/,
400 NULL/*array to dump FP values in*/,
401 &startRegs, stacktop
403 VG_(printf)("\nhost stacktrace:\n");
404 VG_(clo_xml) = False;
405 VG_(pp_StackTrace) (VG_(current_DiEpoch)(), ips, n_ips);
406 VG_(clo_xml) = save_clo_xml;
409 VG_(printf)("\nsched status:\n");
410 if (VG_(threads) == NULL) {
411 VG_(printf)(" scheduler not yet initialised\n");
412 } else {
413 VG_(printf)(" running_tid=%u\n", VG_(get_running_tid)());
414 for (i = 1; i < VG_N_THREADS; i++) {
415 VgStack *stack
416 = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
417 /* If a thread slot was never used (yet), valgrind_stack_base is 0.
418 If a thread slot is used by a thread or was used by a thread which
419 has exited, then valgrind_stack_base points to the stack base. */
420 if (VG_(threads)[i].status == VgTs_Empty
421 && (!exited_threads || stack == 0)) continue;
422 print_thread_state(stack_usage, "", i);
423 if (VG_(inner_threads) != NULL) {
424 /* An inner V has informed us (the outer) of its thread array.
425 Report the inner guest stack trace. */
426 UInt inner_tid;
428 for (inner_tid = 1; inner_tid < VG_N_THREADS; inner_tid++) {
429 if (VG_(threads)[i].os_state.lwpid
430 == VG_(inner_threads)[inner_tid].os_state.lwpid) {
431 ThreadState* save_outer_vg_threads = VG_(threads);
433 VG_(threads) = VG_(inner_threads);
434 print_thread_state(stack_usage, "INNER ", inner_tid);
435 VG_(threads) = save_outer_vg_threads;
436 break;
442 VG_(printf)("\n");
445 void VG_(show_sched_status) ( Bool host_stacktrace,
446 Bool stack_usage,
447 Bool exited_threads)
449 show_sched_status_wrk (host_stacktrace,
450 stack_usage,
451 exited_threads,
452 NULL);
455 __attribute__ ((noreturn))
456 static void report_and_quit ( const HChar* report,
457 const UnwindStartRegs* startRegsIN )
459 show_sched_status_wrk (True, // host_stacktrace
460 True, // stack_usage
461 False, // exited_threads
462 startRegsIN);
463 VG_(printf)(
464 "\n"
465 "Note: see also the FAQ in the source distribution.\n"
466 "It contains workarounds to several common problems.\n"
467 "In particular, if Valgrind aborted or crashed after\n"
468 "identifying problems in your program, there's a good chance\n"
469 "that fixing those problems will prevent Valgrind aborting or\n"
470 "crashing, especially if it happened in m_mallocfree.c.\n"
471 "\n"
472 "If that doesn't help, please report this bug to: %s\n\n"
473 "In the bug report, send all the above text, the valgrind\n"
474 "version, and what OS and version you are using. Thanks.\n\n",
475 report);
476 VG_(exit)(1);
479 void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
480 Int line, const HChar* fn, const HChar* format, ... )
482 va_list vargs, vargs_copy;
483 const HChar* component;
484 const HChar* bugs_to;
485 UInt written;
487 static Bool entered = False;
488 if (entered)
489 VG_(exit)(2);
490 entered = True;
492 if (isCore) {
493 component = "valgrind";
494 bugs_to = VG_BUGS_TO;
495 } else {
496 component = VG_(details).name;
497 bugs_to = VG_(details).bug_reports_to;
500 if (VG_(clo_xml))
501 VG_(printf_xml)("</valgrindoutput>\n");
503 // Treat vg_assert2(0, "foo") specially, as a panicky abort
504 if (VG_STREQ(expr, "0")) {
505 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
506 component, file, line, fn );
507 } else {
508 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
509 component, file, line, fn, expr );
512 /* Check whether anything will be written */
513 HChar buf[5];
514 va_start(vargs, format);
515 va_copy(vargs_copy, vargs);
516 written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
517 va_end(vargs);
519 if (written > 0) {
520 VG_(printf)("%s: ", component);
521 VG_(vprintf)(format, vargs_copy);
522 VG_(printf)("\n");
525 report_and_quit(bugs_to, NULL);
528 __attribute__ ((noreturn))
529 static void panic ( const HChar* name, const HChar* report, const HChar* str,
530 const UnwindStartRegs* startRegs )
532 if (VG_(clo_xml))
533 VG_(printf_xml)("</valgrindoutput>\n");
534 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
535 report_and_quit(report, startRegs);
538 void VG_(core_panic_at) ( const HChar* str, const UnwindStartRegs* startRegs )
540 panic("valgrind", VG_BUGS_TO, str, startRegs);
543 void VG_(core_panic) ( const HChar* str )
545 VG_(core_panic_at)(str, NULL);
548 void VG_(tool_panic) ( const HChar* str )
550 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
553 /* Print some helpful-ish text about unimplemented things, and give up. */
554 void VG_(unimplemented) ( const HChar* format, ... )
556 va_list vargs;
557 HChar msg[256];
559 va_start(vargs, format);
560 VG_(vsnprintf)(msg, sizeof(msg), format, vargs);
561 va_end(vargs);
563 if (VG_(clo_xml))
564 VG_(printf_xml)("</valgrindoutput>\n");
565 VG_(umsg)("\n");
566 VG_(umsg)("Valgrind detected that your program requires\n");
567 VG_(umsg)("the following unimplemented functionality:\n");
568 VG_(umsg)(" %s\n", msg);
569 VG_(umsg)("This may be because the functionality is hard to implement,\n");
570 VG_(umsg)("or because no reasonable program would behave this way,\n");
571 VG_(umsg)("or because nobody has yet needed it. "
572 "In any case, let us know at\n");
573 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
574 VG_BUGS_TO);
575 VG_(umsg)("\n");
576 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
577 VG_(umsg)("\n");
578 VG_(show_sched_status)(False, // host_stacktrace
579 False, // stack_usage
580 False); // exited_threads
581 VG_(exit)(1);
584 /*--------------------------------------------------------------------*/
585 /*--- end ---*/
586 /*--------------------------------------------------------------------*/