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