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-2017 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 #else
    230 #  error Unknown platform
    231 #endif
    232 
    233 #define BACKTRACE_DEPTH    100         // nice and deep!
    234 
    235 __attribute__ ((__noreturn__))
    236 static void exit_wrk( Int status, Bool gdbserver_call_allowed)
    237 {
    238    static Bool exit_called = False;
    239    // avoid recursive exit during gdbserver call.
    240 
    241    if (gdbserver_call_allowed && !exit_called) {
    242       const ThreadId atid = 1; // Arbitrary tid used to call/terminate gdbsrv.
    243       exit_called = True;
    244       if (status != 0
    245           && VgdbStopAtiS(VgdbStopAt_ValgrindAbExit, VG_(clo_vgdb_stop_at))) {
    246          if (VG_(gdbserver_init_done)()) {
    247             VG_(umsg)("(action at valgrind abnormal exit) vgdb me ... \n");
    248             VG_(gdbserver) (atid);
    249          } else {
    250             VG_(umsg)("(action at valgrind abnormal exit)\n"
    251                       "valgrind exit is too early => vgdb not yet usable\n");
    252          }
    253       }
    254       if (VG_(gdbserver_init_done)()) {
    255          // Always terminate the gdbserver when Valgrind exits, so as
    256          // to e.g. cleanup the FIFOs.
    257          VG_(gdbserver_exit) (atid,
    258                               status == 0 ? VgSrc_ExitProcess : VgSrc_FatalSig);
    259       }
    260    }
    261    exit_called = True;
    262 
    263    VG_(exit_now) (status);
    264 }
    265 
    266 /* Call the appropriate system call and nothing else. This function should
    267    be called in places where the dependencies of VG_(exit) need to be
    268    avoided. */
    269 __attribute__ ((__noreturn__))
    270 void VG_(exit_now)( Int status )
    271 {
    272 #if defined(VGO_linux)
    273    (void)VG_(do_syscall1)(__NR_exit_group, status );
    274 #elif defined(VGO_darwin) || defined(VGO_solaris)
    275    (void)VG_(do_syscall1)(__NR_exit, status );
    276 #else
    277 #  error Unknown OS
    278 #endif
    279    /*NOTREACHED*/
    280    // We really shouldn't reach here.  Just in case we do, use some very crude
    281    // methods to force abort
    282    __builtin_trap();
    283    *(volatile Int*)0 = 'x';
    284 }
    285 
    286 /* Pull down the entire world */
    287 void VG_(exit)( Int status )
    288 {
    289    exit_wrk (status, True);
    290 }
    291 
    292 /* Pull down the entire world */
    293 void VG_(client_exit)( Int status )
    294 {
    295    exit_wrk (status, False);
    296 }
    297 
    298 static void print_thread_state (Bool stack_usage,
    299                                 const HChar* prefix, ThreadId i)
    300 {
    301    VgStack *stack
    302       = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
    303 
    304    VG_(printf)("\n%sThread %d: status = %s (lwpid %d)\n", prefix, i,
    305                VG_(name_of_ThreadStatus)(VG_(threads)[i].status),
    306                VG_(threads)[i].os_state.lwpid);
    307    if (VG_(threads)[i].status != VgTs_Empty)
    308       VG_(get_and_pp_StackTrace)( i, BACKTRACE_DEPTH );
    309    if (stack_usage && VG_(threads)[i].client_stack_highest_byte != 0 ) {
    310       Addr start, end;
    311 
    312       start = end = 0;
    313       VG_(stack_limits)(VG_(get_SP)(i), &start, &end);
    314       if (start != end)
    315          VG_(printf)("%sclient stack range: [%p %p] client SP: %p\n",
    316                      prefix,
    317                      (void*)start, (void*)end, (void*)VG_(get_SP)(i));
    318       else
    319          VG_(printf)("%sclient stack range: ??????? client SP: %p\n",
    320                      prefix,
    321                      (void*)VG_(get_SP)(i));
    322    }
    323    if (stack_usage && stack != 0)
    324       VG_(printf)
    325          ("%svalgrind stack top usage: %lu of %lu\n",
    326           prefix,
    327           VG_(clo_valgrind_stacksize)
    328           - VG_(am_get_VgStack_unused_szB) (stack,
    329                                             VG_(clo_valgrind_stacksize)),
    330           (SizeT) VG_(clo_valgrind_stacksize));
    331 }
    332 
    333 // Print the scheduler status.
    334 static void show_sched_status_wrk ( Bool host_stacktrace,
    335                                     Bool stack_usage,
    336                                     Bool exited_threads,
    337                                     const UnwindStartRegs* startRegsIN)
    338 {
    339    Int i;
    340    if (host_stacktrace) {
    341       const Bool save_clo_xml = VG_(clo_xml);
    342       Addr stacktop;
    343       Addr ips[BACKTRACE_DEPTH];
    344       Int  n_ips;
    345       ThreadState *tst
    346          = VG_(get_ThreadState)( VG_(lwpid_to_vgtid)( VG_(gettid)() ) );
    347 
    348       // If necessary, fake up an ExeContext which is of our actual real CPU
    349       // state.  Could cause problems if we got the panic/exception within the
    350       // execontext/stack dump/symtab code.  But it's better than nothing.
    351       UnwindStartRegs startRegs;
    352       VG_(memset)(&startRegs, 0, sizeof(startRegs));
    353 
    354       if (startRegsIN == NULL) {
    355          GET_STARTREGS(&startRegs);
    356       } else {
    357          startRegs = *startRegsIN;
    358       }
    359 
    360       stacktop = tst->os_state.valgrind_stack_init_SP;
    361 
    362       n_ips =
    363          VG_(get_StackTrace_wrk)(
    364             0/*tid is unknown*/,
    365             ips, BACKTRACE_DEPTH,
    366             NULL/*array to dump SP values in*/,
    367             NULL/*array to dump FP values in*/,
    368             &startRegs, stacktop
    369          );
    370       VG_(printf)("\nhost stacktrace:\n");
    371       VG_(clo_xml) = False;
    372       VG_(pp_StackTrace) (ips, n_ips);
    373       VG_(clo_xml) = save_clo_xml;
    374    }
    375 
    376    VG_(printf)("\nsched status:\n");
    377    if (VG_(threads) == NULL) {
    378       VG_(printf)("  scheduler not yet initialised\n");
    379    } else {
    380       VG_(printf)("  running_tid=%u\n", VG_(get_running_tid)());
    381       for (i = 1; i < VG_N_THREADS; i++) {
    382          VgStack *stack
    383             = (VgStack*)VG_(threads)[i].os_state.valgrind_stack_base;
    384          /* If a thread slot was never used (yet), valgrind_stack_base is 0.
    385             If a thread slot is used by a thread or was used by a thread which
    386             has exited, then valgrind_stack_base points to the stack base. */
    387          if (VG_(threads)[i].status == VgTs_Empty
    388              && (!exited_threads || stack == 0)) continue;
    389          print_thread_state(stack_usage, "", i);
    390          if (VG_(inner_threads) != NULL) {
    391             /* An inner V has informed us (the outer) of its thread array.
    392                Report the inner guest stack trace. */
    393             UInt inner_tid;
    394 
    395             for (inner_tid = 1; inner_tid < VG_N_THREADS; inner_tid++) {
    396                if (VG_(threads)[i].os_state.lwpid
    397                    == VG_(inner_threads)[inner_tid].os_state.lwpid) {
    398                   ThreadState* save_outer_vg_threads = VG_(threads);
    399 
    400                   VG_(threads) = VG_(inner_threads);
    401                   print_thread_state(stack_usage, "INNER ", inner_tid);
    402                   VG_(threads) = save_outer_vg_threads;
    403                   break;
    404                }
    405             }
    406          }
    407       }
    408    }
    409    VG_(printf)("\n");
    410 }
    411 
    412 void VG_(show_sched_status) ( Bool host_stacktrace,
    413                               Bool stack_usage,
    414                               Bool exited_threads)
    415 {
    416    show_sched_status_wrk (host_stacktrace,
    417                           stack_usage,
    418                           exited_threads,
    419                           NULL);
    420 }
    421 
    422 __attribute__ ((noreturn))
    423 static void report_and_quit ( const HChar* report,
    424                               const UnwindStartRegs* startRegsIN )
    425 {
    426    show_sched_status_wrk (True,  // host_stacktrace
    427                           False, // stack_usage
    428                           False, // exited_threads
    429                           startRegsIN);
    430    VG_(printf)(
    431       "\n"
    432       "Note: see also the FAQ in the source distribution.\n"
    433       "It contains workarounds to several common problems.\n"
    434       "In particular, if Valgrind aborted or crashed after\n"
    435       "identifying problems in your program, there's a good chance\n"
    436       "that fixing those problems will prevent Valgrind aborting or\n"
    437       "crashing, especially if it happened in m_mallocfree.c.\n"
    438       "\n"
    439       "If that doesn't help, please report this bug to: %s\n\n"
    440       "In the bug report, send all the above text, the valgrind\n"
    441       "version, and what OS and version you are using.  Thanks.\n\n",
    442       report);
    443    VG_(exit)(1);
    444 }
    445 
    446 void VG_(assert_fail) ( Bool isCore, const HChar* expr, const HChar* file,
    447                         Int line, const HChar* fn, const HChar* format, ... )
    448 {
    449    va_list vargs, vargs_copy;
    450    const HChar* component;
    451    const HChar* bugs_to;
    452    UInt written;
    453 
    454    static Bool entered = False;
    455    if (entered)
    456       VG_(exit)(2);
    457    entered = True;
    458 
    459    if (isCore) {
    460       component = "valgrind";
    461       bugs_to   = VG_BUGS_TO;
    462    } else {
    463       component = VG_(details).name;
    464       bugs_to   = VG_(details).bug_reports_to;
    465    }
    466 
    467    if (VG_(clo_xml))
    468       VG_(printf_xml)("</valgrindoutput>\n");
    469 
    470    // Treat vg_assert2(0, "foo") specially, as a panicky abort
    471    if (VG_STREQ(expr, "0")) {
    472       VG_(printf)("\n%s: %s:%d (%s): the 'impossible' happened.\n",
    473                   component, file, line, fn );
    474    } else {
    475       VG_(printf)("\n%s: %s:%d (%s): Assertion '%s' failed.\n",
    476                   component, file, line, fn, expr );
    477    }
    478 
    479    /* Check whether anything will be written */
    480    HChar buf[5];
    481    va_start(vargs, format);
    482    va_copy(vargs_copy, vargs);
    483    written = VG_(vsnprintf) ( buf, sizeof(buf), format, vargs );
    484    va_end(vargs);
    485 
    486    if (written > 0) {
    487       VG_(printf)("%s: ", component);
    488       VG_(vprintf)(format, vargs_copy);
    489       VG_(printf)("\n");
    490    }
    491 
    492    report_and_quit(bugs_to, NULL);
    493 }
    494 
    495 __attribute__ ((noreturn))
    496 static void panic ( const HChar* name, const HChar* report, const HChar* str,
    497                     const UnwindStartRegs* startRegs )
    498 {
    499    if (VG_(clo_xml))
    500       VG_(printf_xml)("</valgrindoutput>\n");
    501    VG_(printf)("\n%s: the 'impossible' happened:\n   %s\n", name, str);
    502    report_and_quit(report, startRegs);
    503 }
    504 
    505 void VG_(core_panic_at) ( const HChar* str, const UnwindStartRegs* startRegs )
    506 {
    507    panic("valgrind", VG_BUGS_TO, str, startRegs);
    508 }
    509 
    510 void VG_(core_panic) ( const HChar* str )
    511 {
    512    VG_(core_panic_at)(str, NULL);
    513 }
    514 
    515 void VG_(tool_panic) ( const HChar* str )
    516 {
    517    panic(VG_(details).name, VG_(details).bug_reports_to, str, NULL);
    518 }
    519 
    520 /* Print some helpful-ish text about unimplemented things, and give up. */
    521 void VG_(unimplemented) ( const HChar* format, ... )
    522 {
    523    va_list vargs;
    524    HChar msg[256];
    525 
    526    va_start(vargs, format);
    527    VG_(vsnprintf)(msg, sizeof(msg), format, vargs);
    528    va_end(vargs);
    529 
    530    if (VG_(clo_xml))
    531       VG_(printf_xml)("</valgrindoutput>\n");
    532    VG_(umsg)("\n");
    533    VG_(umsg)("Valgrind detected that your program requires\n");
    534    VG_(umsg)("the following unimplemented functionality:\n");
    535    VG_(umsg)("   %s\n", msg);
    536    VG_(umsg)("This may be because the functionality is hard to implement,\n");
    537    VG_(umsg)("or because no reasonable program would behave this way,\n");
    538    VG_(umsg)("or because nobody has yet needed it.  "
    539              "In any case, let us know at\n");
    540    VG_(umsg)("%s and/or try to work around the problem, if you can.\n",
    541              VG_BUGS_TO);
    542    VG_(umsg)("\n");
    543    VG_(umsg)("Valgrind has to exit now.  Sorry.  Bye!\n");
    544    VG_(umsg)("\n");
    545    VG_(show_sched_status)(False,  // host_stacktrace
    546                           False,  // stack_usage
    547                           False); // exited_threads
    548    VG_(exit)(1);
    549 }
    550 
    551 /*--------------------------------------------------------------------*/
    552 /*--- end                                                          ---*/
    553 /*--------------------------------------------------------------------*/
    554