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-2013 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_libcsetjmp.h"    // to keep threadstate.h happy
     35 #include "pub_core_threadstate.h"
     36 #include "pub_core_gdbserver.h"
     37 #include "pub_core_aspacemgr.h"
     38 #include "pub_core_libcbase.h"
     39 #include "pub_core_libcassert.h"
     40 #include "pub_core_libcprint.h"
     41 #include "pub_core_libcproc.h"      // For VG_(gettid)()
     42 #include "pub_core_stacktrace.h"
     43 #include "pub_core_syscall.h"
     44 #include "pub_core_tooliface.h"     // For VG_(details).{name,bug_reports_to}
     45 #include "pub_core_options.h"       // For VG_(clo_xml)
     46 
     47 /* ---------------------------------------------------------------------
     48    Assertery.
     49    ------------------------------------------------------------------ */
     50 
     51 #if defined(VGP_x86_linux) || defined(VGP_x86_darwin)
     52 #  define GET_STARTREGS(srP)                              \
     53       { UInt eip, esp, ebp;                               \
     54         __asm__ __volatile__(                             \
     55            "call 0f;"                                     \
     56            "0: popl %0;"                                  \
     57            "movl %%esp, %1;"                              \
     58            "movl %%ebp, %2;"                              \
     59            : "=r" (eip), "=r" (esp), "=r" (ebp)           \
     60            : /* reads none */                             \
     61            : "memory"                                     \
     62         );                                                \
     63         (srP)->r_pc = (ULong)eip;                         \
     64         (srP)->r_sp = (ULong)esp;                         \
     65         (srP)->misc.X86.r_ebp = ebp;                      \
     66       }
     67 #elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin)
     68 #  define GET_STARTREGS(srP)                              \
     69       { ULong rip, rsp, rbp;                              \
     70         __asm__ __volatile__(                             \
     71            "leaq 0(%%rip), %0;"                           \
     72            "movq %%rsp, %1;"                              \
     73            "movq %%rbp, %2;"                              \
     74            : "=r" (rip), "=r" (rsp), "=r" (rbp)           \
     75            : /* reads none */                             \
     76            : "memory"                                     \
     77         );                                                \
     78         (srP)->r_pc = rip;                                \
     79         (srP)->r_sp = rsp;                                \
     80         (srP)->misc.AMD64.r_rbp = rbp;                    \
     81       }
     82 #elif defined(VGP_ppc32_linux)
     83 #  define GET_STARTREGS(srP)                              \
     84       { UInt cia, r1, lr;                                 \
     85         __asm__ __volatile__(                             \
     86            "mflr 0;"                   /* r0 = lr */      \
     87            "bl m_libcassert_get_ip;"   /* lr = pc */      \
     88            "m_libcassert_get_ip:\n"                       \
     89            "mflr %0;"                  /* %0 = pc */      \
     90            "mtlr 0;"                   /* restore lr */   \
     91            "mr %1,1;"                  /* %1 = r1 */      \
     92            "mr %2,0;"                  /* %2 = lr */      \
     93            : "=r" (cia), "=r" (r1), "=r" (lr)             \
     94            : /* reads none */                             \
     95            : "r0" /* trashed */                           \
     96         );                                                \
     97         (srP)->r_pc = (ULong)cia;                         \
     98         (srP)->r_sp = (ULong)r1;                          \
     99         (srP)->misc.PPC32.r_lr = lr;                      \
    100       }
    101 #elif defined(VGP_ppc64_linux)
    102 #  define GET_STARTREGS(srP)                              \
    103       { ULong cia, r1, lr;                                \
    104         __asm__ __volatile__(                             \
    105            "mflr 0;"                   /* r0 = lr */      \
    106            "bl .m_libcassert_get_ip;"  /* lr = pc */      \
    107            ".m_libcassert_get_ip:\n"                      \
    108            "mflr %0;"                  /* %0 = pc */      \
    109            "mtlr 0;"                   /* restore lr */   \
    110            "mr %1,1;"                  /* %1 = r1 */      \
    111            "mr %2,0;"                  /* %2 = lr */      \
    112            : "=r" (cia), "=r" (r1), "=r" (lr)             \
    113            : /* reads none */                             \
    114            : "r0" /* trashed */                           \
    115         );                                                \
    116         (srP)->r_pc = cia;                                \
    117         (srP)->r_sp = r1;                                 \
    118         (srP)->misc.PPC64.r_lr = lr;                      \
    119       }
    120 #elif defined(VGP_arm_linux)
    121 #  define GET_STARTREGS(srP)                              \
    122       { UInt block[6];                                    \
    123         __asm__ __volatile__(                             \
    124            "str r15, [%0, #+0];"                          \
    125            "str r14, [%0, #+4];"                          \
    126            "str r13, [%0, #+8];"                          \
    127            "str r12, [%0, #+12];"                         \
    128            "str r11, [%0, #+16];"                         \
    129            "str r7,  [%0, #+20];"                         \
    130            : /* out */                                    \
    131            : /* in */ "r"(&block[0])                      \
    132            : /* trash */ "memory"                         \
    133         );                                                \
    134         (srP)->r_pc = block[0] - 8;                       \
    135         (srP)->r_sp = block[1];                           \
    136         (srP)->misc.ARM.r14 = block[2];                   \
    137         (srP)->misc.ARM.r12 = block[3];                   \
    138         (srP)->misc.ARM.r11 = block[4];                   \
    139         (srP)->misc.ARM.r7  = block[5];                   \
    140       }
    141 #elif defined(VGP_arm64_linux)
    142 #  define GET_STARTREGS(srP)                              \
    143       { ULong block[4];                                   \
    144         __asm__ __volatile__(                             \
    145            "adr x19, 0;"                                  \
    146            "str x19, [%0, #+0];"   /* pc */               \
    147            "mov x19, sp;"                                 \
    148            "str x19, [%0, #+8];"   /* sp */               \
    149            "str x29, [%0, #+16];"  /* fp */               \
    150            "str x30, [%0, #+24];"  /* lr */               \
    151            : /* out */                                    \
    152            : /* in */ "r"(&block[0])                      \
    153            : /* trash */ "memory","x19"                   \
    154         );                                                \
    155         (srP)->r_pc = block[0];                           \
    156         (srP)->r_sp = block[1];                           \
    157         (srP)->misc.ARM64.x29 = block[2];                 \
    158         (srP)->misc.ARM64.x30 = block[3];                 \
    159       }
    160 #elif defined(VGP_s390x_linux)
    161 #  define GET_STARTREGS(srP)                              \
    162       { ULong ia, sp, fp, lr;                             \
    163         __asm__ __volatile__(                             \
    164            "bras %0,0f;"                                  \
    165            "0: lgr %1,15;"                                \
    166            "lgr %2,11;"                                   \
    167            "lgr %3,14;"                                   \
    168            : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr)     \
    169            /* no read & clobber */                        \
    170         );                                                \
    171         (srP)->r_pc = ia;                                 \
    172         (srP)->r_sp = sp;                                 \
    173         (srP)->misc.S390X.r_fp = fp;                      \
    174         (srP)->misc.S390X.r_lr = lr;                      \
    175       }
    176 #elif defined(VGP_mips32_linux)
    177 #  define GET_STARTREGS(srP)                              \
    178       { UInt pc, sp, fp, ra, gp;                          \
    179       asm("move $8, $31;"             /* t0 = ra */       \
    180           "bal m_libcassert_get_ip;"  /* ra = pc */       \
    181           "m_libcassert_get_ip:\n"                        \
    182           "move %0, $31;"                                 \
    183           "move $31, $8;"             /* restore lr */    \
    184           "move %1, $29;"                                 \
    185           "move %2, $30;"                                 \
    186           "move %3, $31;"                                 \
    187           "move %4, $28;"                                 \
    188           : "=r" (pc),                                    \
    189             "=r" (sp),                                    \
    190             "=r" (fp),                                    \
    191             "=r" (ra),                                    \
    192             "=r" (gp)                                     \
    193           : /* reads none */                              \
    194           : "$8" /* trashed */ );                         \
    195         (srP)->r_pc = (ULong)pc - 8;                      \
    196         (srP)->r_sp = (ULong)sp;                          \
    197         (srP)->misc.MIPS32.r30 = (ULong)fp;               \
    198         (srP)->misc.MIPS32.r31 = (ULong)ra;               \
    199         (srP)->misc.MIPS32.r28 = (ULong)gp;               \
    200       }
    201 #elif defined(VGP_mips64_linux)
    202 #  define GET_STARTREGS(srP)                              \
    203       { ULong pc, sp, fp, ra, gp;                          \
    204       asm("move $8, $31;"             /* t0 = ra */       \
    205           "bal m_libcassert_get_ip;"  /* ra = pc */       \
    206           "m_libcassert_get_ip:\n"                        \
    207           "move %0, $31;"                                 \
    208           "move $31, $8;"             /* restore lr */    \
    209           "move %1, $29;"                                 \
    210           "move %2, $30;"                                 \
    211           "move %3, $31;"                                 \
    212           "move %4, $28;"                                 \
    213           : "=r" (pc),                                    \
    214             "=r" (sp),                                    \
    215             "=r" (fp),                                    \
    216             "=r" (ra),                                    \
    217             "=r" (gp)                                     \
    218           : /* reads none */                              \
    219           : "$8" /* trashed */ );                         \
    220         (srP)->r_pc = (ULong)pc - 8;                      \
    221         (srP)->r_sp = (ULong)sp;                          \
    222         (srP)->misc.MIPS64.r30 = (ULong)fp;               \
    223         (srP)->misc.MIPS64.r31 = (ULong)ra;               \
    224         (srP)->misc.MIPS64.r28 = (ULong)gp;               \
    225       }
    226 #else
    227 #  error Unknown platform
    228 #endif
    229 
    230 #define BACKTRACE_DEPTH    100         // nice and deep!
    231 
    232 __attribute__ ((__noreturn__))
    233 static void exit_wrk( Int status, Bool gdbserver_call_allowed)
    234 {
    235    static Bool exit_called = False;
    236    // avoid recursive exit during gdbserver call.
    237 
    238    if (gdbserver_call_allowed && !exit_called) {
    239       const ThreadId atid = 1; // Arbitrary tid used to call/terminate gdbsrv.
    240       exit_called = True;
    241       if (status != 0 && VG_(gdbserver_stop_at) (VgdbStopAt_ValgrindAbExit)) {
    242          if (VG_(gdbserver_init_done)()) {
    243             VG_(umsg)("(action at valgrind abnormal exit) vgdb me ... \n");
    244             VG_(gdbserver) (atid);
    245          } else {
    246             VG_(umsg)("(action at valgrind abnormal exit) "
    247                       "Early valgrind exit : vgdb not yet usable\n");
    248          }
    249       }
    250       if (VG_(gdbserver_init_done)()) {
    251          // Always terminate the gdbserver when Valgrind exits, so as
    252          // to e.g. cleanup the FIFOs.
    253          VG_(gdbserver_exit) (atid,
    254                               status == 0 ? VgSrc_ExitProcess : VgSrc_FatalSig);
    255       }
    256    }
    257    exit_called = True;
    258 
    259 #if defined(VGO_linux)
    260    (void)VG_(do_syscall1)(__NR_exit_group, status );
    261 #elif defined(VGO_darwin)
    262    (void)VG_(do_syscall1)(__NR_exit, status );
    263 #else
    264 #  error Unknown OS
    265 #endif
    266    /*NOTREACHED*/
    267    // We really shouldn't reach here.  Just in case we do, use some very crude
    268    // methods to force abort
    269    __builtin_trap();
    270    *(volatile Int*)0 = 'x';
    271 }
    272 
    273 /* Pull down the entire world */
    274 void VG_(exit)( Int status )
    275 {
    276    exit_wrk (status, True);
    277 }
    278 
    279 /* Pull down the entire world */
    280 void VG_(client_exit)( Int status )
    281 {
    282    exit_wrk (status, False);
    283 }
    284 
    285 
    286 // Print the scheduler status.
    287 static void show_sched_status_wrk ( Bool host_stacktrace,
    288                                     Bool valgrind_stack_usage,
    289                                     Bool exited_threads,
    290                                     UnwindStartRegs* startRegsIN)
    291 {
    292    Int i;
    293    if (host_stacktrace) {
    294       const Bool save_clo_xml = VG_(clo_xml);
    295       Addr stacktop;
    296       Addr ips[BACKTRACE_DEPTH];
    297       Int  n_ips;
    298       ThreadState *tst
    299          = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
    300 
    301       // If necessary, fake up an ExeContext which is of our actual real CPU
    302       // state.  Could cause problems if we got the panic/exception within the
    303       // execontext/stack dump/symtab code.  But it's better than nothing.
    304       UnwindStartRegs startRegs;
    305       VG_(memset)(&startRegs, 0, sizeof(startRegs));
    306 
    307       if (startRegsIN == NULL) {
    308          GET_STARTREGS(&startRegs);
    309       } else {
    310          startRegs = *startRegsIN;
    311       }
    312 
    313       stacktop = tst->os_state.valgrind_stack_init_SP;
    314 
    315       n_ips =
    316          VG_(get_StackTrace_wrk)(
    317             0/*tid is unknown*/,
    318             ips, BACKTRACE_DEPTH,
    319             NULL/*array to dump SP values in*/,
    320             NULL/*array to dump FP values in*/,
    321             &startRegs, stacktop
    322          );
    323       VG_(printf)("\nhost stacktrace:\n");
    324       VG_(clo_xml) = False;
    325       VG_(pp_StackTrace) (ips, n_ips);
    326       VG_(clo_xml) = save_clo_xml;
    327    }
    328 
    329    VG_(printf)("\nsched status:\n");
    330    VG_(printf)("  running_tid=%d\n", VG_(get_running_tid)());
    331    for (i = 1; i < VG_N_THREADS; i++) {
    332       VgStack* stack
    333          = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
    334       /* If a thread slot was never used (yet), valgrind_stack_base is 0.
    335          If a thread slot is used by a thread or was used by a thread which
    336          has exited, then valgrind_stack_base points to the stack base. */
    337       if (VG_(threads)[i].status == VgTs_Empty
    338           && (!exited_threads || stack == 0)) continue;
    339       VG_(printf)("\nThread %d: status = %s\n", i,
    340                   VG_(name_of_ThreadStatus)(VG_(threads)[i].status) );
    341       if (VG_(threads)[i].status != VgTs_Empty)
    342          VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
    343       if (valgrind_stack_usage && stack != 0)
    344           VG_(printf)("valgrind stack top usage: %ld of %ld\n",
    345                       VG_STACK_ACTIVE_SZB
    346                       - VG_(am_get_VgStack_unused_szB)(stack,
    347                                                        VG_STACK_ACTIVE_SZB),
    348                       (SizeT) VG_STACK_ACTIVE_SZB);
    349    }
    350    VG_(printf)("\n");
    351 }
    352 
    353 void VG_(show_sched_status) ( Bool host_stacktrace,
    354                               Bool valgrind_stack_usage,
    355                               Bool exited_threads)
    356 {
    357    show_sched_status_wrk (host_stacktrace,
    358                           valgrind_stack_usage,
    359                           exited_threads,
    360                           NULL);
    361 }
    362 
    363 __attribute__ ((noreturn))
    364 static void report_and_quit ( const HChar* report,
    365                               UnwindStartRegs* startRegsIN )
    366 {
    367    show_sched_status_wrk (True,  // host_stacktrace
    368                           False, // valgrind_stack_usage
    369                           False, // exited_threads
    370                           startRegsIN);
    371    VG_(printf)(
    372       "\n"
    373       "Note: see also the FAQ in the source distribution.\n"
    374       "It contains workarounds to several common problems.\n"
    375       "In particular, if Valgrind aborted or crashed after\n"
    376       "identifying problems in your program, there's a good chance\n"
    377       "that fixing those problems will prevent Valgrind aborting or\n"
    378       "crashing, especially if it happened in m_mallocfree.c.\n"
    379       "\n"
    380       "If that doesn't help, please report this bug to: %s\n\n"
    381       "In the bug report, send all the above text, the valgrind\n"
    382       "version, and what OS and version you are using.  Thanks.\n\n",
    383       report);
    384    VG_(exit)(1);
    385 }
    386 
    387 void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
    388                         Int line, const HChar* fn, const HChar* format, ... )
    389 {
    390    va_list vargs;
    391    HChar buf[512];
    392    const HChar* component;
    393    const HChar* bugs_to;
    394    UInt written;
    395 
    396    static Bool entered = False;
    397    if (entered)
    398       VG_(exit)(2);
    399    entered = True;
    400 
    401    va_start(vargs, format);
    402    written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
    403    va_end(vargs);
    404 
    405    if (written >= sizeof(buf)) {
    406       VG_(printf)("\nvalgrind: %s: buf is too small, sizeof(buf) = %u, "
    407                   "written = %d\n", __func__, (unsigned)sizeof(buf), written);
    408    }
    409 
    410    if (isCore) {
    411       component = "valgrind";
    412       bugs_to   = VG_BUGS_TO;
    413    } else {
    414       component = VG_(details).name;
    415       bugs_to   = VG_(details).bug_reports_to;
    416    }
    417 
    418    if (VG_(clo_xml))
    419       VG_(printf_xml)("</valgrindoutput>\n");
    420 
    421    // Treat vg_assert2(0, "foo") specially, as a panicky abort
    422    if (VG_STREQ(expr, "0")) {
    423       VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
    424                   component, file, line, fn );
    425    } else {
    426       VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
    427                   component, file, line, fn, expr );
    428    }
    429    if (!VG_STREQ(buf, ""))
    430       VG_(printf)("%s: %s\n", component, buf );
    431 
    432    report_and_quit(bugs_to, NULL);
    433 }
    434 
    435 __attribute__ ((noreturn))
    436 static void panic ( const HChar* name, const HChar* report, const HChar* str,
    437                     UnwindStartRegs* startRegs )
    438 {
    439    if (VG_(clo_xml))
    440       VG_(printf_xml)("</valgrindoutput>\n");
    441    VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
    442    report_and_quit(report, startRegs);
    443 }
    444 
    445 void VG_(core_panic_at) ( const HChar* str, UnwindStartRegs* startRegs )
    446 {
    447    panic("valgrind", VG_BUGS_TO, str, startRegs);
    448 }
    449 
    450 void VG_(core_panic) ( const HChar* str )
    451 {
    452    VG_(core_panic_at)(str, NULL);
    453 }
    454 
    455 void VG_(tool_panic) ( const HChar* str )
    456 {
    457    panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
    458 }
    459 
    460 /* Print some helpful-ish text about unimplemented things, and give up. */
    461 void VG_(unimplemented) ( const HChar* msg )
    462 {
    463    if (VG_(clo_xml))
    464       VG_(printf_xml)("</valgrindoutput>\n");
    465    VG_(umsg)("\n");
    466    VG_(umsg)("Valgrind detected that your program requires\n");
    467    VG_(umsg)("the following unimplemented functionality:\n");
    468    VG_(umsg)("   %s\n", msg);
    469    VG_(umsg)("This may be because the functionality is hard to implement,\n");
    470    VG_(umsg)("or because no reasonable program would behave this way,\n");
    471    VG_(umsg)("or because nobody has yet needed it.  "
    472              "In any case, let us know at\n");
    473    VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
    474              VG_BUGS_TO);
    475    VG_(umsg)("\n");
    476    VG_(umsg)("Valgrind has to exit now.  Sorry.  Bye!\n");
    477    VG_(umsg)("\n");
    478    VG_(show_sched_status)(False,  // host_stacktrace
    479                           False,  // valgrind_stack_usage
    480                           False); // exited_threads
    481    VG_(exit)(1);
    482 }
    483 
    484 /*--------------------------------------------------------------------*/
    485 /*--- end                                                          ---*/
    486 /*--------------------------------------------------------------------*/
    487