-> 3.20.0 final
[valgrind.git] / VEX / priv / main_util.c
blob670de8b040887a0d5066011e99f564f5cf8ef7f7
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, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
28 Neither the names of the U.S. Department of Energy nor the
29 University of California nor the names of its contributors may be
30 used to endorse or promote products derived from this software
31 without prior written permission.
34 #include "libvex_basictypes.h"
35 #include "libvex.h"
37 #include "main_globals.h"
38 #include "main_util.h"
41 /*---------------------------------------------------------*/
42 /*--- Storage ---*/
43 /*---------------------------------------------------------*/
45 /* Try to keep this as low as possible -- in particular, less than the
46 size of the smallest L2 cache we might encounter. At 50000, my VIA
47 Nehemiah 1 GHz (a weedy machine) can satisfy 27 million calls/
48 second to LibVEX_Alloc(16) -- that is, allocate memory at over 400
49 MByte/sec. Once the size increases enough to fall out of the cache
50 into memory, the rate falls by about a factor of 3.
53 #if defined(ENABLE_INNER)
54 /* 5 times more memory to be on the safe side: consider each allocation is
55 8 bytes, and we need 16 bytes redzone before and after. */
56 #define N_TEMPORARY_BYTES (5*5000000)
57 static Bool mempools_created = False;
58 #else
59 #define N_TEMPORARY_BYTES 5000000
60 #endif
62 static HChar temporary[N_TEMPORARY_BYTES] __attribute__((aligned(REQ_ALIGN)));
63 static HChar* temporary_first = &temporary[0];
64 static HChar* temporary_curr = &temporary[0];
65 static HChar* temporary_last = &temporary[N_TEMPORARY_BYTES-1];
67 static ULong temporary_bytes_allocd_TOT = 0;
69 #if defined(ENABLE_INNER)
70 /* See N_TEMPORARY_BYTES */
71 #define N_PERMANENT_BYTES (5*10000)
72 #else
73 #define N_PERMANENT_BYTES 10000
74 #endif
76 static HChar permanent[N_PERMANENT_BYTES] __attribute__((aligned(REQ_ALIGN)));
77 static HChar* permanent_first = &permanent[0];
78 static HChar* permanent_curr = &permanent[0];
79 static HChar* permanent_last = &permanent[N_PERMANENT_BYTES-1];
81 HChar* private_LibVEX_alloc_first = &temporary[0];
82 HChar* private_LibVEX_alloc_curr = &temporary[0];
83 HChar* private_LibVEX_alloc_last = &temporary[N_TEMPORARY_BYTES-1];
86 static VexAllocMode mode = VexAllocModeTEMP;
88 void vexAllocSanityCheck ( void )
90 vassert(temporary_first == &temporary[0]);
91 vassert(temporary_last == &temporary[N_TEMPORARY_BYTES-1]);
92 vassert(permanent_first == &permanent[0]);
93 vassert(permanent_last == &permanent[N_PERMANENT_BYTES-1]);
94 vassert(temporary_first <= temporary_curr);
95 vassert(temporary_curr <= temporary_last);
96 vassert(permanent_first <= permanent_curr);
97 vassert(permanent_curr <= permanent_last);
98 vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr);
99 vassert(private_LibVEX_alloc_curr <= private_LibVEX_alloc_last);
100 if (mode == VexAllocModeTEMP){
101 vassert(private_LibVEX_alloc_first == temporary_first);
102 vassert(private_LibVEX_alloc_last == temporary_last);
104 else
105 if (mode == VexAllocModePERM) {
106 vassert(private_LibVEX_alloc_first == permanent_first);
107 vassert(private_LibVEX_alloc_last == permanent_last);
109 else
110 vassert(0);
112 # define IS_WORD_ALIGNED(p) (0 == (((HWord)p) & (sizeof(HWord)-1)))
113 vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
114 vassert(IS_WORD_ALIGNED(temporary_first));
115 vassert(IS_WORD_ALIGNED(temporary_curr));
116 vassert(IS_WORD_ALIGNED(temporary_last+1));
117 vassert(IS_WORD_ALIGNED(permanent_first));
118 vassert(IS_WORD_ALIGNED(permanent_curr));
119 vassert(IS_WORD_ALIGNED(permanent_last+1));
120 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first));
121 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr));
122 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1));
123 # undef IS_WORD_ALIGNED
126 /* The current allocation mode. */
128 void vexSetAllocMode ( VexAllocMode m )
130 vexAllocSanityCheck();
132 /* Save away the current allocation point .. */
133 if (mode == VexAllocModeTEMP){
134 temporary_curr = private_LibVEX_alloc_curr;
136 else
137 if (mode == VexAllocModePERM) {
138 permanent_curr = private_LibVEX_alloc_curr;
140 else
141 vassert(0);
143 /* Did that screw anything up? */
144 vexAllocSanityCheck();
146 if (m == VexAllocModeTEMP){
147 private_LibVEX_alloc_first = temporary_first;
148 private_LibVEX_alloc_curr = temporary_curr;
149 private_LibVEX_alloc_last = temporary_last;
151 else
152 if (m == VexAllocModePERM) {
153 private_LibVEX_alloc_first = permanent_first;
154 private_LibVEX_alloc_curr = permanent_curr;
155 private_LibVEX_alloc_last = permanent_last;
157 else
158 vassert(0);
160 mode = m;
163 VexAllocMode vexGetAllocMode ( void )
165 return mode;
168 __attribute__((noreturn))
169 void private_LibVEX_alloc_OOM(void)
171 const HChar* pool = "???";
172 if (private_LibVEX_alloc_first == &temporary[0]) pool = "TEMP";
173 if (private_LibVEX_alloc_first == &permanent[0]) pool = "PERM";
174 vex_printf("VEX temporary storage exhausted.\n");
175 vex_printf("Pool = %s, start %p curr %p end %p (size %lld)\n",
176 pool,
177 private_LibVEX_alloc_first,
178 private_LibVEX_alloc_curr,
179 private_LibVEX_alloc_last,
180 (Long)(private_LibVEX_alloc_last + 1 - private_LibVEX_alloc_first));
181 vpanic("VEX temporary storage exhausted.\n"
182 "Increase N_{TEMPORARY,PERMANENT}_BYTES and recompile.");
185 void vexSetAllocModeTEMP_and_clear ( void )
187 /* vassert(vex_initdone); */ /* causes infinite assert loops */
188 temporary_bytes_allocd_TOT
189 += (ULong)(private_LibVEX_alloc_curr - private_LibVEX_alloc_first);
191 #if defined(ENABLE_INNER)
192 if (mempools_created) {
193 VALGRIND_MEMPOOL_TRIM(&temporary[0], &temporary[0], 0);
194 } else {
195 VALGRIND_CREATE_MEMPOOL(&temporary[0], VEX_REDZONE_SIZEB, 0);
196 VALGRIND_CREATE_MEMPOOL(&permanent[0], VEX_REDZONE_SIZEB, 0);
197 VALGRIND_MAKE_MEM_NOACCESS(&permanent[0], N_PERMANENT_BYTES);
198 mempools_created = True;
200 VALGRIND_MAKE_MEM_NOACCESS(&temporary[0], N_TEMPORARY_BYTES);
201 #endif
203 mode = VexAllocModeTEMP;
204 temporary_curr = &temporary[0];
205 private_LibVEX_alloc_curr = &temporary[0];
207 /* Set to (1) and change the fill byte to 0x00 or 0xFF to test for
208 any potential bugs due to using uninitialised memory in the main
209 VEX storage area. */
210 if (0) {
211 Int i;
212 for (i = 0; i < N_TEMPORARY_BYTES; i++)
213 temporary[i] = 0x00;
216 vexAllocSanityCheck();
220 /* Exported to library client. */
222 void LibVEX_ShowAllocStats ( void )
224 vex_printf("vex storage: T total %lld bytes allocated\n",
225 (Long)temporary_bytes_allocd_TOT );
226 vex_printf("vex storage: P total %lld bytes allocated\n",
227 (Long)(permanent_curr - permanent_first) );
230 void *LibVEX_Alloc ( SizeT nbytes )
232 return LibVEX_Alloc_inline(nbytes);
235 /*---------------------------------------------------------*/
236 /*--- Bombing out ---*/
237 /*---------------------------------------------------------*/
239 __attribute__ ((noreturn))
240 void vex_assert_fail ( const HChar* expr,
241 const HChar* file, Int line, const HChar* fn )
243 vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
244 file, line, fn, expr );
245 (*vex_failure_exit)();
248 /* To be used in assert-like (i.e. should never ever happen) situations */
249 __attribute__ ((noreturn))
250 void vpanic ( const HChar* str )
252 vex_printf("\nvex: the `impossible' happened:\n %s\n", str);
253 (*vex_failure_exit)();
257 /*---------------------------------------------------------*/
258 /*--- vex_printf ---*/
259 /*---------------------------------------------------------*/
261 /* This should be the only <...> include in the entire VEX library.
262 New code for vex_util.c should go above this point. */
263 #include <stdarg.h>
265 SizeT vex_strlen ( const HChar* str )
267 SizeT i = 0;
268 while (str[i] != 0) i++;
269 return i;
272 Bool vex_streq ( const HChar* s1, const HChar* s2 )
274 while (True) {
275 if (*s1 == 0 && *s2 == 0)
276 return True;
277 if (*s1 != *s2)
278 return False;
279 s1++;
280 s2++;
284 /* Vectorised memset, copied from Valgrind's m_libcbase.c. */
285 void vex_bzero ( void* sV, SizeT n )
287 # define IS_4_ALIGNED(aaa_p) (0 == (((HWord)(aaa_p)) & ((HWord)0x3)))
289 UChar* d = sV;
291 while ((!IS_4_ALIGNED(d)) && n >= 1) {
292 d[0] = 0;
293 d++;
294 n--;
296 if (n == 0)
297 return;
298 while (n >= 16) {
299 ((UInt*)d)[0] = 0;
300 ((UInt*)d)[1] = 0;
301 ((UInt*)d)[2] = 0;
302 ((UInt*)d)[3] = 0;
303 d += 16;
304 n -= 16;
306 while (n >= 4) {
307 ((UInt*)d)[0] = 0;
308 d += 4;
309 n -= 4;
311 while (n >= 1) {
312 d[0] = 0;
313 d++;
314 n--;
316 return;
317 # undef IS_4_ALIGNED
321 /* Convert N0 into ascii in BUF, which is assumed to be big enough (at
322 least 67 bytes long). Observe BASE, SYNED and HEXCAPS. */
323 static
324 void convert_int ( /*OUT*/HChar* buf, Long n0,
325 Int base, Bool syned, Bool hexcaps )
327 ULong u0;
328 HChar c;
329 Bool minus = False;
330 Int i, j, bufi = 0;
331 buf[bufi] = 0;
333 if (syned) {
334 if (n0 < 0) {
335 minus = True;
336 u0 = (ULong)(-n0);
337 } else {
338 u0 = (ULong)(n0);
340 } else {
341 u0 = (ULong)n0;
344 while (1) {
345 buf[bufi++] = toHChar('0' + toUInt(u0 % base));
346 u0 /= base;
347 if (u0 == 0) break;
349 if (minus)
350 buf[bufi++] = '-';
352 buf[bufi] = 0;
353 for (i = 0; i < bufi; i++)
354 if (buf[i] > '9')
355 buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
357 i = 0;
358 j = bufi-1;
359 while (i <= j) {
360 c = buf[i];
361 buf[i] = buf[j];
362 buf[j] = c;
363 i++;
364 j--;
369 /* A half-arsed and buggy, but good-enough, implementation of
370 printf. */
371 static
372 UInt vprintf_wrk ( void(*sink)(HChar),
373 const HChar* format,
374 va_list ap )
376 # define PUT(_ch) \
377 do { sink(_ch); nout++; } \
378 while (0)
380 # define PAD(_n) \
381 do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
382 while (0)
384 # define PUTSTR(_str) \
385 do { const HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
386 while (0)
388 const HChar* saved_format;
389 Bool longlong, ljustify, is_sizet;
390 HChar padchar;
391 Int fwidth, nout, len1, len3;
392 SizeT len2;
393 HChar intbuf[100]; /* big enough for a 64-bit # in base 2 */
395 nout = 0;
396 while (1) {
398 if (!format)
399 break;
400 if (*format == 0)
401 break;
403 if (*format != '%') {
404 PUT(*format);
405 format++;
406 continue;
409 saved_format = format;
410 longlong = is_sizet = False;
411 ljustify = False;
412 padchar = ' ';
413 fwidth = 0;
414 format++;
416 if (*format == '-') {
417 format++;
418 ljustify = True;
420 if (*format == '0') {
421 format++;
422 padchar = '0';
424 if (*format == '*') {
425 fwidth = va_arg(ap, Int);
426 vassert(fwidth >= 0);
427 format++;
428 } else {
429 while (*format >= '0' && *format <= '9') {
430 fwidth = fwidth * 10 + (*format - '0');
431 format++;
434 if (*format == 'l') {
435 format++;
436 if (*format == 'l') {
437 format++;
438 longlong = True;
440 } else if (*format == 'z') {
441 format++;
442 is_sizet = True;
445 switch (*format) {
446 case 's': {
447 const HChar* str = va_arg(ap, HChar*);
448 if (str == NULL)
449 str = "(null)";
450 len1 = len3 = 0;
451 len2 = vex_strlen(str);
452 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
453 len3 = ljustify ? fwidth-len2 : 0; }
454 PAD(len1); PUTSTR(str); PAD(len3);
455 break;
457 case 'c': {
458 HChar c = (HChar)va_arg(ap, int);
459 HChar str[2];
460 str[0] = c;
461 str[1] = 0;
462 len1 = len3 = 0;
463 len2 = vex_strlen(str);
464 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
465 len3 = ljustify ? fwidth-len2 : 0; }
466 PAD(len1); PUTSTR(str); PAD(len3);
467 break;
469 case 'd': {
470 Long l;
471 vassert(is_sizet == False); // %zd is obscure; we don't allow it
472 if (longlong) {
473 l = va_arg(ap, Long);
474 } else {
475 l = (Long)va_arg(ap, Int);
477 convert_int(intbuf, l, 10/*base*/, True/*signed*/,
478 False/*irrelevant*/);
479 len1 = len3 = 0;
480 len2 = vex_strlen(intbuf);
481 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
482 len3 = ljustify ? fwidth-len2 : 0; }
483 PAD(len1); PUTSTR(intbuf); PAD(len3);
484 break;
486 case 'u':
487 case 'x':
488 case 'X': {
489 Int base = *format == 'u' ? 10 : 16;
490 Bool hexcaps = True; /* *format == 'X'; */
491 ULong l;
492 if (is_sizet) {
493 l = (ULong)va_arg(ap, SizeT);
494 } else if (longlong) {
495 l = va_arg(ap, ULong);
496 } else {
497 l = (ULong)va_arg(ap, UInt);
499 convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
500 len1 = len3 = 0;
501 len2 = vex_strlen(intbuf);
502 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
503 len3 = ljustify ? fwidth-len2 : 0; }
504 PAD(len1); PUTSTR(intbuf); PAD(len3);
505 break;
507 case 'p':
508 case 'P': {
509 Bool hexcaps = toBool(*format == 'P');
510 ULong l = (Addr)va_arg(ap, void*);
511 convert_int(intbuf, l, 16/*base*/, False/*unsigned*/, hexcaps);
512 len1 = len3 = 0;
513 len2 = vex_strlen(intbuf)+2;
514 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
515 len3 = ljustify ? fwidth-len2 : 0; }
516 PAD(len1); PUT('0'); PUT('x'); PUTSTR(intbuf); PAD(len3);
517 break;
519 case '%': {
520 PUT('%');
521 break;
523 default:
524 /* no idea what it is. Print the format literally and
525 move on. */
526 while (saved_format <= format) {
527 PUT(*saved_format);
528 saved_format++;
530 break;
533 format++;
537 return nout;
539 # undef PUT
540 # undef PAD
541 # undef PUTSTR
545 /* A general replacement for printf(). Note that only low-level
546 debugging info should be sent via here. The official route is to
547 to use vg_message(). This interface is deprecated.
549 static HChar myprintf_buf[1000];
550 static Int n_myprintf_buf;
552 static void add_to_myprintf_buf ( HChar c )
554 Bool emit = toBool(c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/);
555 myprintf_buf[n_myprintf_buf++] = c;
556 myprintf_buf[n_myprintf_buf] = 0;
557 if (emit) {
558 (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
559 n_myprintf_buf = 0;
560 myprintf_buf[n_myprintf_buf] = 0;
564 static UInt vex_vprintf ( const HChar* format, va_list vargs )
566 UInt ret;
568 n_myprintf_buf = 0;
569 myprintf_buf[n_myprintf_buf] = 0;
570 ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
572 if (n_myprintf_buf > 0) {
573 (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
576 return ret;
579 UInt vex_printf ( const HChar* format, ... )
581 UInt ret;
582 va_list vargs;
583 va_start(vargs, format);
584 ret = vex_vprintf(format, vargs);
585 va_end(vargs);
587 return ret;
590 /* Use this function to communicate to users that a (legitimate) situation
591 occured that we cannot handle (yet). */
592 __attribute__ ((noreturn))
593 void vfatal ( const HChar* format, ... )
595 va_list vargs;
596 va_start(vargs, format);
597 vex_vprintf( format, vargs );
598 va_end(vargs);
599 vex_printf("Cannot continue. Good-bye\n\n");
601 (*vex_failure_exit)();
604 /* A general replacement for sprintf(). */
606 static HChar *vg_sprintf_ptr;
608 static void add_to_vg_sprintf_buf ( HChar c )
610 *vg_sprintf_ptr++ = c;
613 UInt vex_sprintf ( HChar* buf, const HChar *format, ... )
615 Int ret;
616 va_list vargs;
618 vg_sprintf_ptr = buf;
620 va_start(vargs,format);
622 ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
623 add_to_vg_sprintf_buf(0);
625 va_end(vargs);
627 vassert(vex_strlen(buf) == ret);
628 return ret;
632 /*---------------------------------------------------------*/
633 /*--- Misaligned memory access support ---*/
634 /*---------------------------------------------------------*/
636 UInt read_misaligned_UInt_LE ( void* addr )
638 UChar* p = (UChar*)addr;
639 UInt w = 0;
640 w = (w << 8) | p[3];
641 w = (w << 8) | p[2];
642 w = (w << 8) | p[1];
643 w = (w << 8) | p[0];
644 return w;
647 ULong read_misaligned_ULong_LE ( void* addr )
649 UChar* p = (UChar*)addr;
650 ULong w = 0;
651 w = (w << 8) | p[7];
652 w = (w << 8) | p[6];
653 w = (w << 8) | p[5];
654 w = (w << 8) | p[4];
655 w = (w << 8) | p[3];
656 w = (w << 8) | p[2];
657 w = (w << 8) | p[1];
658 w = (w << 8) | p[0];
659 return w;
662 void write_misaligned_UInt_LE ( void* addr, UInt w )
664 UChar* p = (UChar*)addr;
665 p[0] = (w & 0xFF); w >>= 8;
666 p[1] = (w & 0xFF); w >>= 8;
667 p[2] = (w & 0xFF); w >>= 8;
668 p[3] = (w & 0xFF); w >>= 8;
671 void write_misaligned_ULong_LE ( void* addr, ULong w )
673 UChar* p = (UChar*)addr;
674 p[0] = (w & 0xFF); w >>= 8;
675 p[1] = (w & 0xFF); w >>= 8;
676 p[2] = (w & 0xFF); w >>= 8;
677 p[3] = (w & 0xFF); w >>= 8;
678 p[4] = (w & 0xFF); w >>= 8;
679 p[5] = (w & 0xFF); w >>= 8;
680 p[6] = (w & 0xFF); w >>= 8;
681 p[7] = (w & 0xFF); w >>= 8;
685 /*---------------------------------------------------------------*/
686 /*--- end main_util.c ---*/
687 /*---------------------------------------------------------------*/