]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/main_util.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / main_util.c
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-2010 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
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
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
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))
159 void private_LibVEX_alloc_OOM(void)
160 {
161    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
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
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))
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))
223 void vpanic ( 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
238 Int vex_strlen ( const HChar* str )
239 {
240    Int i = 0;
241    while (str[i] != 0) i++;
242    return i;
243 }
244
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
257
258 /* Convert N0 into ascii in BUF, which is assumed to be big enough (at
259    least 67 bytes long).  Observe BASE, SYNED and HEXCAPS. */
260 static
261 void convert_int ( /*OUT*/HChar* buf, Long n0, 
262                    Int base, Bool syned, Bool hexcaps )
263 {
264    ULong u0;
265    HChar c;
266    Bool minus = False;
267    Int i, j, bufi = 0;
268    buf[bufi] = 0;
269
270    if (syned) {
271       if (n0 < 0) {
272          minus = True;
273          u0 = (ULong)(-n0);
274       } else {
275          u0 = (ULong)(n0);
276       }
277    } else {
278       u0 = (ULong)n0;
279    }
280
281    while (1) {
282      buf[bufi++] = toHChar('0' + toUInt(u0 % base));
283      u0 /= base;
284      if (u0 == 0) break;
285    }
286    if (minus)
287       buf[bufi++] = '-';
288
289    buf[bufi] = 0;
290    for (i = 0; i < bufi; i++)
291       if (buf[i] > '9') 
292          buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
293
294    i = 0;
295    j = bufi-1;
296    while (i <= j) {
297       c = buf[i];
298       buf[i] = buf[j];
299       buf[j] = c;
300       i++;
301       j--;
302    }
303 }
304
305
306 /* A half-arsed and buggy, but good-enough, implementation of
307    printf. */
308 static
309 UInt vprintf_wrk ( void(*sink)(HChar),
310                    HChar* format,
311                    va_list ap )
312 {
313 #  define PUT(_ch)  \
314       do { sink(_ch); nout++; } \
315       while (0)
316
317 #  define PAD(_n) \
318       do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
319       while (0)
320
321 #  define PUTSTR(_str) \
322       do { HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
323       while (0)
324
325    HChar* saved_format;
326    Bool   longlong, ljustify;
327    HChar  padchar;
328    Int    fwidth, nout, len1, len2, len3;
329    HChar  intbuf[100];  /* big enough for a 64-bit # in base 2 */
330
331    nout = 0;
332    while (1) {
333
334       if (!format)
335          break;
336       if (*format == 0) 
337          break;
338
339       if (*format != '%') {
340          PUT(*format); 
341          format++;
342          continue;
343       }
344
345       saved_format = format;
346       longlong = False;
347       ljustify = False;
348       padchar = ' ';
349       fwidth = 0;
350       format++;
351
352       if (*format == '-') {
353          format++;
354          ljustify = True;
355       }
356       if (*format == '0') {
357          format++;
358          padchar = '0';
359       }
360       while (*format >= '0' && *format <= '9') {
361          fwidth = fwidth * 10 + (*format - '0');
362          format++;
363       }
364       if (*format == 'l') {
365          format++;
366          if (*format == 'l') {
367             format++;
368            longlong = True;
369          }
370       }
371
372       switch (*format) {
373          case 's': {
374             HChar* str = va_arg(ap, HChar*);
375             if (str == NULL)
376                str = "(null)";
377             len1 = len3 = 0;
378             len2 = vex_strlen(str);
379             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
380                                  len3 = ljustify ? fwidth-len2 : 0; }
381             PAD(len1); PUTSTR(str); PAD(len3);
382             break;
383          }
384          case 'c': {
385             HChar c = (HChar)va_arg(ap, int);
386             HChar str[2];
387             str[0] = c;
388             str[1] = 0;
389             len1 = len3 = 0;
390             len2 = vex_strlen(str);
391             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
392                                  len3 = ljustify ? fwidth-len2 : 0; }
393             PAD(len1); PUTSTR(str); PAD(len3);
394             break;
395          }
396          case 'd': {
397             Long l;
398             if (longlong) {
399                l = va_arg(ap, Long);
400             } else {
401                l = (Long)va_arg(ap, Int);
402             }
403             convert_int(intbuf, l, 10/*base*/, True/*signed*/,
404                                 False/*irrelevant*/);
405             len1 = len3 = 0;
406             len2 = vex_strlen(intbuf);
407             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
408                                  len3 = ljustify ? fwidth-len2 : 0; }
409             PAD(len1); PUTSTR(intbuf); PAD(len3);
410             break;
411          }
412          case 'u': 
413          case 'x': 
414          case 'X': {
415             Int   base = *format == 'u' ? 10 : 16;
416             Bool  hexcaps = True; /* *format == 'X'; */
417             ULong l;
418             if (longlong) {
419                l = va_arg(ap, ULong);
420             } else {
421                l = (ULong)va_arg(ap, UInt);
422             }
423             convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
424             len1 = len3 = 0;
425             len2 = vex_strlen(intbuf);
426             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
427                                  len3 = ljustify ? fwidth-len2 : 0; }
428             PAD(len1); PUTSTR(intbuf); PAD(len3);
429             break;
430          }
431          case 'p': 
432          case 'P': {
433             Bool hexcaps = toBool(*format == 'P');
434             ULong l = Ptr_to_ULong( va_arg(ap, void*) );
435             convert_int(intbuf, l, 16/*base*/, False/*unsigned*/, hexcaps);
436             len1 = len3 = 0;
437             len2 = vex_strlen(intbuf)+2;
438             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
439                                  len3 = ljustify ? fwidth-len2 : 0; }
440             PAD(len1); PUT('0'); PUT('x'); PUTSTR(intbuf); PAD(len3);
441             break;
442          }
443          case '%': {
444             PUT('%');
445             break;
446          }
447          default:
448             /* no idea what it is.  Print the format literally and
449                move on. */
450             while (saved_format <= format) {
451                PUT(*saved_format);
452                saved_format++;
453             }
454             break;
455       }
456
457       format++;
458
459    }
460
461    return nout;
462
463 #  undef PUT
464 #  undef PAD
465 #  undef PUTSTR
466 }
467
468
469 /* A general replacement for printf().  Note that only low-level 
470    debugging info should be sent via here.  The official route is to
471    to use vg_message().  This interface is deprecated.
472 */
473 static HChar myprintf_buf[1000];
474 static Int   n_myprintf_buf;
475
476 static void add_to_myprintf_buf ( HChar c )
477 {
478    Bool emit = toBool(c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/);
479    myprintf_buf[n_myprintf_buf++] = c;
480    myprintf_buf[n_myprintf_buf] = 0;
481    if (emit) {
482       (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
483       n_myprintf_buf = 0;
484       myprintf_buf[n_myprintf_buf] = 0;
485    }
486 }
487
488 UInt vex_printf ( HChar* format, ... )
489 {
490    UInt ret;
491    va_list vargs;
492    va_start(vargs,format);
493    
494    n_myprintf_buf = 0;
495    myprintf_buf[n_myprintf_buf] = 0;      
496    ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
497
498    if (n_myprintf_buf > 0) {
499       (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
500    }
501
502    va_end(vargs);
503
504    return ret;
505 }
506
507
508 /* A general replacement for sprintf(). */
509
510 static HChar *vg_sprintf_ptr;
511
512 static void add_to_vg_sprintf_buf ( HChar c )
513 {
514    *vg_sprintf_ptr++ = c;
515 }
516
517 UInt vex_sprintf ( HChar* buf, HChar *format, ... )
518 {
519    Int ret;
520    va_list vargs;
521
522    vg_sprintf_ptr = buf;
523
524    va_start(vargs,format);
525
526    ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
527    add_to_vg_sprintf_buf(0);
528
529    va_end(vargs);
530
531    vassert(vex_strlen(buf) == ret);
532    return ret;
533 }
534
535
536 /*---------------------------------------------------------------*/
537 /*--- end                                         main_util.c ---*/
538 /*---------------------------------------------------------------*/