Home | History | Annotate | Download | only in priv
      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-2017 OpenWorks LLP
     11       info (at) 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 
     55 #define N_TEMPORARY_BYTES 5000000
     56 
     57 static HChar  temporary[N_TEMPORARY_BYTES] __attribute__((aligned(REQ_ALIGN)));
     58 static HChar* temporary_first = &temporary[0];
     59 static HChar* temporary_curr  = &temporary[0];
     60 static HChar* temporary_last  = &temporary[N_TEMPORARY_BYTES-1];
     61 
     62 static ULong  temporary_bytes_allocd_TOT = 0;
     63 
     64 #define N_PERMANENT_BYTES 10000
     65 
     66 static HChar  permanent[N_PERMANENT_BYTES] __attribute__((aligned(REQ_ALIGN)));
     67 static HChar* permanent_first = &permanent[0];
     68 static HChar* permanent_curr  = &permanent[0];
     69 static HChar* permanent_last  = &permanent[N_PERMANENT_BYTES-1];
     70 
     71 HChar* private_LibVEX_alloc_first = &temporary[0];
     72 HChar* private_LibVEX_alloc_curr  = &temporary[0];
     73 HChar* private_LibVEX_alloc_last  = &temporary[N_TEMPORARY_BYTES-1];
     74 
     75 
     76 static VexAllocMode mode = VexAllocModeTEMP;
     77 
     78 void vexAllocSanityCheck ( void )
     79 {
     80    vassert(temporary_first == &temporary[0]);
     81    vassert(temporary_last  == &temporary[N_TEMPORARY_BYTES-1]);
     82    vassert(permanent_first == &permanent[0]);
     83    vassert(permanent_last  == &permanent[N_PERMANENT_BYTES-1]);
     84    vassert(temporary_first <= temporary_curr);
     85    vassert(temporary_curr  <= temporary_last);
     86    vassert(permanent_first <= permanent_curr);
     87    vassert(permanent_curr  <= permanent_last);
     88    vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr);
     89    vassert(private_LibVEX_alloc_curr  <= private_LibVEX_alloc_last);
     90    if (mode == VexAllocModeTEMP){
     91       vassert(private_LibVEX_alloc_first == temporary_first);
     92       vassert(private_LibVEX_alloc_last  == temporary_last);
     93    }
     94    else
     95    if (mode == VexAllocModePERM) {
     96       vassert(private_LibVEX_alloc_first == permanent_first);
     97       vassert(private_LibVEX_alloc_last  == permanent_last);
     98    }
     99    else
    100       vassert(0);
    101 
    102 #  define IS_WORD_ALIGNED(p)   (0 == (((HWord)p) & (sizeof(HWord)-1)))
    103    vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
    104    vassert(IS_WORD_ALIGNED(temporary_first));
    105    vassert(IS_WORD_ALIGNED(temporary_curr));
    106    vassert(IS_WORD_ALIGNED(temporary_last+1));
    107    vassert(IS_WORD_ALIGNED(permanent_first));
    108    vassert(IS_WORD_ALIGNED(permanent_curr));
    109    vassert(IS_WORD_ALIGNED(permanent_last+1));
    110    vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first));
    111    vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr));
    112    vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1));
    113 #  undef IS_WORD_ALIGNED
    114 }
    115 
    116 /* The current allocation mode. */
    117 
    118 void vexSetAllocMode ( VexAllocMode m )
    119 {
    120    vexAllocSanityCheck();
    121 
    122    /* Save away the current allocation point .. */
    123    if (mode == VexAllocModeTEMP){
    124       temporary_curr = private_LibVEX_alloc_curr;
    125    }
    126    else
    127    if (mode == VexAllocModePERM) {
    128       permanent_curr = private_LibVEX_alloc_curr;
    129    }
    130    else
    131       vassert(0);
    132 
    133    /* Did that screw anything up? */
    134    vexAllocSanityCheck();
    135 
    136    if (m == VexAllocModeTEMP){
    137       private_LibVEX_alloc_first = temporary_first;
    138       private_LibVEX_alloc_curr  = temporary_curr;
    139       private_LibVEX_alloc_last  = temporary_last;
    140    }
    141    else
    142    if (m == VexAllocModePERM) {
    143       private_LibVEX_alloc_first = permanent_first;
    144       private_LibVEX_alloc_curr  = permanent_curr;
    145       private_LibVEX_alloc_last  = permanent_last;
    146    }
    147    else
    148       vassert(0);
    149 
    150    mode = m;
    151 }
    152 
    153 VexAllocMode vexGetAllocMode ( void )
    154 {
    155    return mode;
    156 }
    157 
    158 __attribute__((noreturn))
    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 
    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 void *LibVEX_Alloc ( SizeT nbytes )
    209 {
    210    return LibVEX_Alloc_inline(nbytes);
    211 }
    212 
    213 /*---------------------------------------------------------*/
    214 /*--- Bombing out                                       ---*/
    215 /*---------------------------------------------------------*/
    216 
    217 __attribute__ ((noreturn))
    218 void vex_assert_fail ( const HChar* expr,
    219                        const HChar* file, Int line, const HChar* fn )
    220 {
    221    vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
    222                file, line, fn, expr );
    223    (*vex_failure_exit)();
    224 }
    225 
    226 /* To be used in assert-like (i.e. should never ever happen) situations */
    227 __attribute__ ((noreturn))
    228 void vpanic ( const HChar* str )
    229 {
    230    vex_printf("\nvex: the `impossible' happened:\n   %s\n", str);
    231    (*vex_failure_exit)();
    232 }
    233 
    234 
    235 /*---------------------------------------------------------*/
    236 /*--- vex_printf                                        ---*/
    237 /*---------------------------------------------------------*/
    238 
    239 /* This should be the only <...> include in the entire VEX library.
    240    New code for vex_util.c should go above this point. */
    241 #include <stdarg.h>
    242 
    243 SizeT vex_strlen ( const HChar* str )
    244 {
    245    SizeT i = 0;
    246    while (str[i] != 0) i++;
    247    return i;
    248 }
    249 
    250 Bool vex_streq ( const HChar* s1, const HChar* s2 )
    251 {
    252    while (True) {
    253       if (*s1 == 0 && *s2 == 0)
    254          return True;
    255       if (*s1 != *s2)
    256          return False;
    257       s1++;
    258       s2++;
    259    }
    260 }
    261 
    262 void vex_bzero ( void* sV, SizeT n )
    263 {
    264    SizeT i;
    265    UChar* s = (UChar*)sV;
    266    /* No laughing, please.  Just don't call this too often.  Thank you
    267       for your attention. */
    268    for (i = 0; i < n; i++) s[i] = 0;
    269 }
    270 
    271 
    272 /* Convert N0 into ascii in BUF, which is assumed to be big enough (at
    273    least 67 bytes long).  Observe BASE, SYNED and HEXCAPS. */
    274 static
    275 void convert_int ( /*OUT*/HChar* buf, Long n0,
    276                    Int base, Bool syned, Bool hexcaps )
    277 {
    278    ULong u0;
    279    HChar c;
    280    Bool minus = False;
    281    Int i, j, bufi = 0;
    282    buf[bufi] = 0;
    283 
    284    if (syned) {
    285       if (n0 < 0) {
    286          minus = True;
    287          u0 = (ULong)(-n0);
    288       } else {
    289          u0 = (ULong)(n0);
    290       }
    291    } else {
    292       u0 = (ULong)n0;
    293    }
    294 
    295    while (1) {
    296      buf[bufi++] = toHChar('0' + toUInt(u0 % base));
    297      u0 /= base;
    298      if (u0 == 0) break;
    299    }
    300    if (minus)
    301       buf[bufi++] = '-';
    302 
    303    buf[bufi] = 0;
    304    for (i = 0; i < bufi; i++)
    305       if (buf[i] > '9')
    306          buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
    307 
    308    i = 0;
    309    j = bufi-1;
    310    while (i <= j) {
    311       c = buf[i];
    312       buf[i] = buf[j];
    313       buf[j] = c;
    314       i++;
    315       j--;
    316    }
    317 }
    318 
    319 
    320 /* A half-arsed and buggy, but good-enough, implementation of
    321    printf. */
    322 static
    323 UInt vprintf_wrk ( void(*sink)(HChar),
    324                    const HChar* format,
    325                    va_list ap )
    326 {
    327 #  define PUT(_ch)  \
    328       do { sink(_ch); nout++; } \
    329       while (0)
    330 
    331 #  define PAD(_n) \
    332       do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
    333       while (0)
    334 
    335 #  define PUTSTR(_str) \
    336       do { const HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
    337       while (0)
    338 
    339    const HChar* saved_format;
    340    Bool   longlong, ljustify, is_sizet;
    341    HChar  padchar;
    342    Int    fwidth, nout, len1, len3;
    343    SizeT  len2;
    344    HChar  intbuf[100];  /* big enough for a 64-bit # in base 2 */
    345 
    346    nout = 0;
    347    while (1) {
    348 
    349       if (!format)
    350          break;
    351       if (*format == 0)
    352          break;
    353 
    354       if (*format != '%') {
    355          PUT(*format);
    356          format++;
    357          continue;
    358       }
    359 
    360       saved_format = format;
    361       longlong = is_sizet = False;
    362       ljustify = False;
    363       padchar = ' ';
    364       fwidth = 0;
    365       format++;
    366 
    367       if (*format == '-') {
    368          format++;
    369          ljustify = True;
    370       }
    371       if (*format == '0') {
    372          format++;
    373          padchar = '0';
    374       }
    375       if (*format == '*') {
    376          fwidth = va_arg(ap, Int);
    377          vassert(fwidth >= 0);
    378          format++;
    379       } else {
    380          while (*format >= '0' && *format <= '9') {
    381             fwidth = fwidth * 10 + (*format - '0');
    382             format++;
    383          }
    384       }
    385       if (*format == 'l') {
    386          format++;
    387          if (*format == 'l') {
    388             format++;
    389             longlong = True;
    390          }
    391       } else if (*format == 'z') {
    392          format++;
    393          is_sizet = True;
    394       }
    395 
    396       switch (*format) {
    397          case 's': {
    398             const HChar* str = va_arg(ap, HChar*);
    399             if (str == NULL)
    400                str = "(null)";
    401             len1 = len3 = 0;
    402             len2 = vex_strlen(str);
    403             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
    404                                  len3 = ljustify ? fwidth-len2 : 0; }
    405             PAD(len1); PUTSTR(str); PAD(len3);
    406             break;
    407          }
    408          case 'c': {
    409             HChar c = (HChar)va_arg(ap, int);
    410             HChar str[2];
    411             str[0] = c;
    412             str[1] = 0;
    413             len1 = len3 = 0;
    414             len2 = vex_strlen(str);
    415             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
    416                                  len3 = ljustify ? fwidth-len2 : 0; }
    417             PAD(len1); PUTSTR(str); PAD(len3);
    418             break;
    419          }
    420          case 'd': {
    421             Long l;
    422             vassert(is_sizet == False); // %zd is obscure; we don't allow it
    423             if (longlong) {
    424                l = va_arg(ap, Long);
    425             } else {
    426                l = (Long)va_arg(ap, Int);
    427             }
    428             convert_int(intbuf, l, 10/*base*/, True/*signed*/,
    429                                 False/*irrelevant*/);
    430             len1 = len3 = 0;
    431             len2 = vex_strlen(intbuf);
    432             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
    433                                  len3 = ljustify ? fwidth-len2 : 0; }
    434             PAD(len1); PUTSTR(intbuf); PAD(len3);
    435             break;
    436          }
    437          case 'u':
    438          case 'x':
    439          case 'X': {
    440             Int   base = *format == 'u' ? 10 : 16;
    441             Bool  hexcaps = True; /* *format == 'X'; */
    442             ULong l;
    443             if (is_sizet) {
    444                l = (ULong)va_arg(ap, SizeT);
    445             } else if (longlong) {
    446                l = va_arg(ap, ULong);
    447             } else {
    448                l = (ULong)va_arg(ap, UInt);
    449             }
    450             convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
    451             len1 = len3 = 0;
    452             len2 = vex_strlen(intbuf);
    453             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
    454                                  len3 = ljustify ? fwidth-len2 : 0; }
    455             PAD(len1); PUTSTR(intbuf); PAD(len3);
    456             break;
    457          }
    458          case 'p':
    459          case 'P': {
    460             Bool hexcaps = toBool(*format == 'P');
    461             ULong l = (Addr)va_arg(ap, void*);
    462             convert_int(intbuf, l, 16/*base*/, False/*unsigned*/, hexcaps);
    463             len1 = len3 = 0;
    464             len2 = vex_strlen(intbuf)+2;
    465             if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
    466                                  len3 = ljustify ? fwidth-len2 : 0; }
    467             PAD(len1); PUT('0'); PUT('x'); PUTSTR(intbuf); PAD(len3);
    468             break;
    469          }
    470          case '%': {
    471             PUT('%');
    472             break;
    473          }
    474          default:
    475             /* no idea what it is.  Print the format literally and
    476                move on. */
    477             while (saved_format <= format) {
    478                PUT(*saved_format);
    479                saved_format++;
    480             }
    481             break;
    482       }
    483 
    484       format++;
    485 
    486    }
    487 
    488    return nout;
    489 
    490 #  undef PUT
    491 #  undef PAD
    492 #  undef PUTSTR
    493 }
    494 
    495 
    496 /* A general replacement for printf().  Note that only low-level
    497    debugging info should be sent via here.  The official route is to
    498    to use vg_message().  This interface is deprecated.
    499 */
    500 static HChar myprintf_buf[1000];
    501 static Int   n_myprintf_buf;
    502 
    503 static void add_to_myprintf_buf ( HChar c )
    504 {
    505    Bool emit = toBool(c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/);
    506    myprintf_buf[n_myprintf_buf++] = c;
    507    myprintf_buf[n_myprintf_buf] = 0;
    508    if (emit) {
    509       (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
    510       n_myprintf_buf = 0;
    511       myprintf_buf[n_myprintf_buf] = 0;
    512    }
    513 }
    514 
    515 static UInt vex_vprintf ( const HChar* format, va_list vargs )
    516 {
    517    UInt ret;
    518 
    519    n_myprintf_buf = 0;
    520    myprintf_buf[n_myprintf_buf] = 0;
    521    ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
    522 
    523    if (n_myprintf_buf > 0) {
    524       (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
    525    }
    526 
    527    return ret;
    528 }
    529 
    530 UInt vex_printf ( const HChar* format, ... )
    531 {
    532    UInt ret;
    533    va_list vargs;
    534    va_start(vargs, format);
    535    ret = vex_vprintf(format, vargs);
    536    va_end(vargs);
    537 
    538    return ret;
    539 }
    540 
    541 /* Use this function to communicate to users that a (legitimate) situation
    542    occured that we cannot handle (yet). */
    543 __attribute__ ((noreturn))
    544 void vfatal ( const HChar* format, ... )
    545 {
    546    va_list vargs;
    547    va_start(vargs, format);
    548    vex_vprintf( format, vargs );
    549    va_end(vargs);
    550    vex_printf("Cannot continue. Good-bye\n\n");
    551 
    552    (*vex_failure_exit)();
    553 }
    554 
    555 /* A general replacement for sprintf(). */
    556 
    557 static HChar *vg_sprintf_ptr;
    558 
    559 static void add_to_vg_sprintf_buf ( HChar c )
    560 {
    561    *vg_sprintf_ptr++ = c;
    562 }
    563 
    564 UInt vex_sprintf ( HChar* buf, const HChar *format, ... )
    565 {
    566    Int ret;
    567    va_list vargs;
    568 
    569    vg_sprintf_ptr = buf;
    570 
    571    va_start(vargs,format);
    572 
    573    ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
    574    add_to_vg_sprintf_buf(0);
    575 
    576    va_end(vargs);
    577 
    578    vassert(vex_strlen(buf) == ret);
    579    return ret;
    580 }
    581 
    582 
    583 /*---------------------------------------------------------*/
    584 /*--- Misaligned memory access support                  ---*/
    585 /*---------------------------------------------------------*/
    586 
    587 UInt read_misaligned_UInt_LE ( void* addr )
    588 {
    589    UChar* p = (UChar*)addr;
    590    UInt   w = 0;
    591    w = (w << 8) | p[3];
    592    w = (w << 8) | p[2];
    593    w = (w << 8) | p[1];
    594    w = (w << 8) | p[0];
    595    return w;
    596 }
    597 
    598 ULong read_misaligned_ULong_LE ( void* addr )
    599 {
    600    UChar* p = (UChar*)addr;
    601    ULong  w = 0;
    602    w = (w << 8) | p[7];
    603    w = (w << 8) | p[6];
    604    w = (w << 8) | p[5];
    605    w = (w << 8) | p[4];
    606    w = (w << 8) | p[3];
    607    w = (w << 8) | p[2];
    608    w = (w << 8) | p[1];
    609    w = (w << 8) | p[0];
    610    return w;
    611 }
    612 
    613 void write_misaligned_UInt_LE ( void* addr, UInt w )
    614 {
    615    UChar* p = (UChar*)addr;
    616    p[0] = (w & 0xFF); w >>= 8;
    617    p[1] = (w & 0xFF); w >>= 8;
    618    p[2] = (w & 0xFF); w >>= 8;
    619    p[3] = (w & 0xFF); w >>= 8;
    620 }
    621 
    622 void write_misaligned_ULong_LE ( void* addr, ULong w )
    623 {
    624    UChar* p = (UChar*)addr;
    625    p[0] = (w & 0xFF); w >>= 8;
    626    p[1] = (w & 0xFF); w >>= 8;
    627    p[2] = (w & 0xFF); w >>= 8;
    628    p[3] = (w & 0xFF); w >>= 8;
    629    p[4] = (w & 0xFF); w >>= 8;
    630    p[5] = (w & 0xFF); w >>= 8;
    631    p[6] = (w & 0xFF); w >>= 8;
    632    p[7] = (w & 0xFF); w >>= 8;
    633 }
    634 
    635 
    636 /*---------------------------------------------------------------*/
    637 /*--- end                                         main_util.c ---*/
    638 /*---------------------------------------------------------------*/
    639