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-2015 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