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