1 2 /*--------------------------------------------------------------------*/ 3 /*--- Debug (not-for-user) logging; also vprintf. m_debuglog.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2011 Julian Seward 11 jseward (at) acm.org 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., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 32 /* Performs low-level debug logging that can safely run immediately 33 after startup. To minimise the dependencies on any other parts of 34 the system, the only place the debug output may go is file 35 descriptor 2 (stderr). 36 */ 37 /* This is the first-initialised module in the entire system! 38 Therefore it is CRITICAL that it does not depend on any other code 39 running first. Hence only the following very limited includes. We 40 cannot depend (directly or indirectly) on any dynamic memory 41 allocation facilities, nor on the m_libc facilities, since the 42 latter depend on this module. DO NOT MESS WITH THESE INCLUDES 43 UNLESS YOU ARE 100% CERTAIN YOU UNDERSTAND THE CONSEQUENCES. 44 */ 45 46 /* This module is also notable because it is linked into both 47 stage1 and stage2. */ 48 49 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions 50 of syscalls rather than the vanilla version, if a _nocancel version 51 is available. See docs/internals/Darwin-notes.txt for the reason 52 why. */ 53 54 #include "pub_core_basics.h" /* basic types */ 55 #include "pub_core_vkiscnums.h" /* for syscall numbers */ 56 #include "pub_core_debuglog.h" /* our own iface */ 57 #include "valgrind.h" /* for RUNNING_ON_VALGRIND */ 58 59 static Bool clo_xml; 60 61 void VG_(debugLog_setXml)(Bool xml) 62 { 63 clo_xml = xml; 64 } 65 66 /*------------------------------------------------------------*/ 67 /*--- Stuff to make us completely independent. ---*/ 68 /*------------------------------------------------------------*/ 69 70 /* ----- Platform-specifics ----- */ 71 72 #if defined(VGP_x86_linux) 73 74 static UInt local_sys_write_stderr ( HChar* buf, Int n ) 75 { 76 volatile Int block[2]; 77 block[0] = (Int)buf; 78 block[1] = n; 79 __asm__ volatile ( 80 "pushl %%ebx\n" /* ebx is callee-save */ 81 "movl %0, %%ebx\n" /* ebx = &block */ 82 "pushl %%ebx\n" /* save &block */ 83 "movl 0(%%ebx), %%ecx\n" /* %ecx = buf */ 84 "movl 4(%%ebx), %%edx\n" /* %edx = n */ 85 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */ 86 "movl $2, %%ebx\n" /* %ebx = stderr */ 87 "int $0x80\n" /* write(stderr, buf, n) */ 88 "popl %%ebx\n" /* reestablish &block */ 89 "movl %%eax, 0(%%ebx)\n" /* block[0] = result */ 90 "popl %%ebx\n" /* restore ebx */ 91 : /*wr*/ 92 : /*rd*/ "r" (block) 93 : /*trash*/ "eax", "edi", "ecx", "edx", "memory", "cc" 94 ); 95 if (block[0] < 0) 96 block[0] = -1; 97 return block[0]; 98 } 99 100 static UInt local_sys_getpid ( void ) 101 { 102 UInt __res; 103 __asm__ volatile ( 104 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */ 105 "int $0x80\n" /* getpid() */ 106 "movl %%eax, %0\n" /* set __res = eax */ 107 : "=mr" (__res) 108 : 109 : "eax" ); 110 return __res; 111 } 112 113 #elif defined(VGP_amd64_linux) 114 __attribute__((noinline)) 115 static UInt local_sys_write_stderr ( HChar* buf, Int n ) 116 { 117 volatile Long block[2]; 118 block[0] = (Long)buf; 119 block[1] = n; 120 __asm__ volatile ( 121 "subq $256, %%rsp\n" /* don't trash the stack redzone */ 122 "pushq %%r15\n" /* r15 is callee-save */ 123 "movq %0, %%r15\n" /* r15 = &block */ 124 "pushq %%r15\n" /* save &block */ 125 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */ 126 "movq $2, %%rdi\n" /* rdi = stderr */ 127 "movq 0(%%r15), %%rsi\n" /* rsi = buf */ 128 "movq 8(%%r15), %%rdx\n" /* rdx = n */ 129 "syscall\n" /* write(stderr, buf, n) */ 130 "popq %%r15\n" /* reestablish &block */ 131 "movq %%rax, 0(%%r15)\n" /* block[0] = result */ 132 "popq %%r15\n" /* restore r15 */ 133 "addq $256, %%rsp\n" /* restore stack ptr */ 134 : /*wr*/ 135 : /*rd*/ "r" (block) 136 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc" 137 ); 138 if (block[0] < 0) 139 block[0] = -1; 140 return (UInt)block[0]; 141 } 142 143 static UInt local_sys_getpid ( void ) 144 { 145 UInt __res; 146 __asm__ volatile ( 147 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */ 148 "syscall\n" /* getpid() */ 149 "movl %%eax, %0\n" /* set __res = %eax */ 150 : "=mr" (__res) 151 : 152 : "rax" ); 153 return __res; 154 } 155 156 #elif defined(VGP_ppc32_linux) 157 158 static UInt local_sys_write_stderr ( HChar* buf, Int n ) 159 { 160 volatile Int block[2]; 161 block[0] = (Int)buf; 162 block[1] = n; 163 __asm__ volatile ( 164 "addi 1,1,-256\n\t" 165 "mr 5,%0\n\t" /* r5 = &block[0] */ 166 "stw 5,0(1)\n\t" /* stash on stack */ 167 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */ 168 "li 3,2\n\t" /* set %r3 = stderr */ 169 "lwz 4,0(5)\n\t" /* set %r4 = buf */ 170 "lwz 5,4(5)\n\t" /* set %r5 = n */ 171 "sc\n\t" /* write(stderr, buf, n) */ 172 "lwz 5,0(1)\n\t" 173 "addi 1,1,256\n\t" 174 "stw 3,0(5)\n" /* block[0] = result */ 175 : 176 : "b" (block) 177 : "cc","memory","cr0","ctr", 178 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12" 179 ); 180 if (block[0] < 0) 181 block[0] = -1; 182 return (UInt)block[0]; 183 } 184 185 static UInt local_sys_getpid ( void ) 186 { 187 register UInt __res __asm__ ("r3"); 188 __asm__ volatile ( 189 "li 0, %1\n\t" 190 "sc" 191 : "=&r" (__res) 192 : "i" (__NR_getpid) 193 : "cc","memory","cr0","ctr", 194 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12" 195 ); 196 return __res; 197 } 198 199 #elif defined(VGP_ppc64_linux) 200 201 static UInt local_sys_write_stderr ( HChar* buf, Int n ) 202 { 203 volatile Long block[2]; 204 block[0] = (Long)buf; 205 block[1] = (Long)n; 206 __asm__ volatile ( 207 "addi 1,1,-256\n\t" 208 "mr 5,%0\n\t" /* r5 = &block[0] */ 209 "std 5,0(1)\n\t" /* stash on stack */ 210 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */ 211 "li 3,2\n\t" /* set %r3 = stderr */ 212 "ld 4,0(5)\n\t" /* set %r4 = buf */ 213 "ld 5,8(5)\n\t" /* set %r5 = n */ 214 "sc\n\t" /* write(stderr, buf, n) */ 215 "ld 5,0(1)\n\t" 216 "addi 1,1,256\n\t" 217 "std 3,0(5)\n" /* block[0] = result */ 218 : 219 : "b" (block) 220 : "cc","memory","cr0","ctr", 221 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12" 222 ); 223 if (block[0] < 0) 224 block[0] = -1; 225 return (UInt)(Int)block[0]; 226 } 227 228 static UInt local_sys_getpid ( void ) 229 { 230 register ULong __res __asm__ ("r3"); 231 __asm__ volatile ( 232 "li 0, %1\n\t" 233 "sc" 234 : "=&r" (__res) 235 : "i" (__NR_getpid) 236 : "cc","memory","cr0","ctr", 237 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12" 238 ); 239 return (UInt)__res; 240 } 241 242 #elif defined(VGP_arm_linux) 243 244 static UInt local_sys_write_stderr ( HChar* buf, Int n ) 245 { 246 volatile Int block[2]; 247 block[0] = (Int)buf; 248 block[1] = n; 249 __asm__ volatile ( 250 "mov r0, #2\n\t" /* stderr */ 251 "ldr r1, [%0]\n\t" /* buf */ 252 "ldr r2, [%0, #4]\n\t" /* n */ 253 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t" 254 "svc 0x0\n" /* write() */ 255 "str r0, [%0]\n\t" 256 : 257 : "r" (block) 258 : "r0","r1","r2","r7" 259 ); 260 if (block[0] < 0) 261 block[0] = -1; 262 return (UInt)block[0]; 263 } 264 265 static UInt local_sys_getpid ( void ) 266 { 267 UInt __res; 268 __asm__ volatile ( 269 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n" 270 "svc 0x0\n" /* getpid() */ 271 "mov %0, r0\n" 272 : "=r" (__res) 273 : 274 : "r0", "r7" ); 275 return __res; 276 } 277 278 #elif defined(VGP_x86_darwin) 279 280 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX 281 except that the former has a C ternary ?: operator which isn't valid in 282 asm code. Both macros give the same results for Unix-class syscalls (which 283 these all are, as identified by the use of 'int 0x80'). */ 284 __attribute__((noinline)) 285 static UInt local_sys_write_stderr ( HChar* buf, Int n ) 286 { 287 UInt __res; 288 __asm__ volatile ( 289 "movl %2, %%eax\n" /* push n */ 290 "pushl %%eax\n" 291 "movl %1, %%eax\n" /* push buf */ 292 "pushl %%eax\n" 293 "movl $2, %%eax\n" /* push stderr */ 294 "pushl %%eax\n" 295 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel)) 296 ", %%eax\n" 297 "pushl %%eax\n" /* push fake return address */ 298 "int $0x80\n" /* write(stderr, buf, n) */ 299 "jnc 1f\n" /* jump if no error */ 300 "movl $-1, %%eax\n" /* return -1 if error */ 301 "1: " 302 "movl %%eax, %0\n" /* __res = eax */ 303 "addl $16, %%esp\n" /* pop x4 */ 304 : "=mr" (__res) 305 : "g" (buf), "g" (n) 306 : "eax", "edx", "cc" 307 ); 308 return __res; 309 } 310 311 static UInt local_sys_getpid ( void ) 312 { 313 UInt __res; 314 __asm__ volatile ( 315 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n" 316 "int $0x80\n" /* getpid() */ 317 "movl %%eax, %0\n" /* set __res = eax */ 318 : "=mr" (__res) 319 : 320 : "eax", "cc" ); 321 return __res; 322 } 323 324 #elif defined(VGP_amd64_darwin) 325 326 __attribute__((noinline)) 327 static UInt local_sys_write_stderr ( HChar* buf, Int n ) 328 { 329 UInt __res; 330 __asm__ volatile ( 331 "movq $2, %%rdi\n" /* push stderr */ 332 "movq %1, %%rsi\n" /* push buf */ 333 "movl %2, %%edx\n" /* push n */ 334 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel)) 335 ", %%eax\n" 336 "syscall\n" /* write(stderr, buf, n) */ 337 "jnc 1f\n" /* jump if no error */ 338 "movq $-1, %%rax\n" /* return -1 if error */ 339 "1: " 340 "movl %%eax, %0\n" /* __res = eax */ 341 : "=mr" (__res) 342 : "g" (buf), "g" (n) 343 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" ); 344 return __res; 345 } 346 347 static UInt local_sys_getpid ( void ) 348 { 349 UInt __res; 350 __asm__ volatile ( 351 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n" 352 "syscall\n" /* getpid() */ 353 "movl %%eax, %0\n" /* set __res = eax */ 354 : "=mr" (__res) 355 : 356 : "rax", "rcx", "cc" ); 357 return __res; 358 } 359 360 #elif defined(VGP_s390x_linux) 361 static UInt local_sys_write_stderr ( HChar* buf, Int n ) 362 { 363 register Int r2 asm("2") = 2; /* file descriptor STDERR */ 364 register HChar* r3 asm("3") = buf; 365 register ULong r4 asm("4") = n; 366 register ULong r2_res asm("2"); 367 ULong __res; 368 369 __asm__ __volatile__ ( 370 "svc %b1\n" 371 : "=d" (r2_res) 372 : "i" (__NR_write), 373 "0" (r2), 374 "d" (r3), 375 "d" (r4) 376 : "cc", "memory"); 377 __res = r2_res; 378 379 if (__res >= (ULong)(-125)) 380 __res = -1; 381 return (UInt)(__res); 382 } 383 384 static UInt local_sys_getpid ( void ) 385 { 386 register ULong r2 asm("2"); 387 ULong __res; 388 389 __asm__ __volatile__ ( 390 "svc %b1\n" 391 : "=d" (r2) 392 : "i" (__NR_getpid) 393 : "cc", "memory"); 394 __res = r2; 395 396 if (__res >= (ULong)(-125)) 397 __res = -1; 398 return (UInt)(__res); 399 } 400 401 402 #else 403 # error Unknown platform 404 #endif 405 406 407 /* ----- generic ----- */ 408 409 /* strlen, so we don't need m_libc */ 410 static Int local_strlen ( const HChar* str ) 411 { 412 Int i = 0; 413 while (str[i] != 0) i++; 414 return i; 415 } 416 417 static HChar local_toupper ( HChar c ) 418 { 419 if (c >= 'a' && c <= 'z') 420 return c + ('A' - 'a'); 421 else 422 return c; 423 } 424 425 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific. 426 */ 427 static void emit ( HChar* buf, Int n ) 428 { 429 if (n >= 1) 430 (void)local_sys_write_stderr(buf, n); 431 } 432 433 434 /*------------------------------------------------------------*/ 435 /*--- A simple, generic, vprintf implementation. ---*/ 436 /*------------------------------------------------------------*/ 437 438 /* ----------------------------------------------- 439 Distantly derived from: 440 441 vprintf replacement for Checker. 442 Copyright 1993, 1994, 1995 Tristan Gingold 443 Written September 1993 Tristan Gingold 444 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE 445 446 (Checker itself was GPL'd.) 447 ----------------------------------------------- */ 448 449 /* Some flags. */ 450 #define VG_MSG_SIGNED 1 /* The value is signed. */ 451 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */ 452 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */ 453 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */ 454 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */ 455 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */ 456 457 /* Copy a string into the buffer. */ 458 static 459 UInt myvprintf_str ( void(*send)(HChar,void*), 460 void* send_arg2, 461 Int flags, 462 Int width, 463 HChar* str, 464 Bool capitalise ) 465 { 466 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch)) 467 UInt ret = 0; 468 Int i, extra; 469 Int len = local_strlen(str); 470 471 if (width == 0) { 472 ret += len; 473 for (i = 0; i < len; i++) 474 send(MAYBE_TOUPPER(str[i]), send_arg2); 475 return ret; 476 } 477 478 if (len > width) { 479 ret += width; 480 for (i = 0; i < width; i++) 481 send(MAYBE_TOUPPER(str[i]), send_arg2); 482 return ret; 483 } 484 485 extra = width - len; 486 if (flags & VG_MSG_LJUSTIFY) { 487 ret += extra; 488 for (i = 0; i < extra; i++) 489 send(' ', send_arg2); 490 } 491 ret += len; 492 for (i = 0; i < len; i++) 493 send(MAYBE_TOUPPER(str[i]), send_arg2); 494 if (!(flags & VG_MSG_LJUSTIFY)) { 495 ret += extra; 496 for (i = 0; i < extra; i++) 497 send(' ', send_arg2); 498 } 499 500 # undef MAYBE_TOUPPER 501 return ret; 502 } 503 504 505 /* Copy a string into the buffer, escaping bad XML chars. */ 506 static 507 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*), 508 void* send_arg2, 509 HChar* str ) 510 { 511 UInt ret = 0; 512 Int i; 513 Int len = local_strlen(str); 514 HChar* alt; 515 516 for (i = 0; i < len; i++) { 517 switch (str[i]) { 518 case '&': alt = "&"; break; 519 case '<': alt = "<"; break; 520 case '>': alt = ">"; break; 521 default: alt = NULL; 522 } 523 524 if (alt) { 525 while (*alt) { 526 send(*alt, send_arg2); 527 ret++; 528 alt++; 529 } 530 } else { 531 send(str[i], send_arg2); 532 ret++; 533 } 534 } 535 536 return ret; 537 } 538 539 540 /* Write P into the buffer according to these args: 541 * If SIGN is true, p is a signed. 542 * BASE is the base. 543 * If WITH_ZERO is true, '0' must be added. 544 * WIDTH is the width of the field. 545 */ 546 static 547 UInt myvprintf_int64 ( void(*send)(HChar,void*), 548 void* send_arg2, 549 Int flags, 550 Int base, 551 Int width, 552 Bool capitalised, 553 ULong p ) 554 { 555 HChar buf[40]; 556 Int ind = 0; 557 Int i, nc = 0; 558 Bool neg = False; 559 HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef"; 560 UInt ret = 0; 561 562 if (base < 2 || base > 16) 563 return ret; 564 565 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) { 566 p = - (Long)p; 567 neg = True; 568 } 569 570 if (p == 0) 571 buf[ind++] = '0'; 572 else { 573 while (p > 0) { 574 if (flags & VG_MSG_COMMA && 10 == base && 575 0 == (ind-nc) % 3 && 0 != ind) 576 { 577 buf[ind++] = ','; 578 nc++; 579 } 580 buf[ind++] = digits[p % base]; 581 p /= base; 582 } 583 } 584 585 if (neg) 586 buf[ind++] = '-'; 587 588 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) { 589 for(; ind < width; ind++) { 590 /* vg_assert(ind < 39); */ 591 if (ind > 39) { 592 buf[39] = 0; 593 break; 594 } 595 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' '; 596 } 597 } 598 599 /* Reverse copy to buffer. */ 600 ret += ind; 601 for (i = ind -1; i >= 0; i--) { 602 send(buf[i], send_arg2); 603 } 604 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) { 605 for(; ind < width; ind++) { 606 ret++; 607 /* Never pad with zeroes on RHS -- changes the value! */ 608 send(' ', send_arg2); 609 } 610 } 611 return ret; 612 } 613 614 615 /* A simple vprintf(). */ 616 /* EXPORTED */ 617 UInt 618 VG_(debugLog_vprintf) ( 619 void(*send)(HChar,void*), 620 void* send_arg2, 621 const HChar* format, 622 va_list vargs 623 ) 624 { 625 UInt ret = 0; 626 Int i; 627 Int flags; 628 Int width; 629 Int n_ls = 0; 630 Bool is_long, caps; 631 632 /* We assume that vargs has already been initialised by the 633 caller, using va_start, and that the caller will similarly 634 clean up with va_end. 635 */ 636 637 for (i = 0; format[i] != 0; i++) { 638 if (format[i] != '%') { 639 send(format[i], send_arg2); 640 ret++; 641 continue; 642 } 643 i++; 644 /* A '%' has been found. Ignore a trailing %. */ 645 if (format[i] == 0) 646 break; 647 if (format[i] == '%') { 648 /* '%%' is replaced by '%'. */ 649 send('%', send_arg2); 650 ret++; 651 continue; 652 } 653 flags = 0; 654 n_ls = 0; 655 width = 0; /* length of the field. */ 656 while (1) { 657 switch (format[i]) { 658 case '(': 659 flags |= VG_MSG_PAREN; 660 break; 661 case ',': 662 case '\'': 663 /* If ',' or '\'' follows '%', commas will be inserted. */ 664 flags |= VG_MSG_COMMA; 665 break; 666 case '-': 667 /* If '-' follows '%', justify on the left. */ 668 flags |= VG_MSG_LJUSTIFY; 669 break; 670 case '0': 671 /* If '0' follows '%', pads will be inserted. */ 672 flags |= VG_MSG_ZJUSTIFY; 673 break; 674 case '#': 675 /* If '#' follows '%', alternative format will be used. */ 676 flags |= VG_MSG_ALTFORMAT; 677 break; 678 default: 679 goto parse_fieldwidth; 680 } 681 i++; 682 } 683 parse_fieldwidth: 684 /* Compute the field length. */ 685 while (format[i] >= '0' && format[i] <= '9') { 686 width *= 10; 687 width += format[i++] - '0'; 688 } 689 while (format[i] == 'l') { 690 i++; 691 n_ls++; 692 } 693 694 // %d means print a 32-bit integer. 695 // %ld means print a word-size integer. 696 // %lld means print a 64-bit integer. 697 if (0 == n_ls) { is_long = False; } 698 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); } 699 else { is_long = True; } 700 701 switch (format[i]) { 702 case 'o': /* %o */ 703 if (flags & VG_MSG_ALTFORMAT) { 704 ret += 2; 705 send('0',send_arg2); 706 } 707 if (is_long) 708 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False, 709 (ULong)(va_arg (vargs, ULong))); 710 else 711 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False, 712 (ULong)(va_arg (vargs, UInt))); 713 break; 714 case 'd': /* %d */ 715 flags |= VG_MSG_SIGNED; 716 if (is_long) 717 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False, 718 (ULong)(va_arg (vargs, Long))); 719 else 720 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False, 721 (ULong)(va_arg (vargs, Int))); 722 break; 723 case 'u': /* %u */ 724 if (is_long) 725 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False, 726 (ULong)(va_arg (vargs, ULong))); 727 else 728 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False, 729 (ULong)(va_arg (vargs, UInt))); 730 break; 731 case 'p': 732 if (format[i+1] == 'S') { 733 i++; 734 /* %pS, like %s but escaping chars for XML safety */ 735 /* Note: simplistic; ignores field width and flags */ 736 char *str = va_arg (vargs, char *); 737 if (str == (char*) 0) 738 str = "(null)"; 739 ret += myvprintf_str_XML_simplistic(send, send_arg2, str); 740 } else if (format[i+1] == 's') { 741 i++; 742 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */ 743 char *str = va_arg (vargs, char *); 744 if (str == (char*) 0) 745 str = "(null)"; 746 if (clo_xml) 747 ret += myvprintf_str_XML_simplistic(send, send_arg2, str); 748 else 749 ret += myvprintf_str(send, send_arg2, flags, width, str, 750 False); 751 } else { 752 /* %p */ 753 ret += 2; 754 send('0',send_arg2); 755 send('x',send_arg2); 756 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True, 757 (ULong)((UWord)va_arg (vargs, void *))); 758 } 759 break; 760 case 'x': /* %x */ 761 case 'X': /* %X */ 762 caps = toBool(format[i] == 'X'); 763 if (flags & VG_MSG_ALTFORMAT) { 764 ret += 2; 765 send('0',send_arg2); 766 send('x',send_arg2); 767 } 768 if (is_long) 769 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps, 770 (ULong)(va_arg (vargs, ULong))); 771 else 772 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps, 773 (ULong)(va_arg (vargs, UInt))); 774 break; 775 case 'c': /* %c */ 776 ret++; 777 send(va_arg (vargs, int), send_arg2); 778 break; 779 case 's': case 'S': { /* %s */ 780 char *str = va_arg (vargs, char *); 781 if (str == (char*) 0) str = "(null)"; 782 ret += myvprintf_str(send, send_arg2, 783 flags, width, str, format[i]=='S'); 784 break; 785 } 786 787 // case 'y': { /* %y - print symbol */ 788 // Char buf[100]; 789 // Char *cp = buf; 790 // Addr a = va_arg(vargs, Addr); 791 // 792 // if (flags & VG_MSG_PAREN) 793 // *cp++ = '('; 794 // if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) { 795 // if (flags & VG_MSG_PAREN) { 796 // cp += VG_(strlen)(cp); 797 // *cp++ = ')'; 798 // *cp = '\0'; 799 // } 800 // ret += myvprintf_str(send, send_arg2, flags, width, buf, 0); 801 // } 802 // break; 803 // } 804 default: 805 break; 806 } 807 } 808 return ret; 809 } 810 811 812 /*------------------------------------------------------------*/ 813 /*--- Debuglog stuff. ---*/ 814 /*------------------------------------------------------------*/ 815 816 /* Only print messages whose stated level is less than or equal to 817 this. By default, it makes this entire subsystem silent. */ 818 819 static Int loglevel = 0; 820 821 /* Module startup. */ 822 /* EXPORTED */ 823 void VG_(debugLog_startup) ( Int level, HChar* who ) 824 { 825 if (level < 0) level = 0; 826 if (level > 10) level = 10; 827 loglevel = level; 828 VG_(debugLog)(1, "debuglog", 829 "DebugLog system started by %s, " 830 "level %d logging requested\n", 831 who, loglevel); 832 } 833 834 /* Get the logging threshold level, as set by the most recent call to 835 VG_(debugLog_startup), or zero if there have been no such calls so 836 far. */ 837 /* EXPORTED */ 838 Int VG_(debugLog_getLevel) ( void ) 839 { 840 return loglevel; 841 } 842 843 844 /* ------------ */ 845 846 typedef 847 struct { 848 HChar buf[100]; 849 Int n; 850 } 851 printf_buf; 852 853 static void add_to_buf ( HChar c, void* p ) 854 { 855 printf_buf* buf = (printf_buf*)p; 856 857 if (buf->n >= 100-10 /*paranoia*/ ) { 858 emit( buf->buf, local_strlen(buf->buf) ); 859 buf->n = 0; 860 buf->buf[buf->n] = 0; 861 } 862 buf->buf[buf->n++] = c; 863 buf->buf[buf->n] = 0; 864 } 865 866 /* Send a logging message. Nothing is output unless 'level' 867 is <= the current loglevel. */ 868 /* EXPORTED */ 869 void VG_(debugLog) ( Int level, const HChar* modulename, 870 const HChar* format, ... ) 871 { 872 UInt pid; 873 Int indent, depth, i; 874 va_list vargs; 875 printf_buf buf; 876 877 if (level > loglevel) 878 return; 879 880 indent = 2*level - 1; 881 if (indent < 1) indent = 1; 882 883 buf.n = 0; 884 buf.buf[0] = 0; 885 pid = local_sys_getpid(); 886 887 // Print one '>' in front of the messages for each level of self-hosting 888 // being performed. 889 depth = RUNNING_ON_VALGRIND; 890 for (i = 0; i < depth; i++) { 891 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False ); 892 } 893 894 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False ); 895 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid ); 896 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False ); 897 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level ); 898 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False ); 899 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, (HChar*)modulename, False ); 900 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False ); 901 902 va_start(vargs,format); 903 904 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs ); 905 906 if (buf.n > 0) { 907 emit( buf.buf, local_strlen(buf.buf) ); 908 } 909 910 va_end(vargs); 911 } 912 913 914 915 /*--------------------------------------------------------------------*/ 916 /*--- end m_debuglog.c ---*/ 917 /*--------------------------------------------------------------------*/ 918