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