• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*---------------------------------------------------------------*/
3 /*--- begin                                       main_util.c ---*/
4 /*---------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2004-2013 OpenWorks LLP
11       info@open-works.net
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., 51 Franklin Street, Fifth Floor, Boston, MA
26    02110-1301, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 
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.
34 */
35 
36 #include "libvex_basictypes.h"
37 #include "libvex.h"
38 
39 #include "main_globals.h"
40 #include "main_util.h"
41 
42 
43 /*---------------------------------------------------------*/
44 /*--- Storage                                           ---*/
45 /*---------------------------------------------------------*/
46 
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.
53 */
54 #define N_TEMPORARY_BYTES 5000000
55 
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];
60 
61 static ULong  temporary_bytes_allocd_TOT = 0;
62 
63 #define N_PERMANENT_BYTES 10000
64 
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];
69 
70 static VexAllocMode mode = VexAllocModeTEMP;
71 
vexAllocSanityCheck(void)72 void vexAllocSanityCheck ( void )
73 {
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);
87    }
88    else
89    if (mode == VexAllocModePERM) {
90       vassert(private_LibVEX_alloc_first == permanent_first);
91       vassert(private_LibVEX_alloc_last  == permanent_last);
92    }
93    else
94       vassert(0);
95 
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
108 }
109 
110 /* The current allocation mode. */
111 
vexSetAllocMode(VexAllocMode m)112 void vexSetAllocMode ( VexAllocMode m )
113 {
114    vexAllocSanityCheck();
115 
116    /* Save away the current allocation point .. */
117    if (mode == VexAllocModeTEMP){
118       temporary_curr = private_LibVEX_alloc_curr;
119    }
120    else
121    if (mode == VexAllocModePERM) {
122       permanent_curr = private_LibVEX_alloc_curr;
123    }
124    else
125       vassert(0);
126 
127    /* Did that screw anything up? */
128    vexAllocSanityCheck();
129 
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;
134    }
135    else
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;
140    }
141    else
142       vassert(0);
143 
144    mode = m;
145 }
146 
vexGetAllocMode(void)147 VexAllocMode vexGetAllocMode ( void )
148 {
149    return mode;
150 }
151 
152 /* Visible to library client, unfortunately. */
153 
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];
157 
158 __attribute__((noreturn))
private_LibVEX_alloc_OOM(void)159 void private_LibVEX_alloc_OOM(void)
160 {
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",
166               pool,
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.");
173 }
174 
vexSetAllocModeTEMP_and_clear(void)175 void vexSetAllocModeTEMP_and_clear ( void )
176 {
177    /* vassert(vex_initdone); */ /* causes infinite assert loops */
178    temporary_bytes_allocd_TOT
179       += (ULong)(private_LibVEX_alloc_curr - private_LibVEX_alloc_first);
180 
181    mode = VexAllocModeTEMP;
182    temporary_curr            = &temporary[0];
183    private_LibVEX_alloc_curr = &temporary[0];
184 
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
187       VEX storage area. */
188    if (0) {
189       Int i;
190       for (i = 0; i < N_TEMPORARY_BYTES; i++)
191          temporary[i] = 0x00;
192    }
193 
194    vexAllocSanityCheck();
195 }
196 
197 
198 /* Exported to library client. */
199 
LibVEX_ShowAllocStats(void)200 void LibVEX_ShowAllocStats ( void )
201 {
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) );
206 }
207 
208 
209 /*---------------------------------------------------------*/
210 /*--- Bombing out                                       ---*/
211 /*---------------------------------------------------------*/
212 
213 __attribute__ ((noreturn))
vex_assert_fail(const HChar * expr,const HChar * file,Int line,const HChar * fn)214 void vex_assert_fail ( const HChar* expr,
215                        const HChar* file, Int line, const HChar* fn )
216 {
217    vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
218                file, line, fn, expr );
219    (*vex_failure_exit)();
220 }
221 
222 __attribute__ ((noreturn))
vpanic(const HChar * str)223 void vpanic ( const HChar* str )
224 {
225    vex_printf("\nvex: the `impossible' happened:\n   %s\n", str);
226    (*vex_failure_exit)();
227 }
228 
229 
230 /*---------------------------------------------------------*/
231 /*--- vex_printf                                        ---*/
232 /*---------------------------------------------------------*/
233 
234 /* This should be the only <...> include in the entire VEX library.
235    New code for vex_util.c should go above this point. */
236 #include <stdarg.h>
237 
vex_strlen(const HChar * str)238 Int vex_strlen ( const HChar* str )
239 {
240    Int i = 0;
241    while (str[i] != 0) i++;
242    return i;
243 }
244 
vex_streq(const HChar * s1,const HChar * s2)245 Bool vex_streq ( const HChar* s1, const HChar* s2 )
246 {
247    while (True) {
248       if (*s1 == 0 && *s2 == 0)
249          return True;
250       if (*s1 != *s2)
251          return False;
252       s1++;
253       s2++;
254    }
255 }
256 
vex_bzero(void * sV,UInt n)257 void vex_bzero ( void* sV, UInt n )
258 {
259    UInt i;
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;
264 }
265 
266 
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. */
269 static
convert_int(HChar * buf,Long n0,Int base,Bool syned,Bool hexcaps)270 void convert_int ( /*OUT*/HChar* buf, Long n0,
271                    Int base, Bool syned, Bool hexcaps )
272 {
273    ULong u0;
274    HChar c;
275    Bool minus = False;
276    Int i, j, bufi = 0;
277    buf[bufi] = 0;
278 
279    if (syned) {
280       if (n0 < 0) {
281          minus = True;
282          u0 = (ULong)(-n0);
283       } else {
284          u0 = (ULong)(n0);
285       }
286    } else {
287       u0 = (ULong)n0;
288    }
289 
290    while (1) {
291      buf[bufi++] = toHChar('0' + toUInt(u0 % base));
292      u0 /= base;
293      if (u0 == 0) break;
294    }
295    if (minus)
296       buf[bufi++] = '-';
297 
298    buf[bufi] = 0;
299    for (i = 0; i < bufi; i++)
300       if (buf[i] > '9')
301          buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
302 
303    i = 0;
304    j = bufi-1;
305    while (i <= j) {
306       c = buf[i];
307       buf[i] = buf[j];
308       buf[j] = c;
309       i++;
310       j--;
311    }
312 }
313 
314 
315 /* A half-arsed and buggy, but good-enough, implementation of
316    printf. */
317 static
vprintf_wrk(void (* sink)(HChar),const HChar * format,va_list ap)318 UInt vprintf_wrk ( void(*sink)(HChar),
319                    const HChar* format,
320                    va_list ap )
321 {
322 #  define PUT(_ch)  \
323       do { sink(_ch); nout++; } \
324       while (0)
325 
326 #  define PAD(_n) \
327       do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
328       while (0)
329 
330 #  define PUTSTR(_str) \
331       do { const HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
332       while (0)
333 
334    const HChar* saved_format;
335    Bool   longlong, ljustify;
336    HChar  padchar;
337    Int    fwidth, nout, len1, len2, len3;
338    HChar  intbuf[100];  /* big enough for a 64-bit # in base 2 */
339 
340    nout = 0;
341    while (1) {
342 
343       if (!format)
344          break;
345       if (*format == 0)
346          break;
347 
348       if (*format != '%') {
349          PUT(*format);
350          format++;
351          continue;
352       }
353 
354       saved_format = format;
355       longlong = False;
356       ljustify = False;
357       padchar = ' ';
358       fwidth = 0;
359       format++;
360 
361       if (*format == '-') {
362          format++;
363          ljustify = True;
364       }
365       if (*format == '0') {
366          format++;
367          padchar = '0';
368       }
369       if (*format == '*') {
370          fwidth = va_arg(ap, Int);
371          format++;
372       } else {
373          while (*format >= '0' && *format <= '9') {
374             fwidth = fwidth * 10 + (*format - '0');
375             format++;
376          }
377       }
378       if (*format == 'l') {
379          format++;
380          if (*format == 'l') {
381             format++;
382            longlong = True;
383          }
384       }
385 
386       switch (*format) {
387          case 's': {
388             const HChar* str = va_arg(ap, HChar*);
389             if (str == NULL)
390                str = "(null)";
391             len1 = len3 = 0;
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);
396             break;
397          }
398          case 'c': {
399             HChar c = (HChar)va_arg(ap, int);
400             HChar str[2];
401             str[0] = c;
402             str[1] = 0;
403             len1 = len3 = 0;
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);
408             break;
409          }
410          case 'd': {
411             Long l;
412             if (longlong) {
413                l = va_arg(ap, Long);
414             } else {
415                l = (Long)va_arg(ap, Int);
416             }
417             convert_int(intbuf, l, 10/*base*/, True/*signed*/,
418                                 False/*irrelevant*/);
419             len1 = len3 = 0;
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);
424             break;
425          }
426          case 'u':
427          case 'x':
428          case 'X': {
429             Int   base = *format == 'u' ? 10 : 16;
430             Bool  hexcaps = True; /* *format == 'X'; */
431             ULong l;
432             if (longlong) {
433                l = va_arg(ap, ULong);
434             } else {
435                l = (ULong)va_arg(ap, UInt);
436             }
437             convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
438             len1 = len3 = 0;
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);
443             break;
444          }
445          case 'p':
446          case 'P': {
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);
450             len1 = len3 = 0;
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);
455             break;
456          }
457          case '%': {
458             PUT('%');
459             break;
460          }
461          default:
462             /* no idea what it is.  Print the format literally and
463                move on. */
464             while (saved_format <= format) {
465                PUT(*saved_format);
466                saved_format++;
467             }
468             break;
469       }
470 
471       format++;
472 
473    }
474 
475    return nout;
476 
477 #  undef PUT
478 #  undef PAD
479 #  undef PUTSTR
480 }
481 
482 
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.
486 */
487 static HChar myprintf_buf[1000];
488 static Int   n_myprintf_buf;
489 
add_to_myprintf_buf(HChar c)490 static void add_to_myprintf_buf ( HChar c )
491 {
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;
495    if (emit) {
496       (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
497       n_myprintf_buf = 0;
498       myprintf_buf[n_myprintf_buf] = 0;
499    }
500 }
501 
vex_printf(const HChar * format,...)502 UInt vex_printf ( const HChar* format, ... )
503 {
504    UInt ret;
505    va_list vargs;
506    va_start(vargs,format);
507 
508    n_myprintf_buf = 0;
509    myprintf_buf[n_myprintf_buf] = 0;
510    ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
511 
512    if (n_myprintf_buf > 0) {
513       (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
514    }
515 
516    va_end(vargs);
517 
518    return ret;
519 }
520 
521 
522 /* A general replacement for sprintf(). */
523 
524 static HChar *vg_sprintf_ptr;
525 
add_to_vg_sprintf_buf(HChar c)526 static void add_to_vg_sprintf_buf ( HChar c )
527 {
528    *vg_sprintf_ptr++ = c;
529 }
530 
vex_sprintf(HChar * buf,const HChar * format,...)531 UInt vex_sprintf ( HChar* buf, const HChar *format, ... )
532 {
533    Int ret;
534    va_list vargs;
535 
536    vg_sprintf_ptr = buf;
537 
538    va_start(vargs,format);
539 
540    ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
541    add_to_vg_sprintf_buf(0);
542 
543    va_end(vargs);
544 
545    vassert(vex_strlen(buf) == ret);
546    return ret;
547 }
548 
549 
550 /*---------------------------------------------------------------*/
551 /*--- end                                         main_util.c ---*/
552 /*---------------------------------------------------------------*/
553