2 /*---------------------------------------------------------------*/
3 /*--- begin main_util.c ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2013 OpenWorks LLP
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
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"
39 #include "main_globals.h"
40 #include "main_util.h"
43 /*---------------------------------------------------------*/
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.
54 #define N_TEMPORARY_BYTES 5000000
56 static HChar temporary[N_TEMPORARY_BYTES] __attribute__((aligned(8)));
57 static HChar* temporary_first = &temporary[0];
58 static HChar* temporary_curr = &temporary[0];
59 static HChar* temporary_last = &temporary[N_TEMPORARY_BYTES-1];
61 static ULong temporary_bytes_allocd_TOT = 0;
63 #define N_PERMANENT_BYTES 10000
65 static HChar permanent[N_PERMANENT_BYTES] __attribute__((aligned(8)));
66 static HChar* permanent_first = &permanent[0];
67 static HChar* permanent_curr = &permanent[0];
68 static HChar* permanent_last = &permanent[N_PERMANENT_BYTES-1];
70 static VexAllocMode mode = VexAllocModeTEMP;
72 void vexAllocSanityCheck ( void )
74 vassert(temporary_first == &temporary[0]);
75 vassert(temporary_last == &temporary[N_TEMPORARY_BYTES-1]);
76 vassert(permanent_first == &permanent[0]);
77 vassert(permanent_last == &permanent[N_PERMANENT_BYTES-1]);
78 vassert(temporary_first <= temporary_curr);
79 vassert(temporary_curr <= temporary_last);
80 vassert(permanent_first <= permanent_curr);
81 vassert(permanent_curr <= permanent_last);
82 vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr);
83 vassert(private_LibVEX_alloc_curr <= private_LibVEX_alloc_last);
84 if (mode == VexAllocModeTEMP){
85 vassert(private_LibVEX_alloc_first == temporary_first);
86 vassert(private_LibVEX_alloc_last == temporary_last);
89 if (mode == VexAllocModePERM) {
90 vassert(private_LibVEX_alloc_first == permanent_first);
91 vassert(private_LibVEX_alloc_last == permanent_last);
96 # define IS_WORD_ALIGNED(p) (0 == (((HWord)p) & (sizeof(HWord)-1)))
97 vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
98 vassert(IS_WORD_ALIGNED(temporary_first));
99 vassert(IS_WORD_ALIGNED(temporary_curr));
100 vassert(IS_WORD_ALIGNED(temporary_last+1));
101 vassert(IS_WORD_ALIGNED(permanent_first));
102 vassert(IS_WORD_ALIGNED(permanent_curr));
103 vassert(IS_WORD_ALIGNED(permanent_last+1));
104 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first));
105 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr));
106 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1));
107 # undef IS_WORD_ALIGNED
110 /* The current allocation mode. */
112 void vexSetAllocMode ( VexAllocMode m )
114 vexAllocSanityCheck();
116 /* Save away the current allocation point .. */
117 if (mode == VexAllocModeTEMP){
118 temporary_curr = private_LibVEX_alloc_curr;
121 if (mode == VexAllocModePERM) {
122 permanent_curr = private_LibVEX_alloc_curr;
127 /* Did that screw anything up? */
128 vexAllocSanityCheck();
130 if (m == VexAllocModeTEMP){
131 private_LibVEX_alloc_first = temporary_first;
132 private_LibVEX_alloc_curr = temporary_curr;
133 private_LibVEX_alloc_last = temporary_last;
136 if (m == VexAllocModePERM) {
137 private_LibVEX_alloc_first = permanent_first;
138 private_LibVEX_alloc_curr = permanent_curr;
139 private_LibVEX_alloc_last = permanent_last;
147 VexAllocMode vexGetAllocMode ( void )
152 /* Visible to library client, unfortunately. */
154 HChar* private_LibVEX_alloc_first = &temporary[0];
155 HChar* private_LibVEX_alloc_curr = &temporary[0];
156 HChar* private_LibVEX_alloc_last = &temporary[N_TEMPORARY_BYTES-1];
158 __attribute__((noreturn))
159 void private_LibVEX_alloc_OOM(void)
161 const HChar* pool = "???";
162 if (private_LibVEX_alloc_first == &temporary[0]) pool = "TEMP";
163 if (private_LibVEX_alloc_first == &permanent[0]) pool = "PERM";
164 vex_printf("VEX temporary storage exhausted.\n");
165 vex_printf("Pool = %s, start %p curr %p end %p (size %lld)\n",
167 private_LibVEX_alloc_first,
168 private_LibVEX_alloc_curr,
169 private_LibVEX_alloc_last,
170 (Long)(private_LibVEX_alloc_last + 1 - private_LibVEX_alloc_first));
171 vpanic("VEX temporary storage exhausted.\n"
172 "Increase N_{TEMPORARY,PERMANENT}_BYTES and recompile.");
175 void vexSetAllocModeTEMP_and_clear ( void )
177 /* vassert(vex_initdone); */ /* causes infinite assert loops */
178 temporary_bytes_allocd_TOT
179 += (ULong)(private_LibVEX_alloc_curr - private_LibVEX_alloc_first);
181 mode = VexAllocModeTEMP;
182 temporary_curr = &temporary[0];
183 private_LibVEX_alloc_curr = &temporary[0];
185 /* Set to (1) and change the fill byte to 0x00 or 0xFF to test for
186 any potential bugs due to using uninitialised memory in the main
190 for (i = 0; i < N_TEMPORARY_BYTES; i++)
194 vexAllocSanityCheck();
198 /* Exported to library client. */
200 void LibVEX_ShowAllocStats ( void )
202 vex_printf("vex storage: T total %lld bytes allocated\n",
203 (Long)temporary_bytes_allocd_TOT );
204 vex_printf("vex storage: P total %lld bytes allocated\n",
205 (Long)(permanent_curr - permanent_first) );
209 /*---------------------------------------------------------*/
210 /*--- Bombing out ---*/
211 /*---------------------------------------------------------*/
213 __attribute__ ((noreturn))
214 void vex_assert_fail ( const HChar* expr,
215 const HChar* file, Int line, const HChar* fn )
217 vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
218 file, line, fn, expr );
219 (*vex_failure_exit)();
222 __attribute__ ((noreturn))
223 void vpanic ( const HChar* str )
225 vex_printf("\nvex: the `impossible' happened:\n %s\n", str);
226 (*vex_failure_exit)();
230 /*---------------------------------------------------------*/
231 /*--- vex_printf ---*/
232 /*---------------------------------------------------------*/
234 /* This should be the only <...> include in the entire VEX library.
235 New code for vex_util.c should go above this point. */
238 Int vex_strlen ( const HChar* str )
241 while (str[i] != 0) i++;
245 Bool vex_streq ( const HChar* s1, const HChar* s2 )
248 if (*s1 == 0 && *s2 == 0)
257 void vex_bzero ( void* sV, UInt n )
260 UChar* s = (UChar*)sV;
261 /* No laughing, please. Just don't call this too often. Thank you
262 for your attention. */
263 for (i = 0; i < n; i++) s[i] = 0;
267 /* Convert N0 into ascii in BUF, which is assumed to be big enough (at
268 least 67 bytes long). Observe BASE, SYNED and HEXCAPS. */
270 void convert_int ( /*OUT*/HChar* buf, Long n0,
271 Int base, Bool syned, Bool hexcaps )
291 buf[bufi++] = toHChar('0' + toUInt(u0 % base));
299 for (i = 0; i < bufi; i++)
301 buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
315 /* A half-arsed and buggy, but good-enough, implementation of
318 UInt vprintf_wrk ( void(*sink)(HChar),
323 do { sink(_ch); nout++; } \
327 do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
330 # define PUTSTR(_str) \
331 do { const HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
334 const HChar* saved_format;
335 Bool longlong, ljustify;
337 Int fwidth, nout, len1, len2, len3;
338 HChar intbuf[100]; /* big enough for a 64-bit # in base 2 */
348 if (*format != '%') {
354 saved_format = format;
361 if (*format == '-') {
365 if (*format == '0') {
369 if (*format == '*') {
370 fwidth = va_arg(ap, Int);
373 while (*format >= '0' && *format <= '9') {
374 fwidth = fwidth * 10 + (*format - '0');
378 if (*format == 'l') {
380 if (*format == 'l') {
388 const HChar* str = va_arg(ap, HChar*);
392 len2 = vex_strlen(str);
393 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
394 len3 = ljustify ? fwidth-len2 : 0; }
395 PAD(len1); PUTSTR(str); PAD(len3);
399 HChar c = (HChar)va_arg(ap, int);
404 len2 = vex_strlen(str);
405 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
406 len3 = ljustify ? fwidth-len2 : 0; }
407 PAD(len1); PUTSTR(str); PAD(len3);
413 l = va_arg(ap, Long);
415 l = (Long)va_arg(ap, Int);
417 convert_int(intbuf, l, 10/*base*/, True/*signed*/,
418 False/*irrelevant*/);
420 len2 = vex_strlen(intbuf);
421 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
422 len3 = ljustify ? fwidth-len2 : 0; }
423 PAD(len1); PUTSTR(intbuf); PAD(len3);
429 Int base = *format == 'u' ? 10 : 16;
430 Bool hexcaps = True; /* *format == 'X'; */
433 l = va_arg(ap, ULong);
435 l = (ULong)va_arg(ap, UInt);
437 convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
439 len2 = vex_strlen(intbuf);
440 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
441 len3 = ljustify ? fwidth-len2 : 0; }
442 PAD(len1); PUTSTR(intbuf); PAD(len3);
447 Bool hexcaps = toBool(*format == 'P');
448 ULong l = Ptr_to_ULong( va_arg(ap, void*) );
449 convert_int(intbuf, l, 16/*base*/, False/*unsigned*/, hexcaps);
451 len2 = vex_strlen(intbuf)+2;
452 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
453 len3 = ljustify ? fwidth-len2 : 0; }
454 PAD(len1); PUT('0'); PUT('x'); PUTSTR(intbuf); PAD(len3);
462 /* no idea what it is. Print the format literally and
464 while (saved_format <= format) {
483 /* A general replacement for printf(). Note that only low-level
484 debugging info should be sent via here. The official route is to
485 to use vg_message(). This interface is deprecated.
487 static HChar myprintf_buf[1000];
488 static Int n_myprintf_buf;
490 static void add_to_myprintf_buf ( HChar c )
492 Bool emit = toBool(c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/);
493 myprintf_buf[n_myprintf_buf++] = c;
494 myprintf_buf[n_myprintf_buf] = 0;
496 (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
498 myprintf_buf[n_myprintf_buf] = 0;
502 UInt vex_printf ( const HChar* format, ... )
506 va_start(vargs,format);
509 myprintf_buf[n_myprintf_buf] = 0;
510 ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
512 if (n_myprintf_buf > 0) {
513 (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
522 /* A general replacement for sprintf(). */
524 static HChar *vg_sprintf_ptr;
526 static void add_to_vg_sprintf_buf ( HChar c )
528 *vg_sprintf_ptr++ = c;
531 UInt vex_sprintf ( HChar* buf, const HChar *format, ... )
536 vg_sprintf_ptr = buf;
538 va_start(vargs,format);
540 ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
541 add_to_vg_sprintf_buf(0);
545 vassert(vex_strlen(buf) == ret);
550 /*---------------------------------------------------------------*/
551 /*--- end main_util.c ---*/
552 /*---------------------------------------------------------------*/