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