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