Bug 489040 massif trace change to show the location increasing the stack
[valgrind.git] / coregrind / m_libcassert.c
blobdb9d43d8741df066afe6451adafb0266e043a41a
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) || defined(VGP_x86_freebsd)
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) || defined(VGP_amd64_freebsd)
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) || defined(VGP_arm64_freebsd)
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 if (!(VG_(clo_launched_with_multi)))
286 VG_(umsg)("(action at valgrind abnormal exit) vgdb me ... \n");
287 VG_(gdbserver) (atid);
288 } else {
289 VG_(umsg)("(action at valgrind abnormal exit)\n"
290 "valgrind exit is too early => vgdb not yet usable\n");
293 if (VG_(gdbserver_init_done)()) {
294 // Always terminate the gdbserver when Valgrind exits, so as
295 // to e.g. cleanup the FIFOs.
296 VG_(gdbserver_exit) (atid,
297 status == 0 ? VgSrc_ExitProcess : VgSrc_FatalSig);
300 exit_called = True;
302 VG_(exit_now) (status);
305 /* Call the appropriate system call and nothing else. This function should
306 be called in places where the dependencies of VG_(exit) need to be
307 avoided. */
308 __attribute__ ((__noreturn__))
309 void VG_(exit_now)( Int status )
311 #if defined(VGO_linux)
312 (void)VG_(do_syscall1)(__NR_exit_group, status );
313 #elif defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
314 (void)VG_(do_syscall1)(__NR_exit, status );
315 #else
316 # error Unknown OS
317 #endif
318 /*NOTREACHED*/
319 // We really shouldn't reach here. Just in case we do, use some very crude
320 // methods to force abort
321 __builtin_trap();
322 *(volatile Int*)0 = 'x';
325 /* Pull down the entire world */
326 void VG_(exit)( Int status )
328 exit_wrk (status, True);
331 /* Pull down the entire world */
332 void VG_(client_exit)( Int status )
334 exit_wrk (status, False);
337 static void print_thread_state (Bool stack_usage,
338 const HChar* prefix, ThreadId i)
340 VgStack *stack
341 = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
342 HChar syscallno[50];
343 // must be large enough for VG_SYSNUM_STRING result + 10.
345 if (VG_(is_in_syscall) (i))
346 VG_(sprintf)(syscallno, " syscall %s",
347 VG_SYSNUM_STRING(VG_(is_in_syscall_no)(i)));
348 else
349 syscallno[0] = 0;
350 VG_(printf)("\n%sThread %u: status = %s%s (lwpid %d)\n", prefix, i,
351 VG_(name_of_ThreadStatus)(VG_(threads)[i].status),
352 syscallno,
353 VG_(threads)[i].os_state.lwpid);
354 if (VG_(threads)[i].status != VgTs_Empty)
355 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
356 if (stack_usage && VG_(threads)[i].client_stack_highest_byte != 0 ) {
357 Addr start, end;
359 start = end = 0;
360 VG_(stack_limits)(VG_(get_SP)(i), &start, &end);
361 if (start != end)
362 VG_(printf)("%sclient stack range: [%p %p] client SP: %p\n",
363 prefix,
364 (void*)start, (void*)end, (void*)VG_(get_SP)(i));
365 else
366 VG_(printf)("%sclient stack range: ??????? client SP: %p\n",
367 prefix,
368 (void*)VG_(get_SP)(i));
370 if (stack_usage && stack != 0) {
371 Addr stack_low_addr = VG_(am_valgrind_stack_low_addr) (stack);
373 VG_(printf)
374 ("%svalgrind stack range: [%p %p] top usage: %lu of %lu\n",
375 prefix,
376 (void*)stack_low_addr,
377 (void*)(stack_low_addr + VG_(clo_valgrind_stacksize) - 1),
378 VG_(clo_valgrind_stacksize)
379 - VG_(am_get_VgStack_unused_szB) (stack,
380 VG_(clo_valgrind_stacksize)),
381 (SizeT) VG_(clo_valgrind_stacksize));
385 // Print the scheduler status.
386 static void show_sched_status_wrk ( Bool host_stacktrace,
387 Bool stack_usage,
388 Bool exited_threads,
389 const UnwindStartRegs* startRegsIN)
391 Int i;
392 if (host_stacktrace) {
393 const Bool save_clo_xml = VG_(clo_xml);
394 Addr stacktop;
395 Addr ips[BACKTRACE_DEPTH];
396 Int n_ips;
397 ThreadState *tst
398 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid_dead_ok)(VG_(gettid)()));
400 // If necessary, fake up an ExeContext which is of our actual real CPU
401 // state. Could cause problems if we got the panic/exception within the
402 // execontext/stack dump/symtab code. But it's better than nothing.
403 UnwindStartRegs startRegs;
404 VG_(memset)(&startRegs, 0, sizeof(startRegs));
406 if (startRegsIN == NULL) {
407 GET_STARTREGS(&startRegs);
408 } else {
409 startRegs = *startRegsIN;
412 stacktop = tst->os_state.valgrind_stack_init_SP;
414 n_ips =
415 VG_(get_StackTrace_wrk)(
416 0/*tid is unknown*/,
417 ips, BACKTRACE_DEPTH,
418 NULL/*array to dump SP values in*/,
419 NULL/*array to dump FP values in*/,
420 &startRegs, stacktop
422 VG_(printf)("\nhost stacktrace:\n");
423 VG_(clo_xml) = False;
424 VG_(pp_StackTrace) (VG_(current_DiEpoch)(), ips, n_ips);
425 VG_(clo_xml) = save_clo_xml;
428 VG_(printf)("\nsched status:\n");
429 if (VG_(threads) == NULL) {
430 VG_(printf)(" scheduler not yet initialised\n");
431 } else {
432 VG_(printf)(" running_tid=%u\n", VG_(get_running_tid)());
433 for (i = 1; i < VG_N_THREADS; i++) {
434 VgStack *stack
435 = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
436 /* If a thread slot was never used (yet), valgrind_stack_base is 0.
437 If a thread slot is used by a thread or was used by a thread which
438 has exited, then valgrind_stack_base points to the stack base. */
439 if (VG_(threads)[i].status == VgTs_Empty
440 && (!exited_threads || stack == 0)) continue;
441 print_thread_state(stack_usage, "", i);
442 if (VG_(inner_threads) != NULL) {
443 /* An inner V has informed us (the outer) of its thread array.
444 Report the inner guest stack trace. */
445 UInt inner_tid;
447 for (inner_tid = 1; inner_tid < VG_N_THREADS; inner_tid++) {
448 if (VG_(threads)[i].os_state.lwpid
449 == VG_(inner_threads)[inner_tid].os_state.lwpid) {
450 ThreadState* save_outer_vg_threads = VG_(threads);
452 VG_(threads) = VG_(inner_threads);
453 print_thread_state(stack_usage, "INNER ", inner_tid);
454 VG_(threads) = save_outer_vg_threads;
455 break;
461 VG_(printf)("\n");
464 void VG_(show_sched_status) ( Bool host_stacktrace,
465 Bool stack_usage,
466 Bool exited_threads)
468 show_sched_status_wrk (host_stacktrace,
469 stack_usage,
470 exited_threads,
471 NULL);
474 __attribute__ ((noreturn))
475 static void report_and_quit ( const HChar* report,
476 const UnwindStartRegs* startRegsIN )
478 show_sched_status_wrk (True, // host_stacktrace
479 True, // stack_usage
480 False, // exited_threads
481 startRegsIN);
482 VG_(printf)(
483 "\n"
484 "Note: see also the FAQ in the source distribution.\n"
485 "It contains workarounds to several common problems.\n"
486 "In particular, if Valgrind aborted or crashed after\n"
487 "identifying problems in your program, there's a good chance\n"
488 "that fixing those problems will prevent Valgrind aborting or\n"
489 "crashing, especially if it happened in m_mallocfree.c.\n"
490 "\n"
491 "If that doesn't help, please report this bug to: %s\n\n"
492 "In the bug report, send all the above text, the valgrind\n"
493 "version, and what OS and version you are using. Thanks.\n\n",
494 report);
495 VG_(exit)(1);
498 void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
499 Int line, const HChar* fn, const HChar* format, ... )
501 va_list vargs, vargs_copy;
502 const HChar* component;
503 const HChar* bugs_to;
504 UInt written;
506 static Bool entered = False;
507 if (entered)
508 VG_(exit)(2);
509 entered = True;
511 if (isCore) {
512 component = "valgrind";
513 bugs_to = VG_BUGS_TO;
514 } else {
515 component = VG_(details).name;
516 bugs_to = VG_(details).bug_reports_to;
519 if (VG_(clo_xml))
520 VG_(printf_xml)("</valgrindoutput>\n");
522 // Treat vg_assert2(0, "foo") specially, as a panicky abort
523 if (VG_STREQ(expr, "0")) {
524 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
525 component, file, line, fn );
526 } else {
527 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
528 component, file, line, fn, expr );
531 /* Check whether anything will be written */
532 HChar buf[5];
533 va_start(vargs, format);
534 va_copy(vargs_copy, vargs);
535 written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
536 va_end(vargs);
538 if (written > 0) {
539 VG_(printf)("%s: ", component);
540 VG_(vprintf)(format, vargs_copy);
541 VG_(printf)("\n");
544 report_and_quit(bugs_to, NULL);
547 __attribute__ ((noreturn))
548 static void panic ( const HChar* name, const HChar* report, const HChar* str,
549 const UnwindStartRegs* startRegs )
551 if (VG_(clo_xml))
552 VG_(printf_xml)("</valgrindoutput>\n");
553 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str);
554 report_and_quit(report, startRegs);
557 void VG_(core_panic_at) ( const HChar* str, const UnwindStartRegs* startRegs )
559 panic("valgrind", VG_BUGS_TO, str, startRegs);
562 void VG_(core_panic) ( const HChar* str )
564 VG_(core_panic_at)(str, NULL);
567 void VG_(tool_panic) ( const HChar* str )
569 panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
572 /* Print some helpful-ish text about unimplemented things, and give up. */
573 void VG_(unimplemented) ( const HChar* format, ... )
575 va_list vargs;
576 HChar msg[256];
578 va_start(vargs, format);
579 VG_(vsnprintf)(msg, sizeof(msg), format, vargs);
580 va_end(vargs);
582 if (VG_(clo_xml))
583 VG_(printf_xml)("</valgrindoutput>\n");
584 VG_(umsg)("\n");
585 VG_(umsg)("Valgrind detected that your program requires\n");
586 VG_(umsg)("the following unimplemented functionality:\n");
587 VG_(umsg)(" %s\n", msg);
588 VG_(umsg)("This may be because the functionality is hard to implement,\n");
589 VG_(umsg)("or because no reasonable program would behave this way,\n");
590 VG_(umsg)("or because nobody has yet needed it. "
591 "In any case, let us know at\n");
592 VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
593 VG_BUGS_TO);
594 VG_(umsg)("\n");
595 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n");
596 VG_(umsg)("\n");
597 VG_(show_sched_status)(False, // host_stacktrace
598 False, // stack_usage
599 False); // exited_threads
600 VG_(exit)(1);
603 /*--------------------------------------------------------------------*/
604 /*--- end ---*/
605 /*--------------------------------------------------------------------*/