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