1 /* Copyright (c) 2017 Apple Inc. All rights reserved. */
4 #include <dispatch/dispatch.h>
9 #include <sys/syscall.h>
11 #include <mach/mach_time.h>
12 #include <sys/stackshot.h>
13 #include <sys/types.h>
14 #include <kern/debug.h>
18 #include <kern/kcdata.h>
21 stackshot_get_mach_absolute_time(void *buffer
, uint32_t size
)
23 kcdata_iter_t iter
= kcdata_iter_find_type(kcdata_iter(buffer
, size
), KCDATA_TYPE_MACH_ABSOLUTE_TIME
);
24 if (!kcdata_iter_valid(iter
) || kcdata_iter_size(iter
) < sizeof(uint64_t)) {
25 fprintf(stderr
, "bad kcdata\n");
28 return *(uint64_t *)kcdata_iter_payload(iter
);
31 static void usage(char **argv
)
33 fprintf (stderr
, "usage: %s [-d] [-t] >file\n", argv
[0]);
34 fprintf (stderr
, " -d : take delta stackshot\n");
35 fprintf (stderr
, " -b : get bootprofile\n");
36 fprintf (stderr
, " -c : get coalition data\n");
37 fprintf (stderr
, " -i : get instructions and cycles\n");
38 fprintf (stderr
, " -t : enable tailspin mode\n");
39 fprintf (stderr
, " -g : get thread group data\n");
40 fprintf (stderr
, " -s : fork a sleep process\n");
41 fprintf (stderr
, " -L : disable loadinfo\n");
42 fprintf (stderr
, " -k : active kernel threads only\n");
43 fprintf (stderr
, " -I : disable io statistics\n");
44 fprintf (stderr
, " -S : stress test: while(1) stackshot; \n");
45 fprintf (stderr
, " -p PID : target a pid\n");
46 fprintf (stderr
, " -E : grab existing kernel buffer\n");
58 execlp("sleep", "sleep", "30", NULL
);
65 int main(int argc
, char **argv
) {
68 uint32_t active_kernel_threads_only
= 0;
69 uint32_t tailspin
= 0;
70 uint32_t bootprofile
= 0;
71 uint32_t thread_group
= 0;
72 uint32_t coalition
= 0;
73 uint32_t instrs_cycles
= 0;
75 uint32_t loadinfo
= STACKSHOT_SAVE_LOADINFO
| STACKSHOT_SAVE_KEXT_LOADINFO
;
76 boolean_t delta
= FALSE
;
77 boolean_t sleep
= FALSE
;
78 boolean_t stress
= FALSE
;
82 while ((c
= getopt(argc
, argv
, "SgIikbcLdtsp:E")) != EOF
) {
85 iostats
|= STACKSHOT_NO_IO_STATS
;
88 active_kernel_threads_only
|= STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY
;
89 loadinfo
&= ~STACKSHOT_SAVE_LOADINFO
;
92 bootprofile
|= STACKSHOT_GET_BOOT_PROFILE
;
95 coalition
|= STACKSHOT_SAVE_JETSAM_COALITIONS
;
98 instrs_cycles
|= STACKSHOT_INSTRS_CYCLES
;
104 thread_group
|= STACKSHOT_THREAD_GROUP
;
107 tailspin
|= STACKSHOT_TAILSPIN
;
122 flags
= flags
| STACKSHOT_RETRIEVE_EXISTING_BUFFER
;
132 if (thread_group
&& delta
) {
133 fprintf(stderr
, "stackshot does not support delta snapshots with thread groups\n");
144 void * config
= stackshot_config_create();
146 perror("stackshot_config_create");
149 flags
= flags
| loadinfo
| STACKSHOT_SAVE_IMP_DONATION_PIDS
| STACKSHOT_GET_DQ
| STACKSHOT_KCDATA_FORMAT
|
150 tailspin
| bootprofile
| active_kernel_threads_only
| iostats
| thread_group
| coalition
| instrs_cycles
;
152 int err
= stackshot_config_set_flags(config
, flags
);
154 perror("stackshot_config_set_flags");
159 int err
= stackshot_config_set_pid(config
, pid
);
161 perror("stackshot_config_set_flags");
166 err
= stackshot_capture_with_config(config
);
168 perror("stackshot_capture_with_config");
172 void *buf
= stackshot_config_get_stackshot_buffer(config
);
174 perror("stackshot_config_get_stackshot_buffer");
178 uint32_t size
= stackshot_config_get_stackshot_size(config
);
181 // output the original somewhere?
183 uint64_t time
= stackshot_get_mach_absolute_time(buf
, size
);
185 err
= stackshot_config_dealloc_buffer(config
);
188 flags
|= STACKSHOT_COLLECT_DELTA_SNAPSHOT
;
189 int err
= stackshot_config_set_flags(config
, flags
);
191 perror("stackshot_config_set_flags");
195 err
= stackshot_config_set_delta_timestamp(config
, time
);
197 perror("stackshot_config_delta_timestamp");
206 err
= stackshot_capture_with_config(config
);
208 perror("stackshot_capture_with_config");
212 buf
= stackshot_config_get_stackshot_buffer(config
);
214 perror("stackshot_config_get_stackshot_buffer");
218 size
= stackshot_config_get_stackshot_size(config
);
226 stackshot_config_dealloc(config
);
232 fwrite(buf
, size
, 1, stdout
);