1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 17 To Do: 18 19 - Use StackWalk on Windows to optionally print stack frames. 20 */ 21 22 #if 0 23 #pragma mark == Includes == 24 #endif 25 26 //=========================================================================================================================== 27 // Includes 28 //=========================================================================================================================== 29 30 #if( !KERNEL ) 31 #include <ctype.h> 32 #include <stdio.h> 33 #include <string.h> 34 #endif 35 36 #include "CommonServices.h" 37 38 #include "DebugServices.h" 39 40 #if( DEBUG ) 41 42 #if( TARGET_OS_VXWORKS ) 43 #include "intLib.h" 44 #endif 45 46 #if( TARGET_OS_WIN32 ) 47 #include <time.h> 48 49 #if( !TARGET_OS_WINDOWS_CE ) 50 #include <fcntl.h> 51 #include <io.h> 52 #endif 53 #endif 54 55 #if( DEBUG_IDEBUG_ENABLED && TARGET_API_MAC_OSX_KERNEL ) 56 #include <IOKit/IOLib.h> 57 #endif 58 59 // If MDNS_DEBUGMSGS is defined (even if defined 0), it is aware of mDNS and it is probably safe to include mDNSEmbeddedAPI.h. 60 61 #if( defined( MDNS_DEBUGMSGS ) ) 62 #include "mDNSEmbeddedAPI.h" 63 #endif 64 65 #if 0 66 #pragma mark == Macros == 67 #endif 68 69 //=========================================================================================================================== 70 // Macros 71 //=========================================================================================================================== 72 73 #define DebugIsPrint( C ) ( ( ( C ) >= 0x20 ) && ( ( C ) <= 0x7E ) ) 74 75 #if 0 76 #pragma mark == Prototypes == 77 #endif 78 79 //=========================================================================================================================== 80 // Prototypes 81 //=========================================================================================================================== 82 83 static OSStatus DebugPrint( DebugLevel inLevel, char *inData, size_t inSize ); 84 85 // fprintf 86 87 #if( DEBUG_FPRINTF_ENABLED ) 88 static OSStatus DebugFPrintFInit( DebugOutputTypeFlags inFlags, const char *inFilename ); 89 static void DebugFPrintFPrint( char *inData, size_t inSize ); 90 #endif 91 92 // iDebug (Mac OS X user and kernel) 93 94 #if( DEBUG_IDEBUG_ENABLED ) 95 static OSStatus DebugiDebugInit( void ); 96 static void DebugiDebugPrint( char *inData, size_t inSize ); 97 #endif 98 99 // kprintf (Mac OS X Kernel) 100 101 #if( DEBUG_KPRINTF_ENABLED ) 102 static void DebugKPrintFPrint( char *inData, size_t inSize ); 103 #endif 104 105 // Mac OS X IOLog (Mac OS X Kernel) 106 107 #if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 108 static void DebugMacOSXIOLogPrint( char *inData, size_t inSize ); 109 #endif 110 111 // Mac OS X Log 112 113 #if( TARGET_OS_MAC ) 114 static OSStatus DebugMacOSXLogInit( void ); 115 static void DebugMacOSXLogPrint( char *inData, size_t inSize ); 116 #endif 117 118 // Windows Debugger 119 120 #if( TARGET_OS_WIN32 ) 121 static void DebugWindowsDebuggerPrint( char *inData, size_t inSize ); 122 #endif 123 124 // Windows Event Log 125 126 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 127 static OSStatus DebugWindowsEventLogInit( const char *inName, HMODULE inModule ); 128 static void DebugWindowsEventLogPrint( DebugLevel inLevel, char *inData, size_t inSize ); 129 #endif 130 131 // DebugLib support 132 133 #if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 134 static pascal void 135 DebugAssertOutputHandler( 136 OSType inComponentSignature, 137 UInt32 inOptions, 138 const char * inAssertionString, 139 const char * inExceptionString, 140 const char * inErrorString, 141 const char * inFileName, 142 long inLineNumber, 143 void * inValue, 144 ConstStr255Param inOutputMsg ); 145 #endif 146 147 // Utilities 148 149 static char * DebugNumVersionToString( uint32_t inVersion, char *inString ); 150 151 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 152 static void DebugWinEnableConsole( void ); 153 #endif 154 155 #if( TARGET_OS_WIN32 ) 156 static TCHAR * 157 DebugWinCharToTCharString( 158 const char * inCharString, 159 size_t inCharCount, 160 TCHAR * outTCharString, 161 size_t inTCharCountMax, 162 size_t * outTCharCount ); 163 #endif 164 165 #if 0 166 #pragma mark == Globals == 167 #endif 168 169 //=========================================================================================================================== 170 // Private Globals 171 //=========================================================================================================================== 172 173 #if( TARGET_OS_VXWORKS ) 174 // TCP States for inetstatShow. 175 176 extern char ** pTcpstates; // defined in tcpLib.c 177 178 const char * kDebugTCPStates[] = 179 { 180 "(0) TCPS_CLOSED", 181 "(1) TCPS_LISTEN", 182 "(2) TCPS_SYN_SENT", 183 "(3) TCPS_SYN_RECEIVED", 184 "(4) TCPS_ESTABLISHED", 185 "(5) TCPS_CLOSE_WAIT", 186 "(6) TCPS_FIN_WAIT_1", 187 "(7) TCPS_CLOSING", 188 "(8) TCPS_LAST_ACK", 189 "(9) TCPS_FIN_WAIT_2", 190 "(10) TCPS_TIME_WAIT", 191 }; 192 #endif 193 194 // General 195 196 static bool gDebugInitialized = false; 197 static DebugOutputType gDebugOutputType = kDebugOutputTypeNone; 198 static DebugLevel gDebugPrintLevelMin = kDebugLevelInfo; 199 static DebugLevel gDebugPrintLevelMax = kDebugLevelMax; 200 static DebugLevel gDebugBreakLevel = kDebugLevelAssert; 201 #if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 202 static DebugAssertOutputHandlerUPP gDebugAssertOutputHandlerUPP = NULL; 203 #endif 204 205 // Custom 206 207 static DebugOutputFunctionPtr gDebugCustomOutputFunction = NULL; 208 static void * gDebugCustomOutputContext = NULL; 209 210 // fprintf 211 212 #if( DEBUG_FPRINTF_ENABLED ) 213 static FILE * gDebugFPrintFFile = NULL; 214 #endif 215 216 // MacOSXLog 217 218 #if( TARGET_OS_MAC ) 219 typedef int ( *DebugMacOSXLogFunctionPtr )( const char *inFormat, ... ); 220 221 static DebugMacOSXLogFunctionPtr gDebugMacOSXLogFunction = NULL; 222 #endif 223 224 // WindowsEventLog 225 226 227 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 228 static HANDLE gDebugWindowsEventLogEventSource = NULL; 229 #endif 230 231 #if 0 232 #pragma mark - 233 #pragma mark == General == 234 #endif 235 236 //=========================================================================================================================== 237 // DebugInitialize 238 //=========================================================================================================================== 239 240 DEBUG_EXPORT OSStatus DebugInitialize( DebugOutputType inType, ... ) 241 { 242 OSStatus err; 243 DebugOutputType type; 244 va_list args; 245 246 va_start( args, inType ); 247 248 #if( TARGET_OS_VXWORKS ) 249 // Set up the TCP state strings if they are not already set up by VxWorks (normally not set up for some reason). 250 251 if( !pTcpstates ) 252 { 253 pTcpstates = (char **) kDebugTCPStates; 254 } 255 #endif 256 257 // Set up DebugLib stuff (if building with Debugging.h). 258 259 #if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 260 if( !gDebugAssertOutputHandlerUPP ) 261 { 262 gDebugAssertOutputHandlerUPP = NewDebugAssertOutputHandlerUPP( DebugAssertOutputHandler ); 263 check( gDebugAssertOutputHandlerUPP ); 264 if( gDebugAssertOutputHandlerUPP ) 265 { 266 InstallDebugAssertOutputHandler( gDebugAssertOutputHandlerUPP ); 267 } 268 } 269 #endif 270 271 // Pre-process meta-output kind to pick an appropriate output kind for the platform. 272 273 type = inType; 274 if( type == kDebugOutputTypeMetaConsole ) 275 { 276 #if( TARGET_OS_MAC ) 277 type = kDebugOutputTypeMacOSXLog; 278 #elif( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 279 #if( DEBUG_FPRINTF_ENABLED ) 280 type = kDebugOutputTypeFPrintF; 281 #else 282 type = kDebugOutputTypeWindowsDebugger; 283 #endif 284 #elif( TARGET_API_MAC_OSX_KERNEL ) 285 #if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 286 type = kDebugOutputTypeMacOSXIOLog; 287 #elif( DEBUG_IDEBUG_ENABLED ) 288 type = kDebugOutputTypeiDebug; 289 #elif( DEBUG_KPRINTF_ENABLED ) 290 type = kDebugOutputTypeKPrintF; 291 #endif 292 #elif( TARGET_OS_VXWORKS ) 293 #if( DEBUG_FPRINTF_ENABLED ) 294 type = kDebugOutputTypeFPrintF; 295 #else 296 #error target is VxWorks, but fprintf output is disabled 297 #endif 298 #else 299 #if( DEBUG_FPRINTF_ENABLED ) 300 type = kDebugOutputTypeFPrintF; 301 #endif 302 #endif 303 } 304 305 // Process output kind. 306 307 gDebugOutputType = type; 308 switch( type ) 309 { 310 case kDebugOutputTypeNone: 311 err = kNoErr; 312 break; 313 314 case kDebugOutputTypeCustom: 315 gDebugCustomOutputFunction = va_arg( args, DebugOutputFunctionPtr ); 316 gDebugCustomOutputContext = va_arg( args, void * ); 317 err = kNoErr; 318 break; 319 320 #if( DEBUG_FPRINTF_ENABLED ) 321 case kDebugOutputTypeFPrintF: 322 if( inType == kDebugOutputTypeMetaConsole ) 323 { 324 err = DebugFPrintFInit( kDebugOutputTypeFlagsStdErr, NULL ); 325 } 326 else 327 { 328 DebugOutputTypeFlags flags; 329 const char * filename; 330 331 flags = (DebugOutputTypeFlags) va_arg( args, unsigned int ); 332 if( ( flags & kDebugOutputTypeFlagsTypeMask ) == kDebugOutputTypeFlagsFile ) 333 { 334 filename = va_arg( args, const char * ); 335 } 336 else 337 { 338 filename = NULL; 339 } 340 err = DebugFPrintFInit( flags, filename ); 341 } 342 break; 343 #endif 344 345 #if( DEBUG_IDEBUG_ENABLED ) 346 case kDebugOutputTypeiDebug: 347 err = DebugiDebugInit(); 348 break; 349 #endif 350 351 #if( DEBUG_KPRINTF_ENABLED ) 352 case kDebugOutputTypeKPrintF: 353 err = kNoErr; 354 break; 355 #endif 356 357 #if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 358 case kDebugOutputTypeMacOSXIOLog: 359 err = kNoErr; 360 break; 361 #endif 362 363 #if( TARGET_OS_MAC ) 364 case kDebugOutputTypeMacOSXLog: 365 err = DebugMacOSXLogInit(); 366 break; 367 #endif 368 369 #if( TARGET_OS_WIN32 ) 370 case kDebugOutputTypeWindowsDebugger: 371 err = kNoErr; 372 break; 373 #endif 374 375 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 376 case kDebugOutputTypeWindowsEventLog: 377 { 378 const char * name; 379 HMODULE module; 380 381 name = va_arg( args, const char * ); 382 module = va_arg( args, HMODULE ); 383 err = DebugWindowsEventLogInit( name, module ); 384 } 385 break; 386 #endif 387 388 default: 389 err = kParamErr; 390 goto exit; 391 } 392 gDebugInitialized = true; 393 394 exit: 395 va_end( args ); 396 return( err ); 397 } 398 399 //=========================================================================================================================== 400 // DebugFinalize 401 //=========================================================================================================================== 402 403 DEBUG_EXPORT void DebugFinalize( void ) 404 { 405 #if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 406 check( gDebugAssertOutputHandlerUPP ); 407 if( gDebugAssertOutputHandlerUPP ) 408 { 409 InstallDebugAssertOutputHandler( NULL ); 410 DisposeDebugAssertOutputHandlerUPP( gDebugAssertOutputHandlerUPP ); 411 gDebugAssertOutputHandlerUPP = NULL; 412 } 413 #endif 414 } 415 416 //=========================================================================================================================== 417 // DebugGetProperty 418 //=========================================================================================================================== 419 420 DEBUG_EXPORT OSStatus DebugGetProperty( DebugPropertyTag inTag, ... ) 421 { 422 OSStatus err; 423 va_list args; 424 DebugLevel * level; 425 426 va_start( args, inTag ); 427 switch( inTag ) 428 { 429 case kDebugPropertyTagPrintLevelMin: 430 level = va_arg( args, DebugLevel * ); 431 *level = gDebugPrintLevelMin; 432 err = kNoErr; 433 break; 434 435 case kDebugPropertyTagPrintLevelMax: 436 level = va_arg( args, DebugLevel * ); 437 *level = gDebugPrintLevelMax; 438 err = kNoErr; 439 break; 440 441 case kDebugPropertyTagBreakLevel: 442 level = va_arg( args, DebugLevel * ); 443 *level = gDebugBreakLevel; 444 err = kNoErr; 445 break; 446 447 default: 448 err = kUnsupportedErr; 449 break; 450 } 451 va_end( args ); 452 return( err ); 453 } 454 455 //=========================================================================================================================== 456 // DebugSetProperty 457 //=========================================================================================================================== 458 459 DEBUG_EXPORT OSStatus DebugSetProperty( DebugPropertyTag inTag, ... ) 460 { 461 OSStatus err; 462 va_list args; 463 DebugLevel level; 464 465 va_start( args, inTag ); 466 switch( inTag ) 467 { 468 case kDebugPropertyTagPrintLevelMin: 469 level = va_arg( args, DebugLevel ); 470 gDebugPrintLevelMin = level; 471 err = kNoErr; 472 break; 473 474 case kDebugPropertyTagPrintLevelMax: 475 level = va_arg( args, DebugLevel ); 476 gDebugPrintLevelMax = level; 477 err = kNoErr; 478 break; 479 480 case kDebugPropertyTagBreakLevel: 481 level = va_arg( args, DebugLevel ); 482 gDebugBreakLevel = level; 483 err = kNoErr; 484 break; 485 486 default: 487 err = kUnsupportedErr; 488 break; 489 } 490 va_end( args ); 491 return( err ); 492 } 493 494 #if 0 495 #pragma mark - 496 #pragma mark == Output == 497 #endif 498 499 //=========================================================================================================================== 500 // DebugPrintF 501 //=========================================================================================================================== 502 503 DEBUG_EXPORT size_t DebugPrintF( DebugLevel inLevel, const char *inFormat, ... ) 504 { 505 va_list args; 506 size_t n; 507 508 // Skip if the level is not in the enabled range.. 509 510 if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) 511 { 512 n = 0; 513 goto exit; 514 } 515 516 va_start( args, inFormat ); 517 n = DebugPrintFVAList( inLevel, inFormat, args ); 518 va_end( args ); 519 520 exit: 521 return( n ); 522 } 523 524 //=========================================================================================================================== 525 // DebugPrintFVAList 526 //=========================================================================================================================== 527 528 DEBUG_EXPORT size_t DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs ) 529 { 530 size_t n; 531 char buffer[ 512 ]; 532 533 // Skip if the level is not in the enabled range.. 534 535 if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) 536 { 537 n = 0; 538 goto exit; 539 } 540 541 n = DebugSNPrintFVAList( buffer, sizeof( buffer ), inFormat, inArgs ); 542 DebugPrint( inLevel, buffer, (size_t) n ); 543 544 exit: 545 return( n ); 546 } 547 548 //=========================================================================================================================== 549 // DebugPrint 550 //=========================================================================================================================== 551 552 static OSStatus DebugPrint( DebugLevel inLevel, char *inData, size_t inSize ) 553 { 554 OSStatus err; 555 556 // Skip if the level is not in the enabled range.. 557 558 if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) 559 { 560 err = kRangeErr; 561 goto exit; 562 } 563 564 // Printing is not safe at interrupt time so check for this and warn with an interrupt safe mechanism (if available). 565 566 if( DebugTaskLevel() & kDebugInterruptLevelMask ) 567 { 568 #if( TARGET_OS_VXWORKS ) 569 logMsg( "\ncannot print at interrupt time\n\n", 1, 2, 3, 4, 5, 6 ); 570 #endif 571 572 err = kExecutionStateErr; 573 goto exit; 574 } 575 576 // Initialize the debugging library if it hasn't already been initialized (allows for zero-config usage). 577 578 if( !gDebugInitialized ) 579 { 580 debug_initialize( kDebugOutputTypeMetaConsole ); 581 } 582 583 // Print based on the current output type. 584 585 switch( gDebugOutputType ) 586 { 587 case kDebugOutputTypeNone: 588 break; 589 590 case kDebugOutputTypeCustom: 591 if( gDebugCustomOutputFunction ) 592 { 593 gDebugCustomOutputFunction( inData, inSize, gDebugCustomOutputContext ); 594 } 595 break; 596 597 #if( DEBUG_FPRINTF_ENABLED ) 598 case kDebugOutputTypeFPrintF: 599 DebugFPrintFPrint( inData, inSize ); 600 break; 601 #endif 602 603 #if( DEBUG_IDEBUG_ENABLED ) 604 case kDebugOutputTypeiDebug: 605 DebugiDebugPrint( inData, inSize ); 606 break; 607 #endif 608 609 #if( DEBUG_KPRINTF_ENABLED ) 610 case kDebugOutputTypeKPrintF: 611 DebugKPrintFPrint( inData, inSize ); 612 break; 613 #endif 614 615 #if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 616 case kDebugOutputTypeMacOSXIOLog: 617 DebugMacOSXIOLogPrint( inData, inSize ); 618 break; 619 #endif 620 621 #if( TARGET_OS_MAC ) 622 case kDebugOutputTypeMacOSXLog: 623 DebugMacOSXLogPrint( inData, inSize ); 624 break; 625 #endif 626 627 #if( TARGET_OS_WIN32 ) 628 case kDebugOutputTypeWindowsDebugger: 629 DebugWindowsDebuggerPrint( inData, inSize ); 630 break; 631 #endif 632 633 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 634 case kDebugOutputTypeWindowsEventLog: 635 DebugWindowsEventLogPrint( inLevel, inData, inSize ); 636 break; 637 #endif 638 639 default: 640 break; 641 } 642 err = kNoErr; 643 644 exit: 645 return( err ); 646 } 647 648 //=========================================================================================================================== 649 // DebugPrintAssert 650 // 651 // Warning: This routine relies on several of the strings being string constants that will exist forever because the 652 // underlying logMsg API that does the printing is asynchronous so it cannot use temporary/stack-based 653 // pointer variables (e.g. local strings). The debug macros that invoke this function only use constant 654 // constant strings, but if this function is invoked directly from other places, it must use constant strings. 655 //=========================================================================================================================== 656 657 DEBUG_EXPORT void 658 DebugPrintAssert( 659 int_least32_t inErrorCode, 660 const char * inAssertString, 661 const char * inMessage, 662 const char * inFilename, 663 int_least32_t inLineNumber, 664 const char * inFunction ) 665 { 666 // Skip if the level is not in the enabled range.. 667 668 if( ( kDebugLevelAssert < gDebugPrintLevelMin ) || ( kDebugLevelAssert > gDebugPrintLevelMax ) ) 669 { 670 return; 671 } 672 673 if( inErrorCode != 0 ) 674 { 675 DebugPrintF( 676 kDebugLevelAssert, 677 "\n" 678 "[ASSERT] error: %ld (%m)\n" 679 "[ASSERT] where: \"%s\", line %ld, \"%s\"\n" 680 "\n", 681 inErrorCode, inErrorCode, 682 inFilename ? inFilename : "", 683 inLineNumber, 684 inFunction ? inFunction : "" ); 685 } 686 else 687 { 688 DebugPrintF( 689 kDebugLevelAssert, 690 "\n" 691 "[ASSERT] assert: \"%s\" %s\n" 692 "[ASSERT] where: \"%s\", line %ld, \"%s\"\n" 693 "\n", 694 inAssertString ? inAssertString : "", 695 inMessage ? inMessage : "", 696 inFilename ? inFilename : "", 697 inLineNumber, 698 inFunction ? inFunction : "" ); 699 } 700 701 // Break into the debugger if enabled. 702 703 #if( TARGET_OS_WIN32 ) 704 if( gDebugBreakLevel <= kDebugLevelAssert ) 705 { 706 if( IsDebuggerPresent() ) 707 { 708 DebugBreak(); 709 } 710 } 711 #endif 712 } 713 714 #if 0 715 #pragma mark - 716 #endif 717 718 #if( DEBUG_FPRINTF_ENABLED ) 719 //=========================================================================================================================== 720 // DebugFPrintFInit 721 //=========================================================================================================================== 722 723 static OSStatus DebugFPrintFInit( DebugOutputTypeFlags inFlags, const char *inFilename ) 724 { 725 OSStatus err; 726 DebugOutputTypeFlags typeFlags; 727 728 typeFlags = inFlags & kDebugOutputTypeFlagsTypeMask; 729 if( typeFlags == kDebugOutputTypeFlagsStdOut ) 730 { 731 #if( TARGET_OS_WIN32 ) 732 DebugWinEnableConsole(); 733 #endif 734 735 gDebugFPrintFFile = stdout; 736 } 737 else if( typeFlags == kDebugOutputTypeFlagsStdErr ) 738 { 739 #if( TARGET_OS_WIN32 ) 740 DebugWinEnableConsole(); 741 #endif 742 743 gDebugFPrintFFile = stdout; 744 } 745 else if( typeFlags == kDebugOutputTypeFlagsFile ) 746 { 747 require_action_quiet( inFilename && ( *inFilename != '\0' ), exit, err = kOpenErr ); 748 749 gDebugFPrintFFile = fopen( inFilename, "a" ); 750 require_action_quiet( gDebugFPrintFFile, exit, err = kOpenErr ); 751 } 752 else 753 { 754 err = kParamErr; 755 goto exit; 756 } 757 err = kNoErr; 758 759 exit: 760 return( err ); 761 } 762 763 //=========================================================================================================================== 764 // DebugFPrintFPrint 765 //=========================================================================================================================== 766 767 static void DebugFPrintFPrint( char *inData, size_t inSize ) 768 { 769 char * p; 770 char * q; 771 772 // Convert \r to \n. fprintf will interpret \n and convert to whatever is appropriate for the platform. 773 774 p = inData; 775 q = p + inSize; 776 while( p < q ) 777 { 778 if( *p == '\r' ) 779 { 780 *p = '\n'; 781 } 782 ++p; 783 } 784 785 // Write the data and flush. 786 787 if( gDebugFPrintFFile ) 788 { 789 fprintf( gDebugFPrintFFile, "%.*s", (int) inSize, inData ); 790 fflush( gDebugFPrintFFile ); 791 } 792 } 793 #endif // DEBUG_FPRINTF_ENABLED 794 795 #if( DEBUG_IDEBUG_ENABLED ) 796 //=========================================================================================================================== 797 // DebugiDebugInit 798 //=========================================================================================================================== 799 800 static OSStatus DebugiDebugInit( void ) 801 { 802 OSStatus err; 803 804 #if( TARGET_API_MAC_OSX_KERNEL ) 805 806 extern uint32_t * _giDebugReserved1; 807 808 // Emulate the iDebugSetOutputType macro in iDebugServices.h. 809 // Note: This is not thread safe, but neither is iDebugServices.h nor iDebugKext. 810 811 if( !_giDebugReserved1 ) 812 { 813 _giDebugReserved1 = (uint32_t *) IOMalloc( sizeof( uint32_t ) ); 814 require_action_quiet( _giDebugReserved1, exit, err = kNoMemoryErr ); 815 } 816 *_giDebugReserved1 = 0x00010000U; 817 err = kNoErr; 818 exit: 819 #else 820 821 __private_extern__ void iDebugSetOutputTypeInternal( uint32_t inType ); 822 823 iDebugSetOutputTypeInternal( 0x00010000U ); 824 err = kNoErr; 825 826 #endif 827 828 return( err ); 829 } 830 831 //=========================================================================================================================== 832 // DebugiDebugPrint 833 //=========================================================================================================================== 834 835 static void DebugiDebugPrint( char *inData, size_t inSize ) 836 { 837 #if( TARGET_API_MAC_OSX_KERNEL ) 838 839 // Locally declared here so we do not need to include iDebugKext.h. 840 // Note: IOKit uses a global namespace for all code and only a partial link occurs at build time. When the 841 // KEXT is loaded, the runtime linker will link in this extern'd symbol (assuming iDebug is present). 842 // _giDebugLogInternal is actually part of IOKit proper so this should link even if iDebug is not present. 843 844 typedef void ( *iDebugLogFunctionPtr )( uint32_t inLevel, uint32_t inTag, const char *inFormat, ... ); 845 846 extern iDebugLogFunctionPtr _giDebugLogInternal; 847 848 if( _giDebugLogInternal ) 849 { 850 _giDebugLogInternal( 0, 0, "%.*s", (int) inSize, inData ); 851 } 852 853 #else 854 855 __private_extern__ void iDebugLogInternal( uint32_t inLevel, uint32_t inTag, const char *inFormat, ... ); 856 857 iDebugLogInternal( 0, 0, "%.*s", (int) inSize, inData ); 858 859 #endif 860 } 861 #endif 862 863 #if( DEBUG_KPRINTF_ENABLED ) 864 //=========================================================================================================================== 865 // DebugKPrintFPrint 866 //=========================================================================================================================== 867 868 static void DebugKPrintFPrint( char *inData, size_t inSize ) 869 { 870 extern void kprintf( const char *inFormat, ... ); 871 872 kprintf( "%.*s", (int) inSize, inData ); 873 } 874 #endif 875 876 #if( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 877 //=========================================================================================================================== 878 // DebugMacOSXIOLogPrint 879 //=========================================================================================================================== 880 881 static void DebugMacOSXIOLogPrint( char *inData, size_t inSize ) 882 { 883 extern void IOLog( const char *inFormat, ... ); 884 885 IOLog( "%.*s", (int) inSize, inData ); 886 } 887 #endif 888 889 #if( TARGET_OS_MAC ) 890 //=========================================================================================================================== 891 // DebugMacOSXLogInit 892 //=========================================================================================================================== 893 894 static OSStatus DebugMacOSXLogInit( void ) 895 { 896 OSStatus err; 897 CFStringRef path; 898 CFURLRef url; 899 CFBundleRef bundle; 900 CFStringRef functionName; 901 void * functionPtr; 902 903 bundle = NULL; 904 905 // Create a bundle reference for System.framework. 906 907 path = CFSTR( "/System/Library/Frameworks/System.framework" ); 908 url = CFURLCreateWithFileSystemPath( NULL, path, kCFURLPOSIXPathStyle, true ); 909 require_action_quiet( url, exit, err = memFullErr ); 910 911 bundle = CFBundleCreate( NULL, url ); 912 CFRelease( url ); 913 require_action_quiet( bundle, exit, err = memFullErr ); 914 915 // Get a ptr to the system's "printf" function from System.framework. 916 917 functionName = CFSTR( "printf" ); 918 functionPtr = CFBundleGetFunctionPointerForName( bundle, functionName ); 919 require_action_quiet( functionPtr, exit, err = memFullErr ); 920 921 // Success! Note: The bundle cannot be released because it would invalidate the function ptr. 922 923 gDebugMacOSXLogFunction = (DebugMacOSXLogFunctionPtr) functionPtr; 924 bundle = NULL; 925 err = noErr; 926 927 exit: 928 if( bundle ) 929 { 930 CFRelease( bundle ); 931 } 932 return( err ); 933 } 934 935 //=========================================================================================================================== 936 // DebugMacOSXLogPrint 937 //=========================================================================================================================== 938 939 static void DebugMacOSXLogPrint( char *inData, size_t inSize ) 940 { 941 if( gDebugMacOSXLogFunction ) 942 { 943 gDebugMacOSXLogFunction( "%.*s", (int) inSize, inData ); 944 } 945 } 946 #endif 947 948 #if( TARGET_OS_WIN32 ) 949 //=========================================================================================================================== 950 // DebugWindowsDebuggerPrint 951 //=========================================================================================================================== 952 953 void DebugWindowsDebuggerPrint( char *inData, size_t inSize ) 954 { 955 TCHAR buffer[ 512 ]; 956 const char * src; 957 const char * end; 958 TCHAR * dst; 959 char c; 960 961 // Copy locally and null terminate the string. This also converts from char to TCHAR in case we are 962 // building with UNICODE enabled since the input is always char. Also convert \r to \n in the process. 963 964 src = inData; 965 if( inSize >= sizeof_array( buffer ) ) 966 { 967 inSize = sizeof_array( buffer ) - 1; 968 } 969 end = src + inSize; 970 dst = buffer; 971 while( src < end ) 972 { 973 c = *src++; 974 if( c == '\r' ) 975 { 976 c = '\n'; 977 } 978 *dst++ = (TCHAR) c; 979 } 980 *dst = 0; 981 982 // Print out the string to the debugger. 983 984 OutputDebugString( buffer ); 985 } 986 #endif 987 988 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 989 //=========================================================================================================================== 990 // DebugWindowsEventLogInit 991 //=========================================================================================================================== 992 993 static OSStatus DebugWindowsEventLogInit( const char *inName, HMODULE inModule ) 994 { 995 OSStatus err; 996 HKEY key; 997 TCHAR name[ 128 ]; 998 const char * src; 999 TCHAR path[ MAX_PATH ]; 1000 size_t size; 1001 DWORD typesSupported; 1002 DWORD n; 1003 1004 key = NULL; 1005 1006 // Use a default name if needed then convert the name to TCHARs so it works on ANSI or Unicode builds. 1007 1008 if( !inName || ( *inName == '\0' ) ) 1009 { 1010 inName = "DefaultApp"; 1011 } 1012 DebugWinCharToTCharString( inName, kSizeCString, name, sizeof( name ), NULL ); 1013 1014 // Build the path string using the fixed registry path and app name. 1015 1016 src = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"; 1017 DebugWinCharToTCharString( src, kSizeCString, path, sizeof_array( path ), &size ); 1018 DebugWinCharToTCharString( inName, kSizeCString, path + size, sizeof_array( path ) - size, NULL ); 1019 1020 // Add/Open the source name as a sub-key under the Application key in the EventLog registry key. 1021 1022 err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL ); 1023 require_noerr_quiet( err, exit ); 1024 1025 // Set the path in the EventMessageFile subkey. Add 1 to the TCHAR count to include the null terminator. 1026 1027 n = GetModuleFileName( inModule, path, sizeof_array( path ) ); 1028 err = translate_errno( n > 0, (OSStatus) GetLastError(), kParamErr ); 1029 require_noerr_quiet( err, exit ); 1030 n += 1; 1031 n *= sizeof( TCHAR ); 1032 1033 err = RegSetValueEx( key, TEXT( "EventMessageFile" ), 0, REG_EXPAND_SZ, (const LPBYTE) path, n ); 1034 require_noerr_quiet( err, exit ); 1035 1036 // Set the supported event types in the TypesSupported subkey. 1037 1038 typesSupported = EVENTLOG_SUCCESS | EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE | 1039 EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE; 1040 err = RegSetValueEx( key, TEXT( "TypesSupported" ), 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) ); 1041 require_noerr_quiet( err, exit ); 1042 1043 // Set up the event source. 1044 1045 gDebugWindowsEventLogEventSource = RegisterEventSource( NULL, name ); 1046 err = translate_errno( gDebugWindowsEventLogEventSource, (OSStatus) GetLastError(), kParamErr ); 1047 require_noerr_quiet( err, exit ); 1048 1049 exit: 1050 if( key ) 1051 { 1052 RegCloseKey( key ); 1053 } 1054 return( err ); 1055 } 1056 1057 //=========================================================================================================================== 1058 // DebugWindowsEventLogPrint 1059 //=========================================================================================================================== 1060 1061 static void DebugWindowsEventLogPrint( DebugLevel inLevel, char *inData, size_t inSize ) 1062 { 1063 WORD type; 1064 TCHAR buffer[ 512 ]; 1065 const char * src; 1066 const char * end; 1067 TCHAR * dst; 1068 char c; 1069 const TCHAR * array[ 1 ]; 1070 1071 // Map the debug level to a Windows EventLog type. 1072 1073 if( inLevel <= kDebugLevelNotice ) 1074 { 1075 type = EVENTLOG_INFORMATION_TYPE; 1076 } 1077 else if( inLevel <= kDebugLevelWarning ) 1078 { 1079 type = EVENTLOG_WARNING_TYPE; 1080 } 1081 else 1082 { 1083 type = EVENTLOG_ERROR_TYPE; 1084 } 1085 1086 // Copy locally and null terminate the string. This also converts from char to TCHAR in case we are 1087 // building with UNICODE enabled since the input is always char. Also convert \r to \n in the process. 1088 1089 src = inData; 1090 if( inSize >= sizeof_array( buffer ) ) 1091 { 1092 inSize = sizeof_array( buffer ) - 1; 1093 } 1094 end = src + inSize; 1095 dst = buffer; 1096 while( src < end ) 1097 { 1098 c = *src++; 1099 if( c == '\r' ) 1100 { 1101 c = '\n'; 1102 } 1103 *dst++ = (TCHAR) c; 1104 } 1105 *dst = 0; 1106 1107 // Add the the string to the event log. 1108 1109 array[ 0 ] = buffer; 1110 if( gDebugWindowsEventLogEventSource ) 1111 { 1112 ReportEvent( gDebugWindowsEventLogEventSource, type, 0, 0x20000001L, NULL, 1, 0, array, NULL ); 1113 } 1114 } 1115 #endif // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE 1116 1117 #if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 1118 //=========================================================================================================================== 1119 // DebugAssertOutputHandler 1120 //=========================================================================================================================== 1121 1122 static pascal void 1123 DebugAssertOutputHandler( 1124 OSType inComponentSignature, 1125 UInt32 inOptions, 1126 const char * inAssertString, 1127 const char * inExceptionString, 1128 const char * inErrorString, 1129 const char * inFileName, 1130 long inLineNumber, 1131 void * inValue, 1132 ConstStr255Param inOutputMsg ) 1133 { 1134 DEBUG_UNUSED( inComponentSignature ); 1135 DEBUG_UNUSED( inOptions ); 1136 DEBUG_UNUSED( inExceptionString ); 1137 DEBUG_UNUSED( inValue ); 1138 DEBUG_UNUSED( inOutputMsg ); 1139 1140 DebugPrintAssert( 0, inAssertString, inErrorString, inFileName, (int_least32_t) inLineNumber, "" ); 1141 } 1142 #endif 1143 1144 #if 0 1145 #pragma mark - 1146 #pragma mark == Utilities == 1147 #endif 1148 1149 //=========================================================================================================================== 1150 // DebugSNPrintF 1151 // 1152 // Stolen from mDNS.c's mDNS_snprintf/mDNS_vsnprintf with the following changes: 1153 // 1154 // Changed names to avoid name collisions with the mDNS versions. 1155 // Changed types to standard C types since mDNSEmbeddedAPI.h may not be available. 1156 // Conditionalized mDNS stuff so it can be used with or with mDNSEmbeddedAPI.h. 1157 // Added 64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb). 1158 // Added %@ - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription. 1159 // Added %.8a - FIbre Channel address. Arg=ptr to address. 1160 // Added %##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr. 1161 // Added %b - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc. 1162 // Added %C - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode. 1163 // Added %H - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size. 1164 // Added %#H - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size. 1165 // Added %m - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code args are the same as %d, %x, etc. 1166 // Added %S - UTF-16 string. Host order if no BOM. Precision is UTF-16 char count. BOM counts in any precision. Arg=ptr. 1167 // Added %#S - Big Endian UTF-16 string (unless BOM overrides). Otherwise the same as %S. 1168 // Added %##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise the same as %S. 1169 // Added %U - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID. 1170 //=========================================================================================================================== 1171 1172 DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...) 1173 { 1174 size_t length; 1175 1176 va_list ptr; 1177 va_start(ptr,fmt); 1178 length = DebugSNPrintFVAList(sbuffer, buflen, fmt, ptr); 1179 va_end(ptr); 1180 1181 return(length); 1182 } 1183 1184 //=========================================================================================================================== 1185 // DebugSNPrintFVAList - va_list version of DebugSNPrintF. See DebugSNPrintF for more info. 1186 //=========================================================================================================================== 1187 1188 DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg) 1189 { 1190 static const struct DebugSNPrintF_format 1191 { 1192 unsigned leftJustify : 1; 1193 unsigned forceSign : 1; 1194 unsigned zeroPad : 1; 1195 unsigned havePrecision : 1; 1196 unsigned hSize : 1; 1197 char lSize; 1198 char altForm; 1199 char sign; // +, - or space 1200 unsigned int fieldWidth; 1201 unsigned int precision; 1202 } DebugSNPrintF_format_default = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 1203 1204 size_t nwritten = 0; 1205 int c; 1206 if (buflen == 0) return(0); 1207 buflen--; // Pre-reserve one space in the buffer for the terminating nul 1208 if (buflen == 0) goto exit; 1209 1210 for (c = *fmt; c != 0; c = *++fmt) 1211 { 1212 if (c != '%') 1213 { 1214 *sbuffer++ = (char)c; 1215 if (++nwritten >= buflen) goto exit; 1216 } 1217 else 1218 { 1219 size_t i=0, j; 1220 // The mDNS Vsprintf Argument Conversion Buffer is used as a temporary holding area for 1221 // generating decimal numbers, hexdecimal numbers, IP addresses, domain name strings, etc. 1222 // The size needs to be enough for a 256-byte domain name plus some error text. 1223 #define mDNS_VACB_Size 300 1224 char mDNS_VACB[mDNS_VACB_Size]; 1225 #define mDNS_VACB_Lim (&mDNS_VACB[mDNS_VACB_Size]) 1226 #define mDNS_VACB_Remain(s) ((size_t)(mDNS_VACB_Lim - s)) 1227 char *s = mDNS_VACB_Lim; 1228 const char *digits = "0123456789ABCDEF"; 1229 struct DebugSNPrintF_format F = DebugSNPrintF_format_default; 1230 1231 for(;;) // decode flags 1232 { 1233 c = *++fmt; 1234 if (c == '-') F.leftJustify = 1; 1235 else if (c == '+') F.forceSign = 1; 1236 else if (c == ' ') F.sign = ' '; 1237 else if (c == '#') F.altForm++; 1238 else if (c == '0') F.zeroPad = 1; 1239 else break; 1240 } 1241 1242 if (c == '*') // decode field width 1243 { 1244 int f = va_arg(arg, int); 1245 if (f < 0) { f = -f; F.leftJustify = 1; } 1246 F.fieldWidth = (unsigned int)f; 1247 c = *++fmt; 1248 } 1249 else 1250 { 1251 for (; c >= '0' && c <= '9'; c = *++fmt) 1252 F.fieldWidth = (10 * F.fieldWidth) + (c - '0'); 1253 } 1254 1255 if (c == '.') // decode precision 1256 { 1257 if ((c = *++fmt) == '*') 1258 { F.precision = va_arg(arg, unsigned int); c = *++fmt; } 1259 else for (; c >= '0' && c <= '9'; c = *++fmt) 1260 F.precision = (10 * F.precision) + (c - '0'); 1261 F.havePrecision = 1; 1262 } 1263 1264 if (F.leftJustify) F.zeroPad = 0; 1265 1266 conv: 1267 switch (c) // perform appropriate conversion 1268 { 1269 #if TYPE_LONGLONG_NATIVE 1270 unsigned_long_long_compat n; 1271 unsigned_long_long_compat base; 1272 #else 1273 unsigned long n; 1274 unsigned long base; 1275 #endif 1276 case 'h' : F.hSize = 1; c = *++fmt; goto conv; 1277 case 'l' : // fall through 1278 case 'L' : F.lSize++; c = *++fmt; goto conv; 1279 case 'd' : 1280 case 'i' : base = 10; 1281 goto canBeSigned; 1282 case 'u' : base = 10; 1283 goto notSigned; 1284 case 'o' : base = 8; 1285 goto notSigned; 1286 case 'b' : base = 2; 1287 goto notSigned; 1288 case 'p' : n = va_arg(arg, uintptr_t); 1289 F.havePrecision = 1; 1290 F.precision = (sizeof(uintptr_t) == 4) ? 8 : 16; 1291 F.sign = 0; 1292 base = 16; 1293 c = 'x'; 1294 goto number; 1295 case 'x' : digits = "0123456789abcdef"; 1296 case 'X' : base = 16; 1297 goto notSigned; 1298 canBeSigned: 1299 #if TYPE_LONGLONG_NATIVE 1300 if (F.lSize == 1) n = (unsigned_long_long_compat)va_arg(arg, long); 1301 else if (F.lSize == 2) n = (unsigned_long_long_compat)va_arg(arg, long_long_compat); 1302 else n = (unsigned_long_long_compat)va_arg(arg, int); 1303 #else 1304 if (F.lSize == 1) n = (unsigned long)va_arg(arg, long); 1305 else if (F.lSize == 2) goto exit; 1306 else n = (unsigned long)va_arg(arg, int); 1307 #endif 1308 if (F.hSize) n = (short) n; 1309 #if TYPE_LONGLONG_NATIVE 1310 if ((long_long_compat) n < 0) { n = (unsigned_long_long_compat)-(long_long_compat)n; F.sign = '-'; } 1311 #else 1312 if ((long) n < 0) { n = (unsigned long)-(long)n; F.sign = '-'; } 1313 #endif 1314 else if (F.forceSign) F.sign = '+'; 1315 goto number; 1316 1317 notSigned: if (F.lSize == 1) n = va_arg(arg, unsigned long); 1318 else if (F.lSize == 2) 1319 { 1320 #if TYPE_LONGLONG_NATIVE 1321 n = va_arg(arg, unsigned_long_long_compat); 1322 #else 1323 goto exit; 1324 #endif 1325 } 1326 else n = va_arg(arg, unsigned int); 1327 if (F.hSize) n = (unsigned short) n; 1328 F.sign = 0; 1329 goto number; 1330 1331 number: if (!F.havePrecision) 1332 { 1333 if (F.zeroPad) 1334 { 1335 F.precision = F.fieldWidth; 1336 if (F.altForm) F.precision -= 2; 1337 if (F.sign) --F.precision; 1338 } 1339 if (F.precision < 1) F.precision = 1; 1340 } 1341 if (F.precision > mDNS_VACB_Size - 1) 1342 F.precision = mDNS_VACB_Size - 1; 1343 for (i = 0; n; n /= base, i++) *--s = (char)(digits[n % base]); 1344 for (; i < F.precision; i++) *--s = '0'; 1345 if (F.altForm) { *--s = (char)c; *--s = '0'; i += 2; } 1346 if (F.sign) { *--s = F.sign; i++; } 1347 break; 1348 1349 case 'a' : { 1350 unsigned char *a = va_arg(arg, unsigned char *); 1351 char pre[4] = ""; 1352 char post[32] = ""; 1353 if (!a) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; } 1354 else 1355 { 1356 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1357 if (F.altForm == 1) 1358 { 1359 #if(defined(MDNS_DEBUGMSGS)) 1360 mDNSAddr *ip = (mDNSAddr*)a; 1361 switch (ip->type) 1362 { 1363 case mDNSAddrType_IPv4: F.precision = 4; a = (unsigned char *)&ip->ip.v4; break; 1364 case mDNSAddrType_IPv6: F.precision = 16; a = (unsigned char *)&ip->ip.v6; break; 1365 default: F.precision = 0; break; 1366 } 1367 #else 1368 F.precision = 0; // mDNSEmbeddedAPI.h not included so no mDNSAddr support 1369 #endif 1370 } 1371 else if (F.altForm == 2) 1372 { 1373 #ifdef AF_INET 1374 const struct sockaddr *sa; 1375 unsigned char *port; 1376 sa = (const struct sockaddr*)a; 1377 switch (sa->sa_family) 1378 { 1379 case AF_INET: F.precision = 4; a = (unsigned char*)&((const struct sockaddr_in *)a)->sin_addr; 1380 port = (unsigned char*)&((const struct sockaddr_in *)sa)->sin_port; 1381 DebugSNPrintF(post, sizeof(post), ":%d", (port[0] << 8) | port[1]); break; 1382 #ifdef AF_INET6 1383 case AF_INET6: F.precision = 16; a = (unsigned char*)&((const struct sockaddr_in6 *)a)->sin6_addr; 1384 pre[0] = '['; pre[1] = '\0'; 1385 port = (unsigned char*)&((const struct sockaddr_in6 *)sa)->sin6_port; 1386 DebugSNPrintF(post, sizeof(post), "%%%d]:%d", 1387 (int)((const struct sockaddr_in6 *)sa)->sin6_scope_id, 1388 (port[0] << 8) | port[1]); break; 1389 #endif 1390 default: F.precision = 0; break; 1391 } 1392 #else 1393 F.precision = 0; // socket interfaces not included so no sockaddr support 1394 #endif 1395 } 1396 switch (F.precision) 1397 { 1398 case 4: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%d.%d.%d.%d%s", 1399 a[0], a[1], a[2], a[3], post); break; 1400 case 6: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X", 1401 a[0], a[1], a[2], a[3], a[4], a[5]); break; 1402 case 8: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", 1403 a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); break; 1404 case 16: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), 1405 "%s%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X%s", 1406 pre, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], 1407 a[9], a[10], a[11], a[12], a[13], a[14], a[15], post); break; 1408 default: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%s", "<< ERROR: Must specify address size " 1409 "(i.e. %.4a=IPv4, %.6a=Ethernet, %.8a=Fibre Channel %.16a=IPv6) >>"); break; 1410 } 1411 } 1412 } 1413 break; 1414 1415 case 'U' : { 1416 unsigned char *a = va_arg(arg, unsigned char *); 1417 if (!a) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; } 1418 else 1419 { 1420 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1421 i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 1422 *((uint32_t*) &a[0]), *((uint16_t*) &a[4]), *((uint16_t*) &a[6]), 1423 a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); break; 1424 } 1425 } 1426 break; 1427 1428 case 'c' : *--s = (char)va_arg(arg, int); i = 1; break; 1429 1430 case 'C' : if (F.lSize) n = va_arg(arg, unsigned long); 1431 else n = va_arg(arg, unsigned int); 1432 if (F.hSize) n = (unsigned short) n; 1433 c = (int)( n & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); 1434 c = (int)((n >> 8) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); 1435 c = (int)((n >> 16) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); 1436 c = (int)((n >> 24) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); 1437 i = 4; 1438 break; 1439 1440 case 's' : s = va_arg(arg, char *); 1441 if (!s) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; } 1442 else switch (F.altForm) 1443 { 1444 case 0: i=0; 1445 if (F.havePrecision) // C string 1446 { 1447 while((i < F.precision) && s[i]) i++; 1448 // Make sure we don't truncate in the middle of a UTF-8 character. 1449 // If the last character is part of a multi-byte UTF-8 character, back up to the start of it. 1450 j=0; 1451 while((i > 0) && ((c = s[i-1]) & 0x80)) { j++; i--; if((c & 0xC0) != 0x80) break; } 1452 // If the actual count of UTF-8 characters matches the encoded UTF-8 count, add it back. 1453 if((j > 1) && (j <= 6)) 1454 { 1455 int test = (0xFF << (8-j)) & 0xFF; 1456 int mask = test | (1 << ((8-j)-1)); 1457 if((c & mask) == test) i += j; 1458 } 1459 } 1460 else 1461 while(s[i]) i++; 1462 break; 1463 case 1: i = (unsigned char) *s++; break; // Pascal string 1464 case 2: { // DNS label-sequence name 1465 unsigned char *a = (unsigned char *)s; 1466 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1467 if (*a == 0) *s++ = '.'; // Special case for root DNS name 1468 while (*a) 1469 { 1470 if (*a > 63) { s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "<<INVALID LABEL LENGTH %u>>", *a); break; } 1471 if (s + *a >= &mDNS_VACB[254]) { s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "<<NAME TOO LONG>>"); break; } 1472 s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "%#s.", a); 1473 a += 1 + *a; 1474 } 1475 i = (size_t)(s - mDNS_VACB); 1476 s = mDNS_VACB; // Reset s back to the start of the buffer 1477 break; 1478 } 1479 } 1480 if (F.havePrecision && i > F.precision) // Make sure we don't truncate in the middle of a UTF-8 character 1481 { i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--; } 1482 break; 1483 1484 case 'S': { // UTF-16 string 1485 unsigned char *a = va_arg(arg, unsigned char *); 1486 uint16_t *u = (uint16_t*)a; 1487 if (!u) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; } 1488 if ((!F.havePrecision || F.precision)) 1489 { 1490 if ((a[0] == 0xFE) && (a[1] == 0xFF)) { F.altForm = 1; u += 1; a += 2; F.precision--; } // Big Endian 1491 else if ((a[0] == 0xFF) && (a[1] == 0xFE)) { F.altForm = 2; u += 1; a += 2; F.precision--; } // Little Endian 1492 } 1493 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1494 switch (F.altForm) 1495 { 1496 case 0: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Host Endian 1497 { c = u[i]; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; } 1498 break; 1499 case 1: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Big Endian 1500 { c = ((a[0] << 8) | a[1]) & 0xFF; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; a += 2; } 1501 break; 1502 case 2: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Little Endian 1503 { c = ((a[1] << 8) | a[0]) & 0xFF; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; a += 2; } 1504 break; 1505 } 1506 } 1507 s = mDNS_VACB; // Reset s back to the start of the buffer 1508 break; 1509 1510 #if TARGET_OS_MAC 1511 case '@': { // Cocoa/CoreFoundation object 1512 CFTypeRef cfObj; 1513 CFStringRef cfStr; 1514 cfObj = (CFTypeRef) va_arg(arg, void *); 1515 cfStr = (CFGetTypeID(cfObj) == CFStringGetTypeID()) ? (CFStringRef)CFRetain(cfObj) : CFCopyDescription(cfObj); 1516 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1517 if (cfStr) 1518 { 1519 CFRange range; 1520 CFIndex m; 1521 range = CFRangeMake(0, CFStringGetLength(cfStr)); 1522 m = 0; 1523 CFStringGetBytes(cfStr, range, kCFStringEncodingUTF8, '^', false, (UInt8*)mDNS_VACB, (CFIndex)sizeof(mDNS_VACB), &m); 1524 CFRelease(cfStr); 1525 i = (size_t) m; 1526 } 1527 else 1528 { 1529 i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%s", "ERROR: <invalid CF object>" ); 1530 } 1531 } 1532 if (F.havePrecision && i > F.precision) // Make sure we don't truncate in the middle of a UTF-8 character 1533 { i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--; } 1534 break; 1535 #endif 1536 1537 case 'm' : { // Error Message 1538 long err; 1539 if (F.lSize) err = va_arg(arg, long); 1540 else err = va_arg(arg, int); 1541 if (F.hSize) err = (short)err; 1542 DebugGetErrorString(err, mDNS_VACB, sizeof(mDNS_VACB)); 1543 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1544 for(i=0;s[i];i++) {} 1545 } 1546 break; 1547 1548 case 'H' : { // Hex Dump 1549 void *a = va_arg(arg, void *); 1550 size_t size = (size_t)va_arg(arg, int); 1551 size_t max = (size_t)va_arg(arg, int); 1552 DebugFlags flags = 1553 kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine | 1554 kDebugFlags8BitSeparator | kDebugFlagsNo32BitSeparator | 1555 kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount; 1556 if (F.altForm == 0) flags |= kDebugFlagsNoASCII; 1557 size = (max < size) ? max : size; 1558 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1559 i = DebugHexDump(kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, a, a, size, flags, mDNS_VACB, sizeof(mDNS_VACB)); 1560 } 1561 break; 1562 1563 case 'v' : { // Version 1564 uint32_t version; 1565 version = va_arg(arg, unsigned int); 1566 DebugNumVersionToString(version, mDNS_VACB); 1567 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1568 for(i=0;s[i];i++) {} 1569 } 1570 break; 1571 1572 case 'n' : s = va_arg(arg, char *); 1573 if (F.hSize) * (short *) s = (short)nwritten; 1574 else if (F.lSize) * (long *) s = (long)nwritten; 1575 else * (int *) s = (int)nwritten; 1576 continue; 1577 1578 default: s = mDNS_VACB; 1579 i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "<<UNKNOWN FORMAT CONVERSION CODE %%%c>>", c); 1580 1581 case '%' : *sbuffer++ = (char)c; 1582 if (++nwritten >= buflen) goto exit; 1583 break; 1584 } 1585 1586 if (i < F.fieldWidth && !F.leftJustify) // Pad on the left 1587 do { 1588 *sbuffer++ = ' '; 1589 if (++nwritten >= buflen) goto exit; 1590 } while (i < --F.fieldWidth); 1591 1592 if (i > buflen - nwritten) // Make sure we don't truncate in the middle of a UTF-8 character 1593 { i = buflen - nwritten; while (i>0 && (s[i] & 0xC0) == 0x80) i--; } 1594 for (j=0; j<i; j++) *sbuffer++ = *s++; // Write the converted result 1595 nwritten += i; 1596 if (nwritten >= buflen) goto exit; 1597 1598 for (; i < F.fieldWidth; i++) // Pad on the right 1599 { 1600 *sbuffer++ = ' '; 1601 if (++nwritten >= buflen) goto exit; 1602 } 1603 } 1604 } 1605 exit: 1606 *sbuffer++ = 0; 1607 return(nwritten); 1608 } 1609 1610 //=========================================================================================================================== 1611 // DebugGetErrorString 1612 //=========================================================================================================================== 1613 1614 DEBUG_EXPORT const char * DebugGetErrorString( int_least32_t inErrorCode, char *inBuffer, size_t inBufferSize ) 1615 { 1616 const char * s; 1617 char * dst; 1618 char * end; 1619 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 1620 char buffer[ 256 ]; 1621 #endif 1622 1623 switch( inErrorCode ) 1624 { 1625 #define CaseErrorString( X, STR ) case X: s = STR; break 1626 #define CaseErrorStringify( X ) case X: s = # X; break 1627 #define CaseErrorStringifyHardCode( VALUE, X ) case VALUE: s = # X; break 1628 1629 // General Errors 1630 1631 CaseErrorString( 0, "no error" ); 1632 CaseErrorString( 1, "in-progress/waiting" ); 1633 CaseErrorString( -1, "catch-all unknown error" ); 1634 1635 // ACP Errors 1636 1637 CaseErrorStringifyHardCode( -2, kACPBadRequestErr ); 1638 CaseErrorStringifyHardCode( -3, kACPNoMemoryErr ); 1639 CaseErrorStringifyHardCode( -4, kACPBadParamErr ); 1640 CaseErrorStringifyHardCode( -5, kACPNotFoundErr ); 1641 CaseErrorStringifyHardCode( -6, kACPBadChecksumErr ); 1642 CaseErrorStringifyHardCode( -7, kACPCommandNotHandledErr ); 1643 CaseErrorStringifyHardCode( -8, kACPNetworkErr ); 1644 CaseErrorStringifyHardCode( -9, kACPDuplicateCommandHandlerErr ); 1645 CaseErrorStringifyHardCode( -10, kACPUnknownPropertyErr ); 1646 CaseErrorStringifyHardCode( -11, kACPImmutablePropertyErr ); 1647 CaseErrorStringifyHardCode( -12, kACPBadPropertyValueErr ); 1648 CaseErrorStringifyHardCode( -13, kACPNoResourcesErr ); 1649 CaseErrorStringifyHardCode( -14, kACPBadOptionErr ); 1650 CaseErrorStringifyHardCode( -15, kACPBadSizeErr ); 1651 CaseErrorStringifyHardCode( -16, kACPBadPasswordErr ); 1652 CaseErrorStringifyHardCode( -17, kACPNotInitializedErr ); 1653 CaseErrorStringifyHardCode( -18, kACPNonReadablePropertyErr ); 1654 CaseErrorStringifyHardCode( -19, kACPBadVersionErr ); 1655 CaseErrorStringifyHardCode( -20, kACPBadSignatureErr ); 1656 CaseErrorStringifyHardCode( -21, kACPBadIndexErr ); 1657 CaseErrorStringifyHardCode( -22, kACPUnsupportedErr ); 1658 CaseErrorStringifyHardCode( -23, kACPInUseErr ); 1659 CaseErrorStringifyHardCode( -24, kACPParamCountErr ); 1660 CaseErrorStringifyHardCode( -25, kACPIDErr ); 1661 CaseErrorStringifyHardCode( -26, kACPFormatErr ); 1662 CaseErrorStringifyHardCode( -27, kACPUnknownUserErr ); 1663 CaseErrorStringifyHardCode( -28, kACPAccessDeniedErr ); 1664 CaseErrorStringifyHardCode( -29, kACPIncorrectFWErr ); 1665 1666 // Common Services Errors 1667 1668 CaseErrorStringify( kUnknownErr ); 1669 CaseErrorStringify( kOptionErr ); 1670 CaseErrorStringify( kSelectorErr ); 1671 CaseErrorStringify( kExecutionStateErr ); 1672 CaseErrorStringify( kPathErr ); 1673 CaseErrorStringify( kParamErr ); 1674 CaseErrorStringify( kParamCountErr ); 1675 CaseErrorStringify( kCommandErr ); 1676 CaseErrorStringify( kIDErr ); 1677 CaseErrorStringify( kStateErr ); 1678 CaseErrorStringify( kRangeErr ); 1679 CaseErrorStringify( kRequestErr ); 1680 CaseErrorStringify( kResponseErr ); 1681 CaseErrorStringify( kChecksumErr ); 1682 CaseErrorStringify( kNotHandledErr ); 1683 CaseErrorStringify( kVersionErr ); 1684 CaseErrorStringify( kSignatureErr ); 1685 CaseErrorStringify( kFormatErr ); 1686 CaseErrorStringify( kNotInitializedErr ); 1687 CaseErrorStringify( kAlreadyInitializedErr ); 1688 CaseErrorStringify( kNotInUseErr ); 1689 CaseErrorStringify( kInUseErr ); 1690 CaseErrorStringify( kTimeoutErr ); 1691 CaseErrorStringify( kCanceledErr ); 1692 CaseErrorStringify( kAlreadyCanceledErr ); 1693 CaseErrorStringify( kCannotCancelErr ); 1694 CaseErrorStringify( kDeletedErr ); 1695 CaseErrorStringify( kNotFoundErr ); 1696 CaseErrorStringify( kNoMemoryErr ); 1697 CaseErrorStringify( kNoResourcesErr ); 1698 CaseErrorStringify( kDuplicateErr ); 1699 CaseErrorStringify( kImmutableErr ); 1700 CaseErrorStringify( kUnsupportedDataErr ); 1701 CaseErrorStringify( kIntegrityErr ); 1702 CaseErrorStringify( kIncompatibleErr ); 1703 CaseErrorStringify( kUnsupportedErr ); 1704 CaseErrorStringify( kUnexpectedErr ); 1705 CaseErrorStringify( kValueErr ); 1706 CaseErrorStringify( kNotReadableErr ); 1707 CaseErrorStringify( kNotWritableErr ); 1708 CaseErrorStringify( kBadReferenceErr ); 1709 CaseErrorStringify( kFlagErr ); 1710 CaseErrorStringify( kMalformedErr ); 1711 CaseErrorStringify( kSizeErr ); 1712 CaseErrorStringify( kNameErr ); 1713 CaseErrorStringify( kNotReadyErr ); 1714 CaseErrorStringify( kReadErr ); 1715 CaseErrorStringify( kWriteErr ); 1716 CaseErrorStringify( kMismatchErr ); 1717 CaseErrorStringify( kDateErr ); 1718 CaseErrorStringify( kUnderrunErr ); 1719 CaseErrorStringify( kOverrunErr ); 1720 CaseErrorStringify( kEndingErr ); 1721 CaseErrorStringify( kConnectionErr ); 1722 CaseErrorStringify( kAuthenticationErr ); 1723 CaseErrorStringify( kOpenErr ); 1724 CaseErrorStringify( kTypeErr ); 1725 CaseErrorStringify( kSkipErr ); 1726 CaseErrorStringify( kNoAckErr ); 1727 CaseErrorStringify( kCollisionErr ); 1728 CaseErrorStringify( kBackoffErr ); 1729 CaseErrorStringify( kNoAddressAckErr ); 1730 CaseErrorStringify( kBusyErr ); 1731 CaseErrorStringify( kNoSpaceErr ); 1732 1733 // mDNS/DNS-SD Errors 1734 1735 CaseErrorStringifyHardCode( -65537, mStatus_UnknownErr ); 1736 CaseErrorStringifyHardCode( -65538, mStatus_NoSuchNameErr ); 1737 CaseErrorStringifyHardCode( -65539, mStatus_NoMemoryErr ); 1738 CaseErrorStringifyHardCode( -65540, mStatus_BadParamErr ); 1739 CaseErrorStringifyHardCode( -65541, mStatus_BadReferenceErr ); 1740 CaseErrorStringifyHardCode( -65542, mStatus_BadStateErr ); 1741 CaseErrorStringifyHardCode( -65543, mStatus_BadFlagsErr ); 1742 CaseErrorStringifyHardCode( -65544, mStatus_UnsupportedErr ); 1743 CaseErrorStringifyHardCode( -65545, mStatus_NotInitializedErr ); 1744 CaseErrorStringifyHardCode( -65546, mStatus_NoCache ); 1745 CaseErrorStringifyHardCode( -65547, mStatus_AlreadyRegistered ); 1746 CaseErrorStringifyHardCode( -65548, mStatus_NameConflict ); 1747 CaseErrorStringifyHardCode( -65549, mStatus_Invalid ); 1748 CaseErrorStringifyHardCode( -65550, mStatus_GrowCache ); 1749 CaseErrorStringifyHardCode( -65551, mStatus_BadInterfaceErr ); 1750 CaseErrorStringifyHardCode( -65552, mStatus_Incompatible ); 1751 CaseErrorStringifyHardCode( -65791, mStatus_ConfigChanged ); 1752 CaseErrorStringifyHardCode( -65792, mStatus_MemFree ); 1753 1754 // RSP Errors 1755 1756 CaseErrorStringifyHardCode( -400000, kRSPUnknownErr ); 1757 CaseErrorStringifyHardCode( -400050, kRSPParamErr ); 1758 CaseErrorStringifyHardCode( -400108, kRSPNoMemoryErr ); 1759 CaseErrorStringifyHardCode( -405246, kRSPRangeErr ); 1760 CaseErrorStringifyHardCode( -409057, kRSPSizeErr ); 1761 CaseErrorStringifyHardCode( -400200, kRSPHardwareErr ); 1762 CaseErrorStringifyHardCode( -401712, kRSPTimeoutErr ); 1763 CaseErrorStringifyHardCode( -402053, kRSPUnsupportedErr ); 1764 CaseErrorStringifyHardCode( -402419, kRSPIDErr ); 1765 CaseErrorStringifyHardCode( -403165, kRSPFlagErr ); 1766 CaseErrorString( -200000, "kRSPControllerStatusBase - 0x50" ); 1767 CaseErrorString( -200080, "kRSPCommandSucceededErr - 0x50" ); 1768 CaseErrorString( -200001, "kRSPCommandFailedErr - 0x01" ); 1769 CaseErrorString( -200051, "kRSPChecksumErr - 0x33" ); 1770 CaseErrorString( -200132, "kRSPCommandTimeoutErr - 0x84" ); 1771 CaseErrorString( -200034, "kRSPPasswordRequiredErr - 0x22 OBSOLETE" ); 1772 CaseErrorString( -200128, "kRSPCanceledErr - 0x02 Async" ); 1773 1774 // XML Errors 1775 1776 CaseErrorStringifyHardCode( -100043, kXMLNotFoundErr ); 1777 CaseErrorStringifyHardCode( -100050, kXMLParamErr ); 1778 CaseErrorStringifyHardCode( -100108, kXMLNoMemoryErr ); 1779 CaseErrorStringifyHardCode( -100206, kXMLFormatErr ); 1780 CaseErrorStringifyHardCode( -100586, kXMLNoRootElementErr ); 1781 CaseErrorStringifyHardCode( -101703, kXMLWrongDataTypeErr ); 1782 CaseErrorStringifyHardCode( -101726, kXMLKeyErr ); 1783 CaseErrorStringifyHardCode( -102053, kXMLUnsupportedErr ); 1784 CaseErrorStringifyHardCode( -102063, kXMLMissingElementErr ); 1785 CaseErrorStringifyHardCode( -103026, kXMLParseErr ); 1786 CaseErrorStringifyHardCode( -103159, kXMLBadDataErr ); 1787 CaseErrorStringifyHardCode( -103170, kXMLBadNameErr ); 1788 CaseErrorStringifyHardCode( -105246, kXMLRangeErr ); 1789 CaseErrorStringifyHardCode( -105251, kXMLUnknownElementErr ); 1790 CaseErrorStringifyHardCode( -108739, kXMLMalformedInputErr ); 1791 CaseErrorStringifyHardCode( -109057, kXMLBadSizeErr ); 1792 CaseErrorStringifyHardCode( -101730, kXMLMissingChildElementErr ); 1793 CaseErrorStringifyHardCode( -102107, kXMLMissingParentElementErr ); 1794 CaseErrorStringifyHardCode( -130587, kXMLNonRootElementErr ); 1795 CaseErrorStringifyHardCode( -102015, kXMLDateErr ); 1796 1797 #if( __MACH__ ) 1798 1799 // Mach Errors 1800 1801 CaseErrorStringifyHardCode( 0x00002000, MACH_MSG_IPC_SPACE ); 1802 CaseErrorStringifyHardCode( 0x00001000, MACH_MSG_VM_SPACE ); 1803 CaseErrorStringifyHardCode( 0x00000800, MACH_MSG_IPC_KERNEL ); 1804 CaseErrorStringifyHardCode( 0x00000400, MACH_MSG_VM_KERNEL ); 1805 CaseErrorStringifyHardCode( 0x10000001, MACH_SEND_IN_PROGRESS ); 1806 CaseErrorStringifyHardCode( 0x10000002, MACH_SEND_INVALID_DATA ); 1807 CaseErrorStringifyHardCode( 0x10000003, MACH_SEND_INVALID_DEST ); 1808 CaseErrorStringifyHardCode( 0x10000004, MACH_SEND_TIMED_OUT ); 1809 CaseErrorStringifyHardCode( 0x10000007, MACH_SEND_INTERRUPTED ); 1810 CaseErrorStringifyHardCode( 0x10000008, MACH_SEND_MSG_TOO_SMALL ); 1811 CaseErrorStringifyHardCode( 0x10000009, MACH_SEND_INVALID_REPLY ); 1812 CaseErrorStringifyHardCode( 0x1000000A, MACH_SEND_INVALID_RIGHT ); 1813 CaseErrorStringifyHardCode( 0x1000000B, MACH_SEND_INVALID_NOTIFY ); 1814 CaseErrorStringifyHardCode( 0x1000000C, MACH_SEND_INVALID_MEMORY ); 1815 CaseErrorStringifyHardCode( 0x1000000D, MACH_SEND_NO_BUFFER ); 1816 CaseErrorStringifyHardCode( 0x1000000E, MACH_SEND_TOO_LARGE ); 1817 CaseErrorStringifyHardCode( 0x1000000F, MACH_SEND_INVALID_TYPE ); 1818 CaseErrorStringifyHardCode( 0x10000010, MACH_SEND_INVALID_HEADER ); 1819 CaseErrorStringifyHardCode( 0x10000011, MACH_SEND_INVALID_TRAILER ); 1820 CaseErrorStringifyHardCode( 0x10000015, MACH_SEND_INVALID_RT_OOL_SIZE ); 1821 CaseErrorStringifyHardCode( 0x10004001, MACH_RCV_IN_PROGRESS ); 1822 CaseErrorStringifyHardCode( 0x10004002, MACH_RCV_INVALID_NAME ); 1823 CaseErrorStringifyHardCode( 0x10004003, MACH_RCV_TIMED_OUT ); 1824 CaseErrorStringifyHardCode( 0x10004004, MACH_RCV_TOO_LARGE ); 1825 CaseErrorStringifyHardCode( 0x10004005, MACH_RCV_INTERRUPTED ); 1826 CaseErrorStringifyHardCode( 0x10004006, MACH_RCV_PORT_CHANGED ); 1827 CaseErrorStringifyHardCode( 0x10004007, MACH_RCV_INVALID_NOTIFY ); 1828 CaseErrorStringifyHardCode( 0x10004008, MACH_RCV_INVALID_DATA ); 1829 CaseErrorStringifyHardCode( 0x10004009, MACH_RCV_PORT_DIED ); 1830 CaseErrorStringifyHardCode( 0x1000400A, MACH_RCV_IN_SET ); 1831 CaseErrorStringifyHardCode( 0x1000400B, MACH_RCV_HEADER_ERROR ); 1832 CaseErrorStringifyHardCode( 0x1000400C, MACH_RCV_BODY_ERROR ); 1833 CaseErrorStringifyHardCode( 0x1000400D, MACH_RCV_INVALID_TYPE ); 1834 CaseErrorStringifyHardCode( 0x1000400E, MACH_RCV_SCATTER_SMALL ); 1835 CaseErrorStringifyHardCode( 0x1000400F, MACH_RCV_INVALID_TRAILER ); 1836 CaseErrorStringifyHardCode( 0x10004011, MACH_RCV_IN_PROGRESS_TIMED ); 1837 1838 // Mach OSReturn Errors 1839 1840 CaseErrorStringifyHardCode( 0xDC000001, kOSReturnError ); 1841 CaseErrorStringifyHardCode( 0xDC004001, kOSMetaClassInternal ); 1842 CaseErrorStringifyHardCode( 0xDC004002, kOSMetaClassHasInstances ); 1843 CaseErrorStringifyHardCode( 0xDC004003, kOSMetaClassNoInit ); 1844 CaseErrorStringifyHardCode( 0xDC004004, kOSMetaClassNoTempData ); 1845 CaseErrorStringifyHardCode( 0xDC004005, kOSMetaClassNoDicts ); 1846 CaseErrorStringifyHardCode( 0xDC004006, kOSMetaClassNoKModSet ); 1847 CaseErrorStringifyHardCode( 0xDC004007, kOSMetaClassNoInsKModSet ); 1848 CaseErrorStringifyHardCode( 0xDC004008, kOSMetaClassNoSuper ); 1849 CaseErrorStringifyHardCode( 0xDC004009, kOSMetaClassInstNoSuper ); 1850 CaseErrorStringifyHardCode( 0xDC00400A, kOSMetaClassDuplicateClass ); 1851 1852 // IOKit Errors 1853 1854 CaseErrorStringifyHardCode( 0xE00002BC, kIOReturnError ); 1855 CaseErrorStringifyHardCode( 0xE00002BD, kIOReturnNoMemory ); 1856 CaseErrorStringifyHardCode( 0xE00002BE, kIOReturnNoResources ); 1857 CaseErrorStringifyHardCode( 0xE00002BF, kIOReturnIPCError ); 1858 CaseErrorStringifyHardCode( 0xE00002C0, kIOReturnNoDevice ); 1859 CaseErrorStringifyHardCode( 0xE00002C1, kIOReturnNotPrivileged ); 1860 CaseErrorStringifyHardCode( 0xE00002C2, kIOReturnBadArgument ); 1861 CaseErrorStringifyHardCode( 0xE00002C3, kIOReturnLockedRead ); 1862 CaseErrorStringifyHardCode( 0xE00002C4, kIOReturnLockedWrite ); 1863 CaseErrorStringifyHardCode( 0xE00002C5, kIOReturnExclusiveAccess ); 1864 CaseErrorStringifyHardCode( 0xE00002C6, kIOReturnBadMessageID ); 1865 CaseErrorStringifyHardCode( 0xE00002C7, kIOReturnUnsupported ); 1866 CaseErrorStringifyHardCode( 0xE00002C8, kIOReturnVMError ); 1867 CaseErrorStringifyHardCode( 0xE00002C9, kIOReturnInternalError ); 1868 CaseErrorStringifyHardCode( 0xE00002CA, kIOReturnIOError ); 1869 CaseErrorStringifyHardCode( 0xE00002CC, kIOReturnCannotLock ); 1870 CaseErrorStringifyHardCode( 0xE00002CD, kIOReturnNotOpen ); 1871 CaseErrorStringifyHardCode( 0xE00002CE, kIOReturnNotReadable ); 1872 CaseErrorStringifyHardCode( 0xE00002CF, kIOReturnNotWritable ); 1873 CaseErrorStringifyHardCode( 0xE00002D0, kIOReturnNotAligned ); 1874 CaseErrorStringifyHardCode( 0xE00002D1, kIOReturnBadMedia ); 1875 CaseErrorStringifyHardCode( 0xE00002D2, kIOReturnStillOpen ); 1876 CaseErrorStringifyHardCode( 0xE00002D3, kIOReturnRLDError ); 1877 CaseErrorStringifyHardCode( 0xE00002D4, kIOReturnDMAError ); 1878 CaseErrorStringifyHardCode( 0xE00002D5, kIOReturnBusy ); 1879 CaseErrorStringifyHardCode( 0xE00002D6, kIOReturnTimeout ); 1880 CaseErrorStringifyHardCode( 0xE00002D7, kIOReturnOffline ); 1881 CaseErrorStringifyHardCode( 0xE00002D8, kIOReturnNotReady ); 1882 CaseErrorStringifyHardCode( 0xE00002D9, kIOReturnNotAttached ); 1883 CaseErrorStringifyHardCode( 0xE00002DA, kIOReturnNoChannels ); 1884 CaseErrorStringifyHardCode( 0xE00002DB, kIOReturnNoSpace ); 1885 CaseErrorStringifyHardCode( 0xE00002DD, kIOReturnPortExists ); 1886 CaseErrorStringifyHardCode( 0xE00002DE, kIOReturnCannotWire ); 1887 CaseErrorStringifyHardCode( 0xE00002DF, kIOReturnNoInterrupt ); 1888 CaseErrorStringifyHardCode( 0xE00002E0, kIOReturnNoFrames ); 1889 CaseErrorStringifyHardCode( 0xE00002E1, kIOReturnMessageTooLarge ); 1890 CaseErrorStringifyHardCode( 0xE00002E2, kIOReturnNotPermitted ); 1891 CaseErrorStringifyHardCode( 0xE00002E3, kIOReturnNoPower ); 1892 CaseErrorStringifyHardCode( 0xE00002E4, kIOReturnNoMedia ); 1893 CaseErrorStringifyHardCode( 0xE00002E5, kIOReturnUnformattedMedia ); 1894 CaseErrorStringifyHardCode( 0xE00002E6, kIOReturnUnsupportedMode ); 1895 CaseErrorStringifyHardCode( 0xE00002E7, kIOReturnUnderrun ); 1896 CaseErrorStringifyHardCode( 0xE00002E8, kIOReturnOverrun ); 1897 CaseErrorStringifyHardCode( 0xE00002E9, kIOReturnDeviceError ); 1898 CaseErrorStringifyHardCode( 0xE00002EA, kIOReturnNoCompletion ); 1899 CaseErrorStringifyHardCode( 0xE00002EB, kIOReturnAborted ); 1900 CaseErrorStringifyHardCode( 0xE00002EC, kIOReturnNoBandwidth ); 1901 CaseErrorStringifyHardCode( 0xE00002ED, kIOReturnNotResponding ); 1902 CaseErrorStringifyHardCode( 0xE00002EE, kIOReturnIsoTooOld ); 1903 CaseErrorStringifyHardCode( 0xE00002EF, kIOReturnIsoTooNew ); 1904 CaseErrorStringifyHardCode( 0xE00002F0, kIOReturnNotFound ); 1905 CaseErrorStringifyHardCode( 0xE0000001, kIOReturnInvalid ); 1906 1907 // IOKit FireWire Errors 1908 1909 CaseErrorStringifyHardCode( 0xE0008010, kIOFireWireResponseBase ); 1910 CaseErrorStringifyHardCode( 0xE0008020, kIOFireWireBusReset ); 1911 CaseErrorStringifyHardCode( 0xE0008001, kIOConfigNoEntry ); 1912 CaseErrorStringifyHardCode( 0xE0008002, kIOFireWirePending ); 1913 CaseErrorStringifyHardCode( 0xE0008003, kIOFireWireLastDCLToken ); 1914 CaseErrorStringifyHardCode( 0xE0008004, kIOFireWireConfigROMInvalid ); 1915 CaseErrorStringifyHardCode( 0xE0008005, kIOFireWireAlreadyRegistered ); 1916 CaseErrorStringifyHardCode( 0xE0008006, kIOFireWireMultipleTalkers ); 1917 CaseErrorStringifyHardCode( 0xE0008007, kIOFireWireChannelActive ); 1918 CaseErrorStringifyHardCode( 0xE0008008, kIOFireWireNoListenerOrTalker ); 1919 CaseErrorStringifyHardCode( 0xE0008009, kIOFireWireNoChannels ); 1920 CaseErrorStringifyHardCode( 0xE000800A, kIOFireWireChannelNotAvailable ); 1921 CaseErrorStringifyHardCode( 0xE000800B, kIOFireWireSeparateBus ); 1922 CaseErrorStringifyHardCode( 0xE000800C, kIOFireWireBadSelfIDs ); 1923 CaseErrorStringifyHardCode( 0xE000800D, kIOFireWireLowCableVoltage ); 1924 CaseErrorStringifyHardCode( 0xE000800E, kIOFireWireInsufficientPower ); 1925 CaseErrorStringifyHardCode( 0xE000800F, kIOFireWireOutOfTLabels ); 1926 CaseErrorStringifyHardCode( 0xE0008101, kIOFireWireBogusDCLProgram ); 1927 CaseErrorStringifyHardCode( 0xE0008102, kIOFireWireTalkingAndListening ); 1928 CaseErrorStringifyHardCode( 0xE0008103, kIOFireWireHardwareSlept ); 1929 CaseErrorStringifyHardCode( 0xE00087D0, kIOFWMessageServiceIsRequestingClose ); 1930 CaseErrorStringifyHardCode( 0xE00087D1, kIOFWMessagePowerStateChanged ); 1931 CaseErrorStringifyHardCode( 0xE00087D2, kIOFWMessageTopologyChanged ); 1932 1933 // IOKit USB Errors 1934 1935 CaseErrorStringifyHardCode( 0xE0004061, kIOUSBUnknownPipeErr ); 1936 CaseErrorStringifyHardCode( 0xE0004060, kIOUSBTooManyPipesErr ); 1937 CaseErrorStringifyHardCode( 0xE000405F, kIOUSBNoAsyncPortErr ); 1938 CaseErrorStringifyHardCode( 0xE000405E, kIOUSBNotEnoughPipesErr ); 1939 CaseErrorStringifyHardCode( 0xE000405D, kIOUSBNotEnoughPowerErr ); 1940 CaseErrorStringifyHardCode( 0xE0004057, kIOUSBEndpointNotFound ); 1941 CaseErrorStringifyHardCode( 0xE0004056, kIOUSBConfigNotFound ); 1942 CaseErrorStringifyHardCode( 0xE0004051, kIOUSBTransactionTimeout ); 1943 CaseErrorStringifyHardCode( 0xE0004050, kIOUSBTransactionReturned ); 1944 CaseErrorStringifyHardCode( 0xE000404F, kIOUSBPipeStalled ); 1945 CaseErrorStringifyHardCode( 0xE000404E, kIOUSBInterfaceNotFound ); 1946 CaseErrorStringifyHardCode( 0xE000404D, kIOUSBLowLatencyBufferNotPreviouslyAllocated ); 1947 CaseErrorStringifyHardCode( 0xE000404C, kIOUSBLowLatencyFrameListNotPreviouslyAllocated ); 1948 CaseErrorStringifyHardCode( 0xE000404B, kIOUSBHighSpeedSplitError ); 1949 CaseErrorStringifyHardCode( 0xE0004010, kIOUSBLinkErr ); 1950 CaseErrorStringifyHardCode( 0xE000400F, kIOUSBNotSent2Err ); 1951 CaseErrorStringifyHardCode( 0xE000400E, kIOUSBNotSent1Err ); 1952 CaseErrorStringifyHardCode( 0xE000400D, kIOUSBBufferUnderrunErr ); 1953 CaseErrorStringifyHardCode( 0xE000400C, kIOUSBBufferOverrunErr ); 1954 CaseErrorStringifyHardCode( 0xE000400B, kIOUSBReserved2Err ); 1955 CaseErrorStringifyHardCode( 0xE000400A, kIOUSBReserved1Err ); 1956 CaseErrorStringifyHardCode( 0xE0004007, kIOUSBWrongPIDErr ); 1957 CaseErrorStringifyHardCode( 0xE0004006, kIOUSBPIDCheckErr ); 1958 CaseErrorStringifyHardCode( 0xE0004003, kIOUSBDataToggleErr ); 1959 CaseErrorStringifyHardCode( 0xE0004002, kIOUSBBitstufErr ); 1960 CaseErrorStringifyHardCode( 0xE0004001, kIOUSBCRCErr ); 1961 1962 #endif // __MACH__ 1963 1964 // Other Errors 1965 1966 default: 1967 s = NULL; 1968 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 1969 if( inBuffer && ( inBufferSize > 0 ) ) 1970 { 1971 DWORD n; 1972 1973 n = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD) inErrorCode, 1974 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), buffer, sizeof( buffer ), NULL ); 1975 if( n > 0 ) 1976 { 1977 // Remove any trailing CR's or LF's since some messages have them. 1978 1979 while( ( n > 0 ) && isspace( ( (unsigned char *) buffer )[ n - 1 ] ) ) 1980 { 1981 buffer[ --n ] = '\0'; 1982 } 1983 s = buffer; 1984 } 1985 } 1986 #endif 1987 1988 if( !s ) 1989 { 1990 #if( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE ) 1991 s = strerror( inErrorCode ); 1992 #endif 1993 if( !s ) 1994 { 1995 s = "<unknown error code>"; 1996 } 1997 } 1998 break; 1999 } 2000 2001 // Copy the string to the output buffer. If no buffer is supplied or it is empty, return an empty string. 2002 2003 if( inBuffer && ( inBufferSize > 0 ) ) 2004 { 2005 dst = inBuffer; 2006 end = dst + ( inBufferSize - 1 ); 2007 while( ( ( end - dst ) > 0 ) && ( *s != '\0' ) ) 2008 { 2009 *dst++ = *s++; 2010 } 2011 *dst = '\0'; 2012 s = inBuffer; 2013 } 2014 return( s ); 2015 } 2016 2017 //=========================================================================================================================== 2018 // DebugHexDump 2019 //=========================================================================================================================== 2020 2021 DEBUG_EXPORT size_t 2022 DebugHexDump( 2023 DebugLevel inLevel, 2024 int inIndent, 2025 const char * inLabel, 2026 size_t inLabelSize, 2027 int inLabelMinWidth, 2028 const char * inType, 2029 size_t inTypeSize, 2030 const void * inDataStart, 2031 const void * inData, 2032 size_t inDataSize, 2033 DebugFlags inFlags, 2034 char * outBuffer, 2035 size_t inBufferSize ) 2036 { 2037 static const char kHexChars[] = "0123456789ABCDEF"; 2038 const uint8_t * start; 2039 const uint8_t * src; 2040 char * dst; 2041 char * end; 2042 size_t n; 2043 int offset; 2044 int width; 2045 const char * newline; 2046 char separator[ 8 ]; 2047 char * s; 2048 2049 DEBUG_UNUSED( inType ); 2050 DEBUG_UNUSED( inTypeSize ); 2051 2052 // Set up the function-wide variables. 2053 2054 if( inLabelSize == kSizeCString ) 2055 { 2056 inLabelSize = strlen( inLabel ); 2057 } 2058 start = (const uint8_t *) inData; 2059 src = start; 2060 dst = outBuffer; 2061 end = dst + inBufferSize; 2062 offset = (int)( (intptr_t) inData - (intptr_t) inDataStart ); 2063 width = ( (int) inLabelSize > inLabelMinWidth ) ? (int) inLabelSize : inLabelMinWidth; 2064 newline = ( inFlags & kDebugFlagsNoNewLine ) ? "" : "\n"; 2065 2066 // Set up the separator string. This is used to insert spaces on subsequent "lines" when not using newlines. 2067 2068 s = separator; 2069 if( inFlags & kDebugFlagsNoNewLine ) 2070 { 2071 if( inFlags & kDebugFlags8BitSeparator ) 2072 { 2073 *s++ = ' '; 2074 } 2075 if( inFlags & kDebugFlags16BitSeparator ) 2076 { 2077 *s++ = ' '; 2078 } 2079 if( !( inFlags & kDebugFlagsNo32BitSeparator ) ) 2080 { 2081 *s++ = ' '; 2082 } 2083 check( ( (size_t)( s - separator ) ) < sizeof( separator ) ); 2084 } 2085 *s = '\0'; 2086 2087 for( ;; ) 2088 { 2089 char prefixString[ 32 ]; 2090 char hexString[ 64 ]; 2091 char asciiString[ 32 ]; 2092 char byteCountString[ 32 ]; 2093 int c; 2094 size_t chunkSize; 2095 size_t i; 2096 2097 // If this is a label-only item (i.e. no data), print the label (accounting for prefix string spacing) and exit. 2098 2099 if( inDataSize == 0 ) 2100 { 2101 if( inLabel && ( inLabelSize > 0 ) ) 2102 { 2103 width = 0; 2104 if( !( inFlags & kDebugFlagsNoAddress ) ) 2105 { 2106 width += 8; // "00000000" 2107 if( !( inFlags & kDebugFlagsNoOffset ) ) 2108 { 2109 width += 1; // "+" 2110 } 2111 } 2112 if( inFlags & kDebugFlags32BitOffset ) 2113 { 2114 width += 8; // "00000000" 2115 } 2116 else if( !( inFlags & kDebugFlagsNoOffset ) ) 2117 { 2118 width += 4; // "0000" 2119 } 2120 2121 if( outBuffer ) 2122 { 2123 dst += DebugSNPrintF( dst, (size_t)( end - dst ), "%*s" "%-*.*s" "%.*s" "%s", 2124 width, "", 2125 ( width > 0 ) ? ": " : "", 2126 width, (int) inLabelSize, inLabel, 2127 newline ); 2128 } 2129 else 2130 { 2131 dst += DebugPrintF( inLevel, "%*s" "%-*.*s" "%.*s" "%s", 2132 width, "", 2133 ( width > 0 ) ? ": " : "", 2134 width, (int) inLabelSize, inLabel, 2135 newline ); 2136 } 2137 } 2138 break; 2139 } 2140 2141 // Build the prefix string. It will be in one of the following formats: 2142 // 2143 // 1) "00000000+0000[0000]" (address and offset) 2144 // 2) "00000000" (address only) 2145 // 3) "0000[0000]" (offset only) 2146 // 4) "" (no address or offset) 2147 // 2148 // Note: If we're printing multiple "lines", but not printing newlines, a space is used to separate. 2149 2150 s = prefixString; 2151 if( !( inFlags & kDebugFlagsNoAddress ) ) 2152 { 2153 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 28 ) & 0xF ]; 2154 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 24 ) & 0xF ]; 2155 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 20 ) & 0xF ]; 2156 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 16 ) & 0xF ]; 2157 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 12 ) & 0xF ]; 2158 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 8 ) & 0xF ]; 2159 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 4 ) & 0xF ]; 2160 *s++ = kHexChars[ ( (uintptr_t) src ) & 0xF ]; 2161 2162 if( !( inFlags & kDebugFlagsNoOffset ) ) 2163 { 2164 *s++ = '+'; 2165 } 2166 } 2167 if( !( inFlags & kDebugFlagsNoOffset ) ) 2168 { 2169 if( inFlags & kDebugFlags32BitOffset ) 2170 { 2171 *s++ = kHexChars[ ( offset >> 28 ) & 0xF ]; 2172 *s++ = kHexChars[ ( offset >> 24 ) & 0xF ]; 2173 *s++ = kHexChars[ ( offset >> 20 ) & 0xF ]; 2174 *s++ = kHexChars[ ( offset >> 16 ) & 0xF ]; 2175 } 2176 *s++ = kHexChars[ ( offset >> 12 ) & 0xF ]; 2177 *s++ = kHexChars[ ( offset >> 8 ) & 0xF ]; 2178 *s++ = kHexChars[ ( offset >> 4 ) & 0xF ]; 2179 *s++ = kHexChars[ offset & 0xF ]; 2180 } 2181 if( s != prefixString ) 2182 { 2183 *s++ = ':'; 2184 *s++ = ' '; 2185 } 2186 check( ( (size_t)( s - prefixString ) ) < sizeof( prefixString ) ); 2187 *s = '\0'; 2188 2189 // Build a hex string with a optional spaces after every 1, 2, and/or 4 bytes to make it easier to read. 2190 // Optionally pads the hex string with space to fill the full 16 byte range (so it lines up). 2191 2192 s = hexString; 2193 chunkSize = ( inDataSize < 16 ) ? inDataSize : 16; 2194 n = ( inFlags & kDebugFlagsNo16ByteHexPad ) ? chunkSize : 16; 2195 for( i = 0; i < n; ++i ) 2196 { 2197 if( ( inFlags & kDebugFlags8BitSeparator ) && ( i > 0 ) ) 2198 { 2199 *s++ = ' '; 2200 } 2201 if( ( inFlags & kDebugFlags16BitSeparator ) && ( i > 0 ) && ( ( i % 2 ) == 0 ) ) 2202 { 2203 *s++ = ' '; 2204 } 2205 if( !( inFlags & kDebugFlagsNo32BitSeparator ) && ( i > 0 ) && ( ( i % 4 ) == 0 ) ) 2206 { 2207 *s++ = ' '; 2208 } 2209 if( i < chunkSize ) 2210 { 2211 *s++ = kHexChars[ src[ i ] >> 4 ]; 2212 *s++ = kHexChars[ src[ i ] & 0xF ]; 2213 } 2214 else 2215 { 2216 *s++ = ' '; 2217 *s++ = ' '; 2218 } 2219 } 2220 check( ( (size_t)( s - hexString ) ) < sizeof( hexString ) ); 2221 *s = '\0'; 2222 2223 // Build a string with the ASCII version of the data (replaces non-printable characters with '^'). 2224 // Optionally pads the string with '`' to fill the full 16 byte range (so it lines up). 2225 2226 s = asciiString; 2227 if( !( inFlags & kDebugFlagsNoASCII ) ) 2228 { 2229 *s++ = ' '; 2230 *s++ = '|'; 2231 for( i = 0; i < n; ++i ) 2232 { 2233 if( i < chunkSize ) 2234 { 2235 c = src[ i ]; 2236 if( !DebugIsPrint( c ) ) 2237 { 2238 c = '^'; 2239 } 2240 } 2241 else 2242 { 2243 c = '`'; 2244 } 2245 *s++ = (char) c; 2246 } 2247 *s++ = '|'; 2248 check( ( (size_t)( s - asciiString ) ) < sizeof( asciiString ) ); 2249 } 2250 *s = '\0'; 2251 2252 // Build a string indicating how bytes are in the hex dump. Only printed on the first line. 2253 2254 s = byteCountString; 2255 if( !( inFlags & kDebugFlagsNoByteCount ) ) 2256 { 2257 if( src == start ) 2258 { 2259 s += DebugSNPrintF( s, sizeof( byteCountString ), " (%d bytes)", (int) inDataSize ); 2260 } 2261 } 2262 check( ( (size_t)( s - byteCountString ) ) < sizeof( byteCountString ) ); 2263 *s = '\0'; 2264 2265 // Build the entire line from all the pieces we've previously built. 2266 2267 if( outBuffer ) 2268 { 2269 if( src == start ) 2270 { 2271 dst += DebugSNPrintF( dst, (size_t)( end - dst ), 2272 "%*s" // Indention 2273 "%s" // Separator (only if needed) 2274 "%s" // Prefix 2275 "%-*.*s" // Label 2276 "%s" // Separator 2277 "%s" // Hex 2278 "%s" // ASCII 2279 "%s" // Byte Count 2280 "%s", // Newline 2281 inIndent, "", 2282 ( src != start ) ? separator : "", 2283 prefixString, 2284 width, (int) inLabelSize, inLabel ? inLabel : "", 2285 ( width > 0 ) ? " " : "", 2286 hexString, 2287 asciiString, 2288 byteCountString, 2289 newline ); 2290 } 2291 else 2292 { 2293 dst += DebugSNPrintF( dst, (size_t)( end - dst ), 2294 "%*s" // Indention 2295 "%s" // Separator (only if needed) 2296 "%s" // Prefix 2297 "%*s" // Label Spacing 2298 "%s" // Separator 2299 "%s" // Hex 2300 "%s" // ASCII 2301 "%s" // Byte Count 2302 "%s", // Newline 2303 inIndent, "", 2304 ( src != start ) ? separator : "", 2305 prefixString, 2306 width, "", 2307 ( width > 0 ) ? " " : "", 2308 hexString, 2309 asciiString, 2310 byteCountString, 2311 newline ); 2312 } 2313 } 2314 else 2315 { 2316 if( src == start ) 2317 { 2318 dst += DebugPrintF( inLevel, 2319 "%*s" // Indention 2320 "%s" // Separator (only if needed) 2321 "%s" // Prefix 2322 "%-*.*s" // Label 2323 "%s" // Separator 2324 "%s" // Hex 2325 "%s" // ASCII 2326 "%s" // Byte Count 2327 "%s", // Newline 2328 inIndent, "", 2329 ( src != start ) ? separator : "", 2330 prefixString, 2331 width, (int) inLabelSize, inLabel, 2332 ( width > 0 ) ? " " : "", 2333 hexString, 2334 asciiString, 2335 byteCountString, 2336 newline ); 2337 } 2338 else 2339 { 2340 dst += DebugPrintF( inLevel, 2341 "%*s" // Indention 2342 "%s" // Separator (only if needed) 2343 "%s" // Prefix 2344 "%*s" // Label Spacing 2345 "%s" // Separator 2346 "%s" // Hex 2347 "%s" // ASCII 2348 "%s" // Byte Count 2349 "%s", // Newline 2350 inIndent, "", 2351 ( src != start ) ? separator : "", 2352 prefixString, 2353 width, "", 2354 ( width > 0 ) ? " " : "", 2355 hexString, 2356 asciiString, 2357 byteCountString, 2358 newline ); 2359 } 2360 } 2361 2362 // Move to the next chunk. Exit if there is no more data. 2363 2364 offset += (int) chunkSize; 2365 src += chunkSize; 2366 inDataSize -= chunkSize; 2367 if( inDataSize == 0 ) 2368 { 2369 break; 2370 } 2371 } 2372 2373 // Note: The "dst - outBuffer" size calculation works even if "outBuffer" is NULL because it's all relative. 2374 2375 return( (size_t)( dst - outBuffer ) ); 2376 } 2377 2378 //=========================================================================================================================== 2379 // DebugNumVersionToString 2380 //=========================================================================================================================== 2381 2382 static char * DebugNumVersionToString( uint32_t inVersion, char *inString ) 2383 { 2384 char * s; 2385 uint8_t majorRev; 2386 uint8_t minor; 2387 uint8_t bugFix; 2388 uint8_t stage; 2389 uint8_t revision; 2390 2391 check( inString ); 2392 2393 majorRev = (uint8_t)( ( inVersion >> 24 ) & 0xFF ); 2394 minor = (uint8_t)( ( inVersion >> 20 ) & 0x0F ); 2395 bugFix = (uint8_t)( ( inVersion >> 16 ) & 0x0F ); 2396 stage = (uint8_t)( ( inVersion >> 8 ) & 0xFF ); 2397 revision = (uint8_t)( inVersion & 0xFF ); 2398 2399 // Convert the major, minor, and bugfix numbers. 2400 2401 s = inString; 2402 s += sprintf( s, "%u", majorRev ); 2403 s += sprintf( s, ".%u", minor ); 2404 if( bugFix != 0 ) 2405 { 2406 s += sprintf( s, ".%u", bugFix ); 2407 } 2408 2409 // Convert the version stage and non-release revision number. 2410 2411 switch( stage ) 2412 { 2413 case kVersionStageDevelopment: 2414 s += sprintf( s, "d%u", revision ); 2415 break; 2416 2417 case kVersionStageAlpha: 2418 s += sprintf( s, "a%u", revision ); 2419 break; 2420 2421 case kVersionStageBeta: 2422 s += sprintf( s, "b%u", revision ); 2423 break; 2424 2425 case kVersionStageFinal: 2426 2427 // A non-release revision of zero is a special case indicating the software is GM (at the golden master 2428 // stage) and therefore, the non-release revision should not be added to the string. 2429 2430 if( revision != 0 ) 2431 { 2432 s += sprintf( s, "f%u", revision ); 2433 } 2434 break; 2435 2436 default: 2437 dlog( kDebugLevelError, "invalid NumVersion stage (0x%02X)\n", stage ); 2438 break; 2439 } 2440 return( inString ); 2441 } 2442 2443 //=========================================================================================================================== 2444 // DebugTaskLevel 2445 //=========================================================================================================================== 2446 2447 DEBUG_EXPORT uint32_t DebugTaskLevel( void ) 2448 { 2449 uint32_t level; 2450 2451 level = 0; 2452 2453 #if( TARGET_OS_VXWORKS ) 2454 if( intContext() ) 2455 { 2456 level |= ( ( 1 << kDebugInterruptLevelShift ) & kDebugInterruptLevelMask ); 2457 } 2458 #endif 2459 2460 return( level ); 2461 } 2462 2463 #if( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 2464 //=========================================================================================================================== 2465 // DebugWinEnableConsole 2466 //=========================================================================================================================== 2467 2468 #pragma warning( disable:4311 ) 2469 2470 static void DebugWinEnableConsole( void ) 2471 { 2472 static bool sConsoleEnabled = false; 2473 BOOL result; 2474 int fileHandle; 2475 FILE * file; 2476 int err; 2477 2478 if( sConsoleEnabled ) 2479 { 2480 goto exit; 2481 } 2482 2483 // Create console window. 2484 2485 result = AllocConsole(); 2486 require_quiet( result, exit ); 2487 2488 // Redirect stdin to the console stdin. 2489 2490 fileHandle = _open_osfhandle( (long) GetStdHandle( STD_INPUT_HANDLE ), _O_TEXT ); 2491 2492 #if( defined( __MWERKS__ ) ) 2493 file = __handle_reopen( (unsigned long) fileHandle, "r", stdin ); 2494 require_quiet( file, exit ); 2495 #else 2496 file = _fdopen( fileHandle, "r" ); 2497 require_quiet( file, exit ); 2498 2499 *stdin = *file; 2500 #endif 2501 2502 err = setvbuf( stdin, NULL, _IONBF, 0 ); 2503 require_noerr_quiet( err, exit ); 2504 2505 // Redirect stdout to the console stdout. 2506 2507 fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT ); 2508 2509 #if( defined( __MWERKS__ ) ) 2510 file = __handle_reopen( (unsigned long) fileHandle, "w", stdout ); 2511 require_quiet( file, exit ); 2512 #else 2513 file = _fdopen( fileHandle, "w" ); 2514 require_quiet( file, exit ); 2515 2516 *stdout = *file; 2517 #endif 2518 2519 err = setvbuf( stdout, NULL, _IONBF, 0 ); 2520 require_noerr_quiet( err, exit ); 2521 2522 // Redirect stderr to the console stdout. 2523 2524 fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT ); 2525 2526 #if( defined( __MWERKS__ ) ) 2527 file = __handle_reopen( (unsigned long) fileHandle, "w", stderr ); 2528 require_quiet( file, exit ); 2529 #else 2530 file = _fdopen( fileHandle, "w" ); 2531 require_quiet( file, exit ); 2532 2533 *stderr = *file; 2534 #endif 2535 2536 err = setvbuf( stderr, NULL, _IONBF, 0 ); 2537 require_noerr_quiet( err, exit ); 2538 2539 sConsoleEnabled = true; 2540 2541 exit: 2542 return; 2543 } 2544 2545 #pragma warning( default:4311 ) 2546 2547 #endif // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE 2548 2549 #if( TARGET_OS_WIN32 ) 2550 //=========================================================================================================================== 2551 // DebugWinCharToTCharString 2552 //=========================================================================================================================== 2553 2554 static TCHAR * 2555 DebugWinCharToTCharString( 2556 const char * inCharString, 2557 size_t inCharCount, 2558 TCHAR * outTCharString, 2559 size_t inTCharCountMax, 2560 size_t * outTCharCount ) 2561 { 2562 const char * src; 2563 TCHAR * dst; 2564 TCHAR * end; 2565 2566 if( inCharCount == kSizeCString ) 2567 { 2568 inCharCount = strlen( inCharString ); 2569 } 2570 src = inCharString; 2571 dst = outTCharString; 2572 if( inTCharCountMax > 0 ) 2573 { 2574 inTCharCountMax -= 1; 2575 if( inTCharCountMax > inCharCount ) 2576 { 2577 inTCharCountMax = inCharCount; 2578 } 2579 2580 end = dst + inTCharCountMax; 2581 while( dst < end ) 2582 { 2583 *dst++ = (TCHAR) *src++; 2584 } 2585 *dst = 0; 2586 } 2587 if( outTCharCount ) 2588 { 2589 *outTCharCount = (size_t)( dst - outTCharString ); 2590 } 2591 return( outTCharString ); 2592 } 2593 #endif 2594 2595 #if 0 2596 #pragma mark - 2597 #pragma mark == Debugging == 2598 #endif 2599 2600 //=========================================================================================================================== 2601 // DebugServicesTest 2602 //=========================================================================================================================== 2603 2604 DEBUG_EXPORT OSStatus DebugServicesTest( void ) 2605 { 2606 OSStatus err; 2607 char s[ 512 ]; 2608 uint8_t * p; 2609 uint8_t data[] = 2610 { 2611 0x11, 0x22, 0x33, 0x44, 2612 0x55, 0x66, 2613 0x77, 0x88, 0x99, 0xAA, 2614 0xBB, 0xCC, 0xDD, 2615 0xEE, 2616 0xFF, 2617 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 2618 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 2619 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1 2620 }; 2621 2622 debug_initialize( kDebugOutputTypeMetaConsole ); 2623 2624 // check's 2625 2626 check( 0 && "SHOULD SEE: check" ); 2627 check( 1 && "SHOULD *NOT* SEE: check (valid)" ); 2628 check_string( 0, "SHOULD SEE: check_string" ); 2629 check_string( 1, "SHOULD *NOT* SEE: check_string (valid)" ); 2630 check_noerr( -123 ); 2631 check_noerr( 10038 ); 2632 check_noerr( 22 ); 2633 check_noerr( 0 ); 2634 check_noerr_string( -6712, "SHOULD SEE: check_noerr_string" ); 2635 check_noerr_string( 0, "SHOULD *NOT* SEE: check_noerr_string (valid)" ); 2636 check_translated_errno( 0 >= 0 && "SHOULD *NOT* SEE", -384, -999 ); 2637 check_translated_errno( -1 >= 0 && "SHOULD SEE", -384, -999 ); 2638 check_translated_errno( -1 >= 0 && "SHOULD SEE", 0, -999 ); 2639 check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 22, 10 ); 2640 check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10, 5, 10 ); 2641 check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10, 12, 6 ); 2642 check_ptr_overlap( "SHOULD SEE" ? 12 : 0, 6, 10, 10 ); 2643 check_ptr_overlap( "SHOULD SEE" ? 12 : 0, 10, 10, 10 ); 2644 check_ptr_overlap( "SHOULD *NOT* SEE" ? 22 : 0, 10, 10, 10 ); 2645 check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 20, 10 ); 2646 check_ptr_overlap( "SHOULD *NOT* SEE" ? 20 : 0, 10, 10, 10 ); 2647 2648 // require's 2649 2650 require( 0 && "SHOULD SEE", require1 ); 2651 { err = kResponseErr; goto exit; } 2652 require1: 2653 require( 1 && "SHOULD *NOT* SEE", require2 ); 2654 goto require2Good; 2655 require2: 2656 { err = kResponseErr; goto exit; } 2657 require2Good: 2658 require_string( 0 && "SHOULD SEE", require3, "SHOULD SEE: require_string" ); 2659 { err = kResponseErr; goto exit; } 2660 require3: 2661 require_string( 1 && "SHOULD *NOT* SEE", require4, "SHOULD *NOT* SEE: require_string (valid)" ); 2662 goto require4Good; 2663 require4: 2664 { err = kResponseErr; goto exit; } 2665 require4Good: 2666 require_quiet( 0 && "SHOULD SEE", require5 ); 2667 { err = kResponseErr; goto exit; } 2668 require5: 2669 require_quiet( 1 && "SHOULD *NOT* SEE", require6 ); 2670 goto require6Good; 2671 require6: 2672 { err = kResponseErr; goto exit; } 2673 require6Good: 2674 require_noerr( -1, require7 ); 2675 { err = kResponseErr; goto exit; } 2676 require7: 2677 require_noerr( 0, require8 ); 2678 goto require8Good; 2679 require8: 2680 { err = kResponseErr; goto exit; } 2681 require8Good: 2682 require_noerr_string( -2, require9, "SHOULD SEE: require_noerr_string"); 2683 { err = kResponseErr; goto exit; } 2684 require9: 2685 require_noerr_string( 0, require10, "SHOULD *NOT* SEE: require_noerr_string (valid)" ); 2686 goto require10Good; 2687 require10: 2688 { err = kResponseErr; goto exit; } 2689 require10Good: 2690 require_noerr_action_string( -3, require11, dlog( kDebugLevelMax, "action 1 (expected)\n" ), "require_noerr_action_string" ); 2691 { err = kResponseErr; goto exit; } 2692 require11: 2693 require_noerr_action_string( 0, require12, dlog( kDebugLevelMax, "action 2\n" ), "require_noerr_action_string (valid)" ); 2694 goto require12Good; 2695 require12: 2696 { err = kResponseErr; goto exit; } 2697 require12Good: 2698 require_noerr_quiet( -4, require13 ); 2699 { err = kResponseErr; goto exit; } 2700 require13: 2701 require_noerr_quiet( 0, require14 ); 2702 goto require14Good; 2703 require14: 2704 { err = kResponseErr; goto exit; } 2705 require14Good: 2706 require_noerr_action( -5, require15, dlog( kDebugLevelMax, "SHOULD SEE: action 3 (expected)\n" ) ); 2707 { err = kResponseErr; goto exit; } 2708 require15: 2709 require_noerr_action( 0, require16, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 4\n" ) ); 2710 goto require16Good; 2711 require16: 2712 { err = kResponseErr; goto exit; } 2713 require16Good: 2714 require_noerr_action_quiet( -4, require17, dlog( kDebugLevelMax, "SHOULD SEE: action 5 (expected)\n" ) ); 2715 { err = kResponseErr; goto exit; } 2716 require17: 2717 require_noerr_action_quiet( 0, require18, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 6\n" ) ); 2718 goto require18Good; 2719 require18: 2720 { err = kResponseErr; goto exit; } 2721 require18Good: 2722 require_action( 0 && "SHOULD SEE", require19, dlog( kDebugLevelMax, "SHOULD SEE: action 7 (expected)\n" ) ); 2723 { err = kResponseErr; goto exit; } 2724 require19: 2725 require_action( 1 && "SHOULD *NOT* SEE", require20, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 8\n" ) ); 2726 goto require20Good; 2727 require20: 2728 { err = kResponseErr; goto exit; } 2729 require20Good: 2730 require_action_quiet( 0, require21, dlog( kDebugLevelMax, "SHOULD SEE: action 9 (expected)\n" ) ); 2731 { err = kResponseErr; goto exit; } 2732 require21: 2733 require_action_quiet( 1, require22, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 10\n" ) ); 2734 goto require22Good; 2735 require22: 2736 { err = kResponseErr; goto exit; } 2737 require22Good: 2738 require_action_string( 0, require23, dlog( kDebugLevelMax, "SHOULD SEE: action 11 (expected)\n" ), "SHOULD SEE: require_action_string" ); 2739 { err = kResponseErr; goto exit; } 2740 require23: 2741 require_action_string( 1, require24, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 12\n" ), "SHOULD *NOT* SEE: require_action_string" ); 2742 goto require24Good; 2743 require24: 2744 { err = kResponseErr; goto exit; } 2745 require24Good: 2746 2747 #if( defined( __MWERKS__ ) ) 2748 #if( defined( __cplusplus ) && __option( exceptions ) ) 2749 #define COMPILER_HAS_EXCEPTIONS 1 2750 #else 2751 #define COMPILER_HAS_EXCEPTIONS 0 2752 #endif 2753 #else 2754 #if( defined( __cplusplus ) ) 2755 #define COMPILER_HAS_EXCEPTIONS 1 2756 #else 2757 #define COMPILER_HAS_EXCEPTIONS 0 2758 #endif 2759 #endif 2760 2761 #if( COMPILER_HAS_EXCEPTIONS ) 2762 try 2763 { 2764 require_throw( 1 && "SHOULD *NOT* SEE" ); 2765 require_throw( 0 && "SHOULD SEE" ); 2766 } 2767 catch( ... ) 2768 { 2769 goto require26Good; 2770 } 2771 { err = kResponseErr; goto exit; } 2772 require26Good: 2773 #endif 2774 2775 // translate_errno 2776 2777 err = translate_errno( 1 != -1, -123, -567 ); 2778 require( ( err == 0 ) && "SHOULD *NOT* SEE", exit ); 2779 2780 err = translate_errno( -1 != -1, -123, -567 ); 2781 require( ( err == -123 ) && "SHOULD *NOT* SEE", exit ); 2782 2783 err = translate_errno( -1 != -1, 0, -567 ); 2784 require( ( err == -567 ) && "SHOULD *NOT* SEE", exit ); 2785 2786 // debug_string 2787 2788 debug_string( "debug_string" ); 2789 2790 // DebugSNPrintF 2791 2792 DebugSNPrintF( s, sizeof( s ), "%d", 1234 ); 2793 require_action( strcmp( s, "1234" ) == 0, exit, err = -1 ); 2794 2795 DebugSNPrintF( s, sizeof( s ), "%X", 0x2345 ); 2796 require_action( strcmp( s, "2345" ) == 0, exit, err = -1 ); 2797 2798 DebugSNPrintF( s, sizeof( s ), "%#s", "\05test" ); 2799 require_action( strcmp( s, "test" ) == 0, exit, err = -1 ); 2800 2801 DebugSNPrintF( s, sizeof( s ), "%##s", "\03www\05apple\03com" ); 2802 require_action( strcmp( s, "www.apple.com." ) == 0, exit, err = -1 ); 2803 2804 DebugSNPrintF( s, sizeof( s ), "%ld", (long) INT32_C( 2147483647 ) ); 2805 require_action( strcmp( s, "2147483647" ) == 0, exit, err = -1 ); 2806 2807 DebugSNPrintF( s, sizeof( s ), "%lu", (unsigned long) UINT32_C( 4294967295 ) ); 2808 require_action( strcmp( s, "4294967295" ) == 0, exit, err = -1 ); 2809 2810 #if( TYPE_LONGLONG_NATIVE ) 2811 DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( 9223372036854775807 ) ); 2812 require_action( strcmp( s, "9223372036854775807" ) == 0, exit, err = -1 ); 2813 2814 DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( -9223372036854775807 ) ); 2815 require_action( strcmp( s, "-9223372036854775807" ) == 0, exit, err = -1 ); 2816 2817 DebugSNPrintF( s, sizeof( s ), "%llu", (unsigned_long_long_compat) UINT64_C( 18446744073709551615 ) ); 2818 require_action( strcmp( s, "18446744073709551615" ) == 0, exit, err = -1 ); 2819 #endif 2820 2821 DebugSNPrintF( s, sizeof( s ), "%lb", (unsigned long) binary_32( 01111011, 01111011, 01111011, 01111011 ) ); 2822 require_action( strcmp( s, "1111011011110110111101101111011" ) == 0, exit, err = -1 ); 2823 2824 DebugSNPrintF( s, sizeof( s ), "%C", 0x41624364 ); // 'AbCd' 2825 require_action( strcmp( s, "AbCd" ) == 0, exit, err = -1 ); 2826 2827 #if( defined( MDNS_DEBUGMSGS ) ) 2828 { 2829 mDNSAddr maddr; 2830 2831 memset( &maddr, 0, sizeof( maddr ) ); 2832 maddr.type = mDNSAddrType_IPv4; 2833 maddr.ip.v4.b[ 0 ] = 127; 2834 maddr.ip.v4.b[ 1 ] = 0; 2835 maddr.ip.v4.b[ 2 ] = 0; 2836 maddr.ip.v4.b[ 3 ] = 1; 2837 DebugSNPrintF( s, sizeof( s ), "%#a", &maddr ); 2838 require_action( strcmp( s, "127.0.0.1" ) == 0, exit, err = -1 ); 2839 2840 memset( &maddr, 0, sizeof( maddr ) ); 2841 maddr.type = mDNSAddrType_IPv6; 2842 maddr.ip.v6.b[ 0 ] = 0xFE; 2843 maddr.ip.v6.b[ 1 ] = 0x80; 2844 maddr.ip.v6.b[ 15 ] = 0x01; 2845 DebugSNPrintF( s, sizeof( s ), "%#a", &maddr ); 2846 require_action( strcmp( s, "FE80:0000:0000:0000:0000:0000:0000:0001" ) == 0, exit, err = -1 ); 2847 } 2848 #endif 2849 2850 #if( AF_INET ) 2851 { 2852 struct sockaddr_in sa4; 2853 2854 memset( &sa4, 0, sizeof( sa4 ) ); 2855 sa4.sin_family = AF_INET; 2856 p = (uint8_t *) &sa4.sin_port; 2857 p[ 0 ] = (uint8_t)( ( 80 >> 8 ) & 0xFF ); 2858 p[ 1 ] = (uint8_t)( 80 & 0xFF ); 2859 p = (uint8_t *) &sa4.sin_addr.s_addr; 2860 p[ 0 ] = (uint8_t)( ( INADDR_LOOPBACK >> 24 ) & 0xFF ); 2861 p[ 1 ] = (uint8_t)( ( INADDR_LOOPBACK >> 16 ) & 0xFF ); 2862 p[ 2 ] = (uint8_t)( ( INADDR_LOOPBACK >> 8 ) & 0xFF ); 2863 p[ 3 ] = (uint8_t)( INADDR_LOOPBACK & 0xFF ); 2864 DebugSNPrintF( s, sizeof( s ), "%##a", &sa4 ); 2865 require_action( strcmp( s, "127.0.0.1:80" ) == 0, exit, err = -1 ); 2866 } 2867 #endif 2868 2869 #if( AF_INET6 ) 2870 { 2871 struct sockaddr_in6 sa6; 2872 2873 memset( &sa6, 0, sizeof( sa6 ) ); 2874 sa6.sin6_family = AF_INET6; 2875 p = (uint8_t *) &sa6.sin6_port; 2876 p[ 0 ] = (uint8_t)( ( 80 >> 8 ) & 0xFF ); 2877 p[ 1 ] = (uint8_t)( 80 & 0xFF ); 2878 sa6.sin6_addr.s6_addr[ 0 ] = 0xFE; 2879 sa6.sin6_addr.s6_addr[ 1 ] = 0x80; 2880 sa6.sin6_addr.s6_addr[ 15 ] = 0x01; 2881 sa6.sin6_scope_id = 2; 2882 DebugSNPrintF( s, sizeof( s ), "%##a", &sa6 ); 2883 require_action( strcmp( s, "[FE80:0000:0000:0000:0000:0000:0000:0001%2]:80" ) == 0, exit, err = -1 ); 2884 } 2885 #endif 2886 2887 // Unicode 2888 2889 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes" ); 2890 require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr ); 2891 2892 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "test" ); 2893 require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr ); 2894 2895 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "testing" ); 2896 require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr ); 2897 2898 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9" ); 2899 require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); 2900 2901 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9ing" ); 2902 require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); 2903 2904 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes\xC3\xA9ing" ); 2905 require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr ); 2906 2907 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbf" ); 2908 require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); 2909 2910 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbfing" ); 2911 require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); 2912 2913 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbf" ); 2914 require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr ); 2915 2916 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbfing" ); 2917 require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr ); 2918 2919 DebugSNPrintF(s, sizeof(s), "%.*s", 7, "te\xC3\xA9\xed\x9f\xbfing" ); 2920 require_action( strcmp( s, "te\xC3\xA9\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); 2921 2922 DebugSNPrintF(s, sizeof(s), "%.*s", 6, "te\xC3\xA9\xed\x9f\xbfing" ); 2923 require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); 2924 2925 DebugSNPrintF(s, sizeof(s), "%.*s", 5, "te\xC3\xA9\xed\x9f\xbfing" ); 2926 require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); 2927 2928 #if( TARGET_RT_BIG_ENDIAN ) 2929 DebugSNPrintF( s, sizeof( s ), "%S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); 2930 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2931 #else 2932 DebugSNPrintF( s, sizeof( s ), "%S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); 2933 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2934 #endif 2935 2936 DebugSNPrintF( s, sizeof( s ), "%S", 2937 "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); // Big Endian BOM 2938 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2939 2940 DebugSNPrintF( s, sizeof( s ), "%S", 2941 "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian BOM 2942 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2943 2944 DebugSNPrintF( s, sizeof( s ), "%#S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); // Big Endian 2945 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2946 2947 DebugSNPrintF( s, sizeof( s ), "%##S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian 2948 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2949 2950 DebugSNPrintF( s, sizeof( s ), "%.*S", 2951 4, "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); // Big Endian BOM 2952 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2953 2954 DebugSNPrintF( s, sizeof( s ), "%.*S", 2955 4, "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); // Little Endian BOM 2956 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2957 2958 #if( TARGET_RT_BIG_ENDIAN ) 2959 DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); 2960 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2961 #else 2962 DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); 2963 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2964 #endif 2965 2966 DebugSNPrintF( s, sizeof( s ), "%#.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); // Big Endian 2967 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2968 2969 DebugSNPrintF( s, sizeof( s ), "%##.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); // Little Endian 2970 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2971 2972 // Misc 2973 2974 DebugSNPrintF( s, sizeof( s ), "%U", "\x10\xb8\xa7\x6b" "\xad\x9d" "\xd1\x11" "\x80\xb4" "\x00\xc0\x4f\xd4\x30\xc8" ); 2975 require_action( strcmp( s, "6ba7b810-9dad-11d1-80b4-00c04fd430c8" ) == 0, exit, err = -1 ); 2976 2977 DebugSNPrintF( s, sizeof( s ), "%m", 0 ); 2978 require_action( strcmp( s, "no error" ) == 0, exit, err = -1 ); 2979 2980 DebugSNPrintF( s, sizeof( s ), "%lm", (long) 0 ); 2981 require_action( strcmp( s, "no error" ) == 0, exit, err = -1 ); 2982 2983 DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8", 16, 16 ); 2984 DebugPrintF( kDebugLevelMax, "%s\n\n", s ); 2985 2986 DebugSNPrintF( s, sizeof( s ), "\"%H\"", 2987 "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8" 2988 "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8", 2989 32, 32 ); 2990 DebugPrintF( kDebugLevelMax, "%s\n\n", s ); 2991 2992 DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7", 2, 2 ); 2993 DebugPrintF( kDebugLevelMax, "%s\n\n", s ); 2994 2995 // Hex Dumps 2996 2997 s[ 0 ] = '\0'; 2998 DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), 2999 kDebugFlagsNone, s, sizeof( s ) ); 3000 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3001 3002 s[ 0 ] = '\0'; 3003 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 3004 kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) ); 3005 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3006 3007 s[ 0 ] = '\0'; 3008 DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), 3009 kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) ); 3010 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3011 3012 s[ 0 ] = '\0'; 3013 DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), 3014 kDebugFlagsNoAddress, s, sizeof( s ) ); 3015 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3016 3017 s[ 0 ] = '\0'; 3018 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 3019 kDebugFlagsNoOffset, s, sizeof( s ) ); 3020 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3021 3022 s[ 0 ] = '\0'; 3023 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 3024 kDebugFlagsNoAddress, s, sizeof( s ) ); 3025 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3026 3027 s[ 0 ] = '\0'; 3028 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 3029 kDebugFlagsNoOffset, s, sizeof( s ) ); 3030 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3031 3032 s[ 0 ] = '\0'; 3033 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 3034 kDebugFlagsNoByteCount, s, sizeof( s ) ); 3035 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3036 3037 s[ 0 ] = '\0'; 3038 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, "\x41\x62\x43\x64", "\x41\x62\x43\x64", 4, // 'AbCd' 3039 kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine | 3040 kDebugFlagsNo32BitSeparator | kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount, 3041 s, sizeof( s ) ); 3042 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3043 3044 s[ 0 ] = '\0'; 3045 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 3046 kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoASCII | kDebugFlagsNoNewLine | 3047 kDebugFlags16BitSeparator | kDebugFlagsNo32BitSeparator | 3048 kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount, s, sizeof( s ) ); 3049 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3050 3051 s[ 0 ] = '\0'; 3052 DebugHexDump( kDebugLevelMax, 8, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), kDebugFlagsNone, s, sizeof( s ) ); 3053 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3054 3055 // dlog's 3056 3057 dlog( kDebugLevelNotice, "dlog\n" ); 3058 dlog( kDebugLevelNotice, "dlog integer: %d\n", 123 ); 3059 dlog( kDebugLevelNotice, "dlog string: \"%s\"\n", "test string" ); 3060 dlogmem( kDebugLevelNotice, data, sizeof( data ) ); 3061 3062 // Done 3063 3064 DebugPrintF( kDebugLevelMax, "\n\nALL TESTS DONE\n\n" ); 3065 err = kNoErr; 3066 3067 exit: 3068 if( err ) 3069 { 3070 DebugPrintF( kDebugLevelMax, "\n\n### TEST FAILED ###\n\n" ); 3071 } 3072 return( err ); 3073 } 3074 3075 #endif // DEBUG 3076