drd/tests/tsan_thread_wrappers_pthread.h: Fix MyThread::ThreadBody()
[valgrind.git] / VEX / priv / main_util.c
blobe9a496be024b79301a30c3d68061e41bbdbacb6f
2 /*---------------------------------------------------------------*/
3 /*--- begin main_util.c ---*/
4 /*---------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2004-2017 OpenWorks LLP
11 info@open-works.net
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
28 The GNU General Public License is contained in the file COPYING.
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
36 #include "libvex_basictypes.h"
37 #include "libvex.h"
39 #include "main_globals.h"
40 #include "main_util.h"
43 /*---------------------------------------------------------*/
44 /*--- Storage ---*/
45 /*---------------------------------------------------------*/
47 /* Try to keep this as low as possible -- in particular, less than the
48 size of the smallest L2 cache we might encounter. At 50000, my VIA
49 Nehemiah 1 GHz (a weedy machine) can satisfy 27 million calls/
50 second to LibVEX_Alloc(16) -- that is, allocate memory at over 400
51 MByte/sec. Once the size increases enough to fall out of the cache
52 into memory, the rate falls by about a factor of 3.
55 #if defined(ENABLE_INNER)
56 /* 5 times more memory to be on the safe side: consider each allocation is
57 8 bytes, and we need 16 bytes redzone before and after. */
58 #define N_TEMPORARY_BYTES (5*5000000)
59 static Bool mempools_created = False;
60 #else
61 #define N_TEMPORARY_BYTES 5000000
62 #endif
64 static HChar temporary[N_TEMPORARY_BYTES] __attribute__((aligned(REQ_ALIGN)));
65 static HChar* temporary_first = &temporary[0];
66 static HChar* temporary_curr = &temporary[0];
67 static HChar* temporary_last = &temporary[N_TEMPORARY_BYTES-1];
69 static ULong temporary_bytes_allocd_TOT = 0;
71 #if defined(ENABLE_INNER)
72 /* See N_TEMPORARY_BYTES */
73 #define N_PERMANENT_BYTES (5*10000)
74 #else
75 #define N_PERMANENT_BYTES 10000
76 #endif
78 static HChar permanent[N_PERMANENT_BYTES] __attribute__((aligned(REQ_ALIGN)));
79 static HChar* permanent_first = &permanent[0];
80 static HChar* permanent_curr = &permanent[0];
81 static HChar* permanent_last = &permanent[N_PERMANENT_BYTES-1];
83 HChar* private_LibVEX_alloc_first = &temporary[0];
84 HChar* private_LibVEX_alloc_curr = &temporary[0];
85 HChar* private_LibVEX_alloc_last = &temporary[N_TEMPORARY_BYTES-1];
88 static VexAllocMode mode = VexAllocModeTEMP;
90 void vexAllocSanityCheck ( void )
92 vassert(temporary_first == &temporary[0]);
93 vassert(temporary_last == &temporary[N_TEMPORARY_BYTES-1]);
94 vassert(permanent_first == &permanent[0]);
95 vassert(permanent_last == &permanent[N_PERMANENT_BYTES-1]);
96 vassert(temporary_first <= temporary_curr);
97 vassert(temporary_curr <= temporary_last);
98 vassert(permanent_first <= permanent_curr);
99 vassert(permanent_curr <= permanent_last);
100 vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr);
101 vassert(private_LibVEX_alloc_curr <= private_LibVEX_alloc_last);
102 if (mode == VexAllocModeTEMP){
103 vassert(private_LibVEX_alloc_first == temporary_first);
104 vassert(private_LibVEX_alloc_last == temporary_last);
106 else
107 if (mode == VexAllocModePERM) {
108 vassert(private_LibVEX_alloc_first == permanent_first);
109 vassert(private_LibVEX_alloc_last == permanent_last);
111 else
112 vassert(0);
114 # define IS_WORD_ALIGNED(p) (0 == (((HWord)p) & (sizeof(HWord)-1)))
115 vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
116 vassert(IS_WORD_ALIGNED(temporary_first));
117 vassert(IS_WORD_ALIGNED(temporary_curr));
118 vassert(IS_WORD_ALIGNED(temporary_last+1));
119 vassert(IS_WORD_ALIGNED(permanent_first));
120 vassert(IS_WORD_ALIGNED(permanent_curr));
121 vassert(IS_WORD_ALIGNED(permanent_last+1));
122 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first));
123 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr));
124 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1));
125 # undef IS_WORD_ALIGNED
128 /* The current allocation mode. */
130 void vexSetAllocMode ( VexAllocMode m )
132 vexAllocSanityCheck();
134 /* Save away the current allocation point .. */
135 if (mode == VexAllocModeTEMP){
136 temporary_curr = private_LibVEX_alloc_curr;
138 else
139 if (mode == VexAllocModePERM) {
140 permanent_curr = private_LibVEX_alloc_curr;
142 else
143 vassert(0);
145 /* Did that screw anything up? */
146 vexAllocSanityCheck();
148 if (m == VexAllocModeTEMP){
149 private_LibVEX_alloc_first = temporary_first;
150 private_LibVEX_alloc_curr = temporary_curr;
151 private_LibVEX_alloc_last = temporary_last;
153 else
154 if (m == VexAllocModePERM) {
155 private_LibVEX_alloc_first = permanent_first;
156 private_LibVEX_alloc_curr = permanent_curr;
157 private_LibVEX_alloc_last = permanent_last;
159 else
160 vassert(0);
162 mode = m;
165 VexAllocMode vexGetAllocMode ( void )
167 return mode;
170 __attribute__((noreturn))
171 void private_LibVEX_alloc_OOM(void)
173 const HChar* pool = "???";
174 if (private_LibVEX_alloc_first == &temporary[0]) pool = "TEMP";
175 if (private_LibVEX_alloc_first == &permanent[0]) pool = "PERM";
176 vex_printf("VEX temporary storage exhausted.\n");
177 vex_printf("Pool = %s, start %p curr %p end %p (size %lld)\n",
178 pool,
179 private_LibVEX_alloc_first,
180 private_LibVEX_alloc_curr,
181 private_LibVEX_alloc_last,
182 (Long)(private_LibVEX_alloc_last + 1 - private_LibVEX_alloc_first));
183 vpanic("VEX temporary storage exhausted.\n"
184 "Increase N_{TEMPORARY,PERMANENT}_BYTES and recompile.");
187 void vexSetAllocModeTEMP_and_clear ( void )
189 /* vassert(vex_initdone); */ /* causes infinite assert loops */
190 temporary_bytes_allocd_TOT
191 += (ULong)(private_LibVEX_alloc_curr - private_LibVEX_alloc_first);
193 #if defined(ENABLE_INNER)
194 if (mempools_created) {
195 VALGRIND_MEMPOOL_TRIM(&temporary[0], &temporary[0], 0);
196 } else {
197 VALGRIND_CREATE_MEMPOOL(&temporary[0], VEX_REDZONE_SIZEB, 0);
198 VALGRIND_CREATE_MEMPOOL(&permanent[0], VEX_REDZONE_SIZEB, 0);
199 VALGRIND_MAKE_MEM_NOACCESS(&permanent[0], N_PERMANENT_BYTES);
200 mempools_created = True;
202 VALGRIND_MAKE_MEM_NOACCESS(&temporary[0], N_TEMPORARY_BYTES);
203 #endif
205 mode = VexAllocModeTEMP;
206 temporary_curr = &temporary[0];
207 private_LibVEX_alloc_curr = &temporary[0];
209 /* Set to (1) and change the fill byte to 0x00 or 0xFF to test for
210 any potential bugs due to using uninitialised memory in the main
211 VEX storage area. */
212 if (0) {
213 Int i;
214 for (i = 0; i < N_TEMPORARY_BYTES; i++)
215 temporary[i] = 0x00;
218 vexAllocSanityCheck();
222 /* Exported to library client. */
224 void LibVEX_ShowAllocStats ( void )
226 vex_printf("vex storage: T total %lld bytes allocated\n",
227 (Long)temporary_bytes_allocd_TOT );
228 vex_printf("vex storage: P total %lld bytes allocated\n",
229 (Long)(permanent_curr - permanent_first) );
232 void *LibVEX_Alloc ( SizeT nbytes )
234 return LibVEX_Alloc_inline(nbytes);
237 /*---------------------------------------------------------*/
238 /*--- Bombing out ---*/
239 /*---------------------------------------------------------*/
241 __attribute__ ((noreturn))
242 void vex_assert_fail ( const HChar* expr,
243 const HChar* file, Int line, const HChar* fn )
245 vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
246 file, line, fn, expr );
247 (*vex_failure_exit)();
250 /* To be used in assert-like (i.e. should never ever happen) situations */
251 __attribute__ ((noreturn))
252 void vpanic ( const HChar* str )
254 vex_printf("\nvex: the `impossible' happened:\n %s\n", str);
255 (*vex_failure_exit)();
259 /*---------------------------------------------------------*/
260 /*--- vex_printf ---*/
261 /*---------------------------------------------------------*/
263 /* This should be the only <...> include in the entire VEX library.
264 New code for vex_util.c should go above this point. */
265 #include <stdarg.h>
267 SizeT vex_strlen ( const HChar* str )
269 SizeT i = 0;
270 while (str[i] != 0) i++;
271 return i;
274 Bool vex_streq ( const HChar* s1, const HChar* s2 )
276 while (True) {
277 if (*s1 == 0 && *s2 == 0)
278 return True;
279 if (*s1 != *s2)
280 return False;
281 s1++;
282 s2++;
286 /* Vectorised memset, copied from Valgrind's m_libcbase.c. */
287 void vex_bzero ( void* sV, SizeT n )
289 # define IS_4_ALIGNED(aaa_p) (0 == (((HWord)(aaa_p)) & ((HWord)0x3)))
291 UChar* d = sV;
293 while ((!IS_4_ALIGNED(d)) && n >= 1) {
294 d[0] = 0;
295 d++;
296 n--;
298 if (n == 0)
299 return;
300 while (n >= 16) {
301 ((UInt*)d)[0] = 0;
302 ((UInt*)d)[1] = 0;
303 ((UInt*)d)[2] = 0;
304 ((UInt*)d)[3] = 0;
305 d += 16;
306 n -= 16;
308 while (n >= 4) {
309 ((UInt*)d)[0] = 0;
310 d += 4;
311 n -= 4;
313 while (n >= 1) {
314 d[0] = 0;
315 d++;
316 n--;
318 return;
319 # undef IS_4_ALIGNED
323 /* Convert N0 into ascii in BUF, which is assumed to be big enough (at
324 least 67 bytes long). Observe BASE, SYNED and HEXCAPS. */
325 static
326 void convert_int ( /*OUT*/HChar* buf, Long n0,
327 Int base, Bool syned, Bool hexcaps )
329 ULong u0;
330 HChar c;
331 Bool minus = False;
332 Int i, j, bufi = 0;
333 buf[bufi] = 0;
335 if (syned) {
336 if (n0 < 0) {
337 minus = True;
338 u0 = (ULong)(-n0);
339 } else {
340 u0 = (ULong)(n0);
342 } else {
343 u0 = (ULong)n0;
346 while (1) {
347 buf[bufi++] = toHChar('0' + toUInt(u0 % base));
348 u0 /= base;
349 if (u0 == 0) break;
351 if (minus)
352 buf[bufi++] = '-';
354 buf[bufi] = 0;
355 for (i = 0; i < bufi; i++)
356 if (buf[i] > '9')
357 buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
359 i = 0;
360 j = bufi-1;
361 while (i <= j) {
362 c = buf[i];
363 buf[i] = buf[j];
364 buf[j] = c;
365 i++;
366 j--;
371 /* A half-arsed and buggy, but good-enough, implementation of
372 printf. */
373 static
374 UInt vprintf_wrk ( void(*sink)(HChar),
375 const HChar* format,
376 va_list ap )
378 # define PUT(_ch) \
379 do { sink(_ch); nout++; } \
380 while (0)
382 # define PAD(_n) \
383 do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
384 while (0)
386 # define PUTSTR(_str) \
387 do { const HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
388 while (0)
390 const HChar* saved_format;
391 Bool longlong, ljustify, is_sizet;
392 HChar padchar;
393 Int fwidth, nout, len1, len3;
394 SizeT len2;
395 HChar intbuf[100]; /* big enough for a 64-bit # in base 2 */
397 nout = 0;
398 while (1) {
400 if (!format)
401 break;
402 if (*format == 0)
403 break;
405 if (*format != '%') {
406 PUT(*format);
407 format++;
408 continue;
411 saved_format = format;
412 longlong = is_sizet = False;
413 ljustify = False;
414 padchar = ' ';
415 fwidth = 0;
416 format++;
418 if (*format == '-') {
419 format++;
420 ljustify = True;
422 if (*format == '0') {
423 format++;
424 padchar = '0';
426 if (*format == '*') {
427 fwidth = va_arg(ap, Int);
428 vassert(fwidth >= 0);
429 format++;
430 } else {
431 while (*format >= '0' && *format <= '9') {
432 fwidth = fwidth * 10 + (*format - '0');
433 format++;
436 if (*format == 'l') {
437 format++;
438 if (*format == 'l') {
439 format++;
440 longlong = True;
442 } else if (*format == 'z') {
443 format++;
444 is_sizet = True;
447 switch (*format) {
448 case 's': {
449 const HChar* str = va_arg(ap, HChar*);
450 if (str == NULL)
451 str = "(null)";
452 len1 = len3 = 0;
453 len2 = vex_strlen(str);
454 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
455 len3 = ljustify ? fwidth-len2 : 0; }
456 PAD(len1); PUTSTR(str); PAD(len3);
457 break;
459 case 'c': {
460 HChar c = (HChar)va_arg(ap, int);
461 HChar str[2];
462 str[0] = c;
463 str[1] = 0;
464 len1 = len3 = 0;
465 len2 = vex_strlen(str);
466 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
467 len3 = ljustify ? fwidth-len2 : 0; }
468 PAD(len1); PUTSTR(str); PAD(len3);
469 break;
471 case 'd': {
472 Long l;
473 vassert(is_sizet == False); // %zd is obscure; we don't allow it
474 if (longlong) {
475 l = va_arg(ap, Long);
476 } else {
477 l = (Long)va_arg(ap, Int);
479 convert_int(intbuf, l, 10/*base*/, True/*signed*/,
480 False/*irrelevant*/);
481 len1 = len3 = 0;
482 len2 = vex_strlen(intbuf);
483 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
484 len3 = ljustify ? fwidth-len2 : 0; }
485 PAD(len1); PUTSTR(intbuf); PAD(len3);
486 break;
488 case 'u':
489 case 'x':
490 case 'X': {
491 Int base = *format == 'u' ? 10 : 16;
492 Bool hexcaps = True; /* *format == 'X'; */
493 ULong l;
494 if (is_sizet) {
495 l = (ULong)va_arg(ap, SizeT);
496 } else if (longlong) {
497 l = va_arg(ap, ULong);
498 } else {
499 l = (ULong)va_arg(ap, UInt);
501 convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
502 len1 = len3 = 0;
503 len2 = vex_strlen(intbuf);
504 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
505 len3 = ljustify ? fwidth-len2 : 0; }
506 PAD(len1); PUTSTR(intbuf); PAD(len3);
507 break;
509 case 'p':
510 case 'P': {
511 Bool hexcaps = toBool(*format == 'P');
512 ULong l = (Addr)va_arg(ap, void*);
513 convert_int(intbuf, l, 16/*base*/, False/*unsigned*/, hexcaps);
514 len1 = len3 = 0;
515 len2 = vex_strlen(intbuf)+2;
516 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
517 len3 = ljustify ? fwidth-len2 : 0; }
518 PAD(len1); PUT('0'); PUT('x'); PUTSTR(intbuf); PAD(len3);
519 break;
521 case '%': {
522 PUT('%');
523 break;
525 default:
526 /* no idea what it is. Print the format literally and
527 move on. */
528 while (saved_format <= format) {
529 PUT(*saved_format);
530 saved_format++;
532 break;
535 format++;
539 return nout;
541 # undef PUT
542 # undef PAD
543 # undef PUTSTR
547 /* A general replacement for printf(). Note that only low-level
548 debugging info should be sent via here. The official route is to
549 to use vg_message(). This interface is deprecated.
551 static HChar myprintf_buf[1000];
552 static Int n_myprintf_buf;
554 static void add_to_myprintf_buf ( HChar c )
556 Bool emit = toBool(c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/);
557 myprintf_buf[n_myprintf_buf++] = c;
558 myprintf_buf[n_myprintf_buf] = 0;
559 if (emit) {
560 (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
561 n_myprintf_buf = 0;
562 myprintf_buf[n_myprintf_buf] = 0;
566 static UInt vex_vprintf ( const HChar* format, va_list vargs )
568 UInt ret;
570 n_myprintf_buf = 0;
571 myprintf_buf[n_myprintf_buf] = 0;
572 ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
574 if (n_myprintf_buf > 0) {
575 (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
578 return ret;
581 UInt vex_printf ( const HChar* format, ... )
583 UInt ret;
584 va_list vargs;
585 va_start(vargs, format);
586 ret = vex_vprintf(format, vargs);
587 va_end(vargs);
589 return ret;
592 /* Use this function to communicate to users that a (legitimate) situation
593 occured that we cannot handle (yet). */
594 __attribute__ ((noreturn))
595 void vfatal ( const HChar* format, ... )
597 va_list vargs;
598 va_start(vargs, format);
599 vex_vprintf( format, vargs );
600 va_end(vargs);
601 vex_printf("Cannot continue. Good-bye\n\n");
603 (*vex_failure_exit)();
606 /* A general replacement for sprintf(). */
608 static HChar *vg_sprintf_ptr;
610 static void add_to_vg_sprintf_buf ( HChar c )
612 *vg_sprintf_ptr++ = c;
615 UInt vex_sprintf ( HChar* buf, const HChar *format, ... )
617 Int ret;
618 va_list vargs;
620 vg_sprintf_ptr = buf;
622 va_start(vargs,format);
624 ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
625 add_to_vg_sprintf_buf(0);
627 va_end(vargs);
629 vassert(vex_strlen(buf) == ret);
630 return ret;
634 /*---------------------------------------------------------*/
635 /*--- Misaligned memory access support ---*/
636 /*---------------------------------------------------------*/
638 UInt read_misaligned_UInt_LE ( void* addr )
640 UChar* p = (UChar*)addr;
641 UInt w = 0;
642 w = (w << 8) | p[3];
643 w = (w << 8) | p[2];
644 w = (w << 8) | p[1];
645 w = (w << 8) | p[0];
646 return w;
649 ULong read_misaligned_ULong_LE ( void* addr )
651 UChar* p = (UChar*)addr;
652 ULong w = 0;
653 w = (w << 8) | p[7];
654 w = (w << 8) | p[6];
655 w = (w << 8) | p[5];
656 w = (w << 8) | p[4];
657 w = (w << 8) | p[3];
658 w = (w << 8) | p[2];
659 w = (w << 8) | p[1];
660 w = (w << 8) | p[0];
661 return w;
664 void write_misaligned_UInt_LE ( void* addr, UInt w )
666 UChar* p = (UChar*)addr;
667 p[0] = (w & 0xFF); w >>= 8;
668 p[1] = (w & 0xFF); w >>= 8;
669 p[2] = (w & 0xFF); w >>= 8;
670 p[3] = (w & 0xFF); w >>= 8;
673 void write_misaligned_ULong_LE ( void* addr, ULong w )
675 UChar* p = (UChar*)addr;
676 p[0] = (w & 0xFF); w >>= 8;
677 p[1] = (w & 0xFF); w >>= 8;
678 p[2] = (w & 0xFF); w >>= 8;
679 p[3] = (w & 0xFF); w >>= 8;
680 p[4] = (w & 0xFF); w >>= 8;
681 p[5] = (w & 0xFF); w >>= 8;
682 p[6] = (w & 0xFF); w >>= 8;
683 p[7] = (w & 0xFF); w >>= 8;
687 /*---------------------------------------------------------------*/
688 /*--- end main_util.c ---*/
689 /*---------------------------------------------------------------*/