drd/tests: Fix remaining gcc 8 compiler warnings
[valgrind.git] / coregrind / m_libcassert.c
blob3dba6771c577499475f77bfc5e7039f0b0a8255a
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, 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; \
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; \
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; \
230 #else
231 # error Unknown platform
232 #endif
234 #define BACKTRACE_DEPTH 100 // nice and deep!
236 __attribute__ ((__noreturn__))
237 static void exit_wrk( Int status, Bool gdbserver_call_allowed)
239 static Bool exit_called = False;
240 // avoid recursive exit during gdbserver call.
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");
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);
262 exit_called = True;
264 VG_(exit_now) (status);
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__))
271 void VG_(exit_now)( Int status )
273 #if defined(VGO_linux)
274 (void)VG_(do_syscall1)(__NR_exit_group, status );
275 #elif defined(VGO_darwin) || defined(VGO_solaris)
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';
287 /* Pull down the entire world */
288 void VG_(exit)( Int status )
290 exit_wrk (status, True);
293 /* Pull down the entire world */
294 void VG_(client_exit)( Int status )
296 exit_wrk (status, False);
299 static void print_thread_state (Bool stack_usage,
300 const HChar* prefix, ThreadId i)
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.
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;
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));
332 if (stack_usage && stack != 0) {
333 Addr stack_low_addr = VG_(am_valgrind_stack_low_addr) (stack);
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));
347 // Print the scheduler status.
348 static void show_sched_status_wrk ( Bool host_stacktrace,
349 Bool stack_usage,
350 Bool exited_threads,
351 const UnwindStartRegs* startRegsIN)
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)()));
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));
368 if (startRegsIN == NULL) {
369 GET_STARTREGS(&startRegs);
370 } else {
371 startRegs = *startRegsIN;
374 stacktop = tst->os_state.valgrind_stack_init_SP;
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
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;
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;
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);
414 VG_(threads) = VG_(inner_threads);
415 print_thread_state(stack_usage, "INNER ", inner_tid);
416 VG_(threads) = save_outer_vg_threads;
417 break;
423 VG_(printf)("\n");
426 void VG_(show_sched_status) ( Bool host_stacktrace,
427 Bool stack_usage,
428 Bool exited_threads)
430 show_sched_status_wrk (host_stacktrace,
431 stack_usage,
432 exited_threads,
433 NULL);
436 __attribute__ ((noreturn))
437 static void report_and_quit ( const HChar* report,
438 const UnwindStartRegs* startRegsIN )
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);
460 void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
461 Int line, const HChar* fn, const HChar* format, ... )
463 va_list vargs, vargs_copy;
464 const HChar* component;
465 const HChar* bugs_to;
466 UInt written;
468 static Bool entered = False;
469 if (entered)
470 VG_(exit)(2);
471 entered = True;
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;
481 if (VG_(clo_xml))
482 VG_(printf_xml)("</valgrindoutput>\n");
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 );
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);
500 if (written > 0) {
501 VG_(printf)("%s: ", component);
502 VG_(vprintf)(format, vargs_copy);
503 VG_(printf)("\n");
506 report_and_quit(bugs_to, NULL);
509 __attribute__ ((noreturn))
510 static void panic ( const HChar* name, const HChar* report, const HChar* str,
511 const UnwindStartRegs* startRegs )
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);
519 void VG_(core_panic_at) ( const HChar* str, const UnwindStartRegs* startRegs )
521 panic("valgrind", VG_BUGS_TO, str, startRegs);
524 void VG_(core_panic) ( const HChar* str )
526 VG_(core_panic_at)(str, NULL);
529 void VG_(tool_panic) ( const HChar* str )
531 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
534 /* Print some helpful-ish text about unimplemented things, and give up. */
535 void VG_(unimplemented) ( const HChar* format, ... )
537 va_list vargs;
538 HChar msg[256];
540 va_start(vargs, format);
541 VG_(vsnprintf)(msg, sizeof(msg), format, vargs);
542 va_end(vargs);
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);
565 /*--------------------------------------------------------------------*/
566 /*--- end ---*/
567 /*--------------------------------------------------------------------*/