2  * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29 /* Collect kernel callstacks */ 
  31 #include <mach/mach_types.h> 
  32 #include <machine/machine_routines.h>  /* XXX: remove me */ 
  33 #include <kern/thread.h> 
  35 #include <chud/chud_xnu.h> 
  37 #include <kperf/buffer.h> 
  38 #include <kperf/context.h> 
  39 #include <kperf/callstack.h> 
  40 #include <kperf/ast.h> 
  43 callstack_sample( struct callstack 
*cs
,  
  44                   struct kperf_context 
*context
, 
  48         mach_msg_type_number_t nframes
; /* WTF with the type? */ 
  52                 code 
= PERF_CS_USAMPLE
; 
  54                 code 
= PERF_CS_KSAMPLE
; 
  56         BUF_INFO1( code
, (uintptr_t)context
->cur_thread 
); 
  58         /* fill out known flags */ 
  62                 cs
->flags 
|= CALLSTACK_KERNEL
; 
  64                 cs
->flags 
|= CALLSTACK_64BIT
; 
  69                 /* FIXME: detect 32 vs 64-bit? */ 
  72         /* collect the callstack */ 
  73         nframes 
= MAX_CALLSTACK_FRAMES
; 
  74         kr 
= chudxnu_thread_get_callstack64_kperf( context
->cur_thread
,  
  79         /* check for overflow */ 
  80         if( kr 
== KERN_SUCCESS 
) 
  82                 cs
->flags 
|= CALLSTACK_VALID
; 
  83                 cs
->nframes 
= nframes
; 
  85         else if( kr 
== KERN_RESOURCE_SHORTAGE 
) 
  87                 /* FIXME: more here */ 
  88                 cs
->flags 
|= CALLSTACK_TRUNCATED
; 
  89                 cs
->flags 
|= CALLSTACK_VALID
; 
  90                 cs
->nframes 
= nframes
; 
  94                 BUF_INFO2(PERF_CS_ERROR
, ERR_GETSTACK
, kr
); 
  98         if( cs
->nframes 
>= MAX_CALLSTACK_FRAMES 
) 
 101                 BUF_INFO1(PERF_CS_ERROR
, ERR_FRAMES
); 
 108 kperf_kcallstack_sample( struct callstack 
*cs
, struct kperf_context 
*context 
) 
 110         callstack_sample( cs
, context
, 0 ); 
 114 kperf_ucallstack_sample( struct callstack 
*cs
, struct kperf_context 
*context 
) 
 116         callstack_sample( cs
, context
, 1 ); 
 120 callstack_log( struct callstack 
*cs
, uint32_t hcode
, uint32_t dcode 
) 
 122         unsigned int i
, j
, n
, of 
= 4; 
 124         /* Header on the stack */ 
 125         BUF_DATA2( hcode
, cs
->flags
, cs
->nframes 
); 
 127         /* look for how many batches of 4 */ 
 129         of 
= cs
->nframes 
% 4; 
 133         /* print all the stack data, and zero the overflow */ 
 134         for( i 
= 0; i 
< n
; i
++ ) 
 136 #define SCRUB_FRAME(x) (((x)<cs->nframes)?cs->frames[x]:0) 
 148 kperf_kcallstack_log( struct callstack 
*cs 
) 
 150         callstack_log( cs
, PERF_CS_KHDR
, PERF_CS_KDATA 
); 
 154 kperf_ucallstack_log( struct callstack 
*cs 
) 
 156         callstack_log( cs
, PERF_CS_UHDR
, PERF_CS_UDATA 
); 
 160 kperf_ucallstack_pend( struct kperf_context 
* context 
) 
 162         return kperf_ast_pend( context
->cur_thread
, T_AST_CALLSTACK
, 
 166 //      kr = chudxnu_thread_get_callstack(context->generic->threadID,  
 167 //              (uint32_t*)frames, &frameCount, !collectingSupervisorStack);