m_libcassert.c revision 738856f99eea33d86ce91dcb1d6cd5b151e307ca
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-2009 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_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_stacktrace.h" 40#include "pub_core_syscall.h" 41#include "pub_core_tooliface.h" // For VG_(details).{name,bug_reports_to} 42#include "pub_core_options.h" // For VG_(clo_xml) 43 44/* --------------------------------------------------------------------- 45 Assertery. 46 ------------------------------------------------------------------ */ 47 48#if defined(VGP_x86_linux) || defined(VGP_x86_darwin) 49# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \ 50 asm("call 0f;" \ 51 "0: popl %0;" \ 52 "movl %%esp, %1;" \ 53 "movl %%ebp, %2;" \ 54 : "=r" (pc),\ 55 "=r" (sp),\ 56 "=r" (fp)); 57#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) 58# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \ 59 asm("leaq 0(%%rip), %0;" \ 60 "movq %%rsp, %1;" \ 61 "movq %%rbp, %2;" \ 62 : "=r" (pc),\ 63 "=r" (sp),\ 64 "=r" (fp)); 65#elif defined(VGP_ppc32_linux) || defined(VGP_ppc32_aix5) 66# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \ 67 asm("mflr 0;" /* r0 = lr */ \ 68 "bl m_libcassert_get_ip;" /* lr = pc */ \ 69 "m_libcassert_get_ip:\n" \ 70 "mflr %0;" \ 71 "mtlr 0;" /* restore lr */ \ 72 "mr %1,1;" \ 73 "mr %2,1;" \ 74 : "=r" (pc), \ 75 "=r" (sp), \ 76 "=r" (fp) \ 77 : /* reads none */ \ 78 : "r0" /* trashed */ ); 79#elif defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5) 80# define GET_REAL_PC_SP_AND_FP(pc, sp, fp) \ 81 asm("mflr 0;" /* r0 = lr */ \ 82 "bl .m_libcassert_get_ip;" /* lr = pc */ \ 83 ".m_libcassert_get_ip:\n" \ 84 "mflr %0;" \ 85 "mtlr 0;" /* restore lr */ \ 86 "mr %1,1;" \ 87 "mr %2,1;" \ 88 : "=r" (pc), \ 89 "=r" (sp), \ 90 "=r" (fp) \ 91 : /* reads none */ \ 92 : "r0" /* trashed */ ); 93#else 94# error Unknown platform 95#endif 96 97#define BACKTRACE_DEPTH 100 // nice and deep! 98 99/* Pull down the entire world */ 100void VG_(exit)( Int status ) 101{ 102#if defined(VGO_linux) 103 (void)VG_(do_syscall1)(__NR_exit_group, status ); 104#elif defined(VGO_aix5) || defined(VGO_darwin) 105 (void)VG_(do_syscall1)(__NR_exit, status ); 106#else 107# error Unknown OS 108#endif 109 /*NOTREACHED*/ 110 // We really shouldn't reach here. Just in case we do, use some very crude 111 // methods to force abort 112 __builtin_trap(); 113 *(volatile Int*)0 = 'x'; 114} 115 116// Print the scheduler status. 117void VG_(show_sched_status) ( void ) 118{ 119 Int i; 120 VG_(printf)("\nsched status:\n"); 121 VG_(printf)(" running_tid=%d\n", VG_(get_running_tid)()); 122 for (i = 1; i < VG_N_THREADS; i++) { 123 if (VG_(threads)[i].status == VgTs_Empty) continue; 124 VG_(printf)( "\nThread %d: status = %s\n", i, 125 VG_(name_of_ThreadStatus)(VG_(threads)[i].status) ); 126 VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH ); 127 } 128 VG_(printf)("\n"); 129} 130 131__attribute__ ((noreturn)) 132static void report_and_quit ( const Char* report, 133 Addr ip, Addr sp, Addr fp, Addr lr ) 134{ 135 Addr stacktop; 136 Addr ips[BACKTRACE_DEPTH]; 137 Int n_ips; 138 ThreadState *tst 139 = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) ); 140 141 // If necessary, fake up an ExeContext which is of our actual real CPU 142 // state. Could cause problems if we got the panic/exception within the 143 // execontext/stack dump/symtab code. But it's better than nothing. 144 if (0 == ip && 0 == sp && 0 == fp) { 145 GET_REAL_PC_SP_AND_FP(ip, sp, fp); 146 } 147 148 stacktop = tst->os_state.valgrind_stack_init_SP; 149 150 n_ips = 151 VG_(get_StackTrace_wrk)( 152 0/*tid is unknown*/, 153 ips, BACKTRACE_DEPTH, 154 NULL/*array to dump SP values in*/, 155 NULL/*array to dump FP values in*/, 156 ip, sp, fp, lr, sp, stacktop 157 ); 158 VG_(clo_xml) = False; 159 VG_(pp_StackTrace) (ips, n_ips); 160 161 VG_(show_sched_status)(); 162 VG_(printf)( 163 "\n" 164 "Note: see also the FAQ in the source distribution.\n" 165 "It contains workarounds to several common problems.\n" 166 "In particular, if Valgrind aborted or crashed after\n" 167 "identifying problems in your program, there's a good chance\n" 168 "that fixing those problems will prevent Valgrind aborting or\n" 169 "crashing, especially if it happened in m_mallocfree.c.\n" 170 "\n" 171 "If that doesn't help, please report this bug to: %s\n\n" 172 "In the bug report, send all the above text, the valgrind\n" 173 "version, and what OS and version you are using. Thanks.\n\n", 174 report); 175 VG_(exit)(1); 176} 177 178void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file, 179 Int line, const Char* fn, const HChar* format, ... ) 180{ 181 va_list vargs; 182 Char buf[256]; 183 Char* component; 184 Char* bugs_to; 185 186 static Bool entered = False; 187 if (entered) 188 VG_(exit)(2); 189 entered = True; 190 191 va_start(vargs, format); 192 VG_(vsprintf) ( buf, format, vargs ); 193 va_end(vargs); 194 195 if (isCore) { 196 component = "valgrind"; 197 bugs_to = VG_BUGS_TO; 198 } else { 199 component = VG_(details).name; 200 bugs_to = VG_(details).bug_reports_to; 201 } 202 203 if (VG_(clo_xml)) 204 VG_(printf_xml)("</valgrindoutput>\n"); 205 206 // Treat vg_assert2(0, "foo") specially, as a panicky abort 207 if (VG_STREQ(expr, "0")) { 208 VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n", 209 component, file, line, fn ); 210 } else { 211 VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n", 212 component, file, line, fn, expr ); 213 } 214 if (!VG_STREQ(buf, "")) 215 VG_(printf)("%s: %s\n", component, buf ); 216 217 report_and_quit(bugs_to, 0,0,0,0); 218} 219 220__attribute__ ((noreturn)) 221static void panic ( Char* name, Char* report, Char* str, 222 Addr ip, Addr sp, Addr fp, Addr lr ) 223{ 224 if (VG_(clo_xml)) 225 VG_(printf_xml)("</valgrindoutput>\n"); 226 VG_(printf)("\n%s: the 'impossible' happened:\n %s\n", name, str); 227 report_and_quit(report, ip, sp, fp, lr); 228} 229 230void VG_(core_panic_at) ( Char* str, Addr ip, Addr sp, Addr fp, Addr lr ) 231{ 232 panic("valgrind", VG_BUGS_TO, str, ip, sp, fp, lr); 233} 234 235void VG_(core_panic) ( Char* str ) 236{ 237 VG_(core_panic_at)(str, 0,0,0,0); 238} 239 240void VG_(tool_panic) ( Char* str ) 241{ 242 panic(VG_(details).name, VG_(details).bug_reports_to, str, 0,0,0,0); 243} 244 245/* Print some helpful-ish text about unimplemented things, and give up. */ 246void VG_(unimplemented) ( Char* msg ) 247{ 248 if (VG_(clo_xml)) 249 VG_(printf_xml)("</valgrindoutput>\n"); 250 VG_(umsg)("\n"); 251 VG_(umsg)("Valgrind detected that your program requires\n"); 252 VG_(umsg)("the following unimplemented functionality:\n"); 253 VG_(umsg)(" %s\n", msg); 254 VG_(umsg)("This may be because the functionality is hard to implement,\n"); 255 VG_(umsg)("or because no reasonable program would behave this way,\n"); 256 VG_(umsg)("or because nobody has yet needed it. " 257 "In any case, let us know at\n"); 258 VG_(umsg)("%s and/or try to work around the problem, if you can.\n", 259 VG_BUGS_TO); 260 VG_(umsg)("\n"); 261 VG_(umsg)("Valgrind has to exit now. Sorry. Bye!\n"); 262 VG_(umsg)("\n"); 263 VG_(show_sched_status)(); 264 VG_(exit)(1); 265} 266 267/*--------------------------------------------------------------------*/ 268/*--- end ---*/ 269/*--------------------------------------------------------------------*/ 270 271