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